From d2d089629881770193a5d2c42f7b4c915e0310d4 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 31 May 2021 19:22:20 +0900 Subject: [PATCH 1/9] Expose GameplayBeatmap and GameplayRuleset from Player --- osu.Game/Screens/Play/Player.cs | 38 +++++++++++------------- osu.Game/Screens/Play/SpectatorPlayer.cs | 16 +++++----- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index a9f3edf049..2258d509b7 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -84,10 +84,6 @@ namespace osu.Game.Screens.Play [Resolved] private ScoreManager scoreManager { get; set; } - private RulesetInfo rulesetInfo; - - private Ruleset ruleset; - [Resolved] private IAPIProvider api { get; set; } @@ -97,6 +93,10 @@ namespace osu.Game.Screens.Play [Resolved] private SpectatorClient spectatorClient { get; set; } + protected Ruleset GameplayRuleset { get; private set; } + + protected GameplayBeatmap GameplayBeatmap { get; private set; } + private Sample sampleRestart; public BreakOverlay BreakOverlay; @@ -145,8 +145,6 @@ namespace osu.Game.Screens.Play Configuration = configuration ?? new PlayerConfiguration(); } - private GameplayBeatmap gameplayBeatmap; - private ScreenSuspensionHandler screenSuspension; private DependencyContainer dependencies; @@ -204,16 +202,16 @@ namespace osu.Game.Screens.Play if (game is OsuGame osuGame) LocalUserPlaying.BindTo(osuGame.LocalUserPlaying); - DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); + DrawableRuleset = GameplayRuleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value); dependencies.CacheAs(DrawableRuleset); - ScoreProcessor = ruleset.CreateScoreProcessor(); + ScoreProcessor = GameplayRuleset.CreateScoreProcessor(); ScoreProcessor.ApplyBeatmap(playableBeatmap); ScoreProcessor.Mods.BindTo(Mods); dependencies.CacheAs(ScoreProcessor); - HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); + HealthProcessor = GameplayRuleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime); HealthProcessor.ApplyBeatmap(playableBeatmap); dependencies.CacheAs(HealthProcessor); @@ -223,16 +221,16 @@ namespace osu.Game.Screens.Play InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime); - AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap)); + AddInternal(GameplayBeatmap = new GameplayBeatmap(playableBeatmap)); AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer)); - dependencies.CacheAs(gameplayBeatmap); + dependencies.CacheAs(GameplayBeatmap); var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin); // the beatmapSkinProvider is used as the fallback source here to allow the ruleset-specific skin implementation // full access to all skin sources. - var rulesetSkinProvider = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); + var rulesetSkinProvider = new SkinProvidingContainer(GameplayRuleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); // load the skinning hierarchy first. // this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources. @@ -247,7 +245,7 @@ namespace osu.Game.Screens.Play // also give the HUD a ruleset container to allow rulesets to potentially override HUD elements (used to disable combo counters etc.) // we may want to limit this in the future to disallow rulesets from outright replacing elements the user expects to be there. - var hudRulesetContainer = new SkinProvidingContainer(ruleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); + var hudRulesetContainer = new SkinProvidingContainer(GameplayRuleset.CreateLegacySkinProvider(beatmapSkinProvider, playableBeatmap)); // add the overlay components as a separate step as they proxy some elements from the above underlay/gameplay components. GameplayClockContainer.Add(hudRulesetContainer.WithChild(createOverlayComponents(Beatmap.Value))); @@ -284,7 +282,7 @@ namespace osu.Game.Screens.Play { HealthProcessor.ApplyResult(r); ScoreProcessor.ApplyResult(r); - gameplayBeatmap.ApplyResult(r); + GameplayBeatmap.ApplyResult(r); }; DrawableRuleset.RevertResult += r => @@ -473,18 +471,18 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Beatmap == null) throw new InvalidOperationException("Beatmap was not loaded"); - rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset; - ruleset = rulesetInfo.CreateInstance(); + var rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset; + GameplayRuleset = rulesetInfo.CreateInstance(); try { - playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Mods.Value); + playable = Beatmap.Value.GetPlayableBeatmap(GameplayRuleset.RulesetInfo, Mods.Value); } catch (BeatmapInvalidForRulesetException) { // A playable beatmap may not be creatable with the user's preferred ruleset, so try using the beatmap's default ruleset rulesetInfo = Beatmap.Value.BeatmapInfo.Ruleset; - ruleset = rulesetInfo.CreateInstance(); + GameplayRuleset = rulesetInfo.CreateInstance(); playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, Mods.Value); } @@ -915,7 +913,7 @@ namespace osu.Game.Screens.Play ScoreInfo = new ScoreInfo { Beatmap = Beatmap.Value.BeatmapInfo, - Ruleset = rulesetInfo, + Ruleset = GameplayRuleset.RulesetInfo, Mods = Mods.Value.ToArray(), } }; @@ -951,7 +949,7 @@ namespace osu.Game.Screens.Play using (var stream = new MemoryStream()) { - new LegacyScoreEncoder(score, gameplayBeatmap.PlayableBeatmap).Encode(stream); + new LegacyScoreEncoder(score, GameplayBeatmap.PlayableBeatmap).Encode(stream); replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr"); } diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index a8125dfded..ad0f05e931 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -16,6 +16,9 @@ namespace osu.Game.Screens.Play { public class SpectatorPlayer : Player { + [Resolved] + private SpectatorClient spectatorClient { get; set; } + private readonly Score score; protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap @@ -25,14 +28,6 @@ namespace osu.Game.Screens.Play this.score = score; } - protected override ResultsScreen CreateResults(ScoreInfo score) - { - return new SpectatorResultsScreen(score); - } - - [Resolved] - private SpectatorClient spectatorClient { get; set; } - [BackgroundDependencyLoader] private void load() { @@ -48,6 +43,11 @@ namespace osu.Game.Screens.Play }); } + protected override ResultsScreen CreateResults(ScoreInfo score) + { + return new SpectatorResultsScreen(score); + } + protected override void PrepareReplay() { DrawableRuleset?.SetReplayScore(score); From 7f24518004854d6e3e0167ac7a42c0e629fcc801 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 31 May 2021 19:24:22 +0900 Subject: [PATCH 2/9] Fix spectator crashing when converting mania replay frames --- osu.Game/Screens/Play/SpectatorPlayer.cs | 37 ++++++++++++++++++++ osu.Game/Screens/Spectate/SpectatorScreen.cs | 29 --------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index ad0f05e931..c5e26bdef6 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -9,6 +9,8 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.Spectator; +using osu.Game.Rulesets.Replays; +using osu.Game.Rulesets.Replays.Types; using osu.Game.Scoring; using osu.Game.Screens.Ranking; @@ -43,6 +45,36 @@ namespace osu.Game.Screens.Play }); } + protected override void LoadComplete() + { + base.LoadComplete(); + + spectatorClient.OnNewFrames += userSentFrames; + } + + private void userSentFrames(int userId, FrameDataBundle bundle) + { + if (userId != score.ScoreInfo.User.Id) + return; + + if (!LoadedBeatmapSuccessfully) + return; + + if (!this.IsCurrentScreen()) + return; + + foreach (var frame in bundle.Frames) + { + IConvertibleReplayFrame convertibleFrame = GameplayRuleset.CreateConvertibleReplayFrame(); + convertibleFrame.FromLegacy(frame, GameplayBeatmap.PlayableBeatmap); + + var convertedFrame = (ReplayFrame)convertibleFrame; + convertedFrame.Time = frame.Time; + + score.Replay.Frames.Add(convertedFrame); + } + } + protected override ResultsScreen CreateResults(ScoreInfo score) { return new SpectatorResultsScreen(score); @@ -67,6 +99,8 @@ namespace osu.Game.Screens.Play public override bool OnExiting(IScreen next) { spectatorClient.OnUserBeganPlaying -= userBeganPlaying; + spectatorClient.OnNewFrames -= userSentFrames; + return base.OnExiting(next); } @@ -85,7 +119,10 @@ namespace osu.Game.Screens.Play base.Dispose(isDisposing); if (spectatorClient != null) + { spectatorClient.OnUserBeganPlaying -= userBeganPlaying; + spectatorClient.OnNewFrames -= userSentFrames; + } } } } diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index 9a20bb58b8..8fc9222f59 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -15,8 +15,6 @@ using osu.Game.Database; using osu.Game.Online.Spectator; using osu.Game.Replays; using osu.Game.Rulesets; -using osu.Game.Rulesets.Replays; -using osu.Game.Rulesets.Replays.Types; using osu.Game.Scoring; using osu.Game.Users; @@ -71,8 +69,6 @@ namespace osu.Game.Screens.Spectate playingUserStates.BindTo(spectatorClient.PlayingUserStates); playingUserStates.BindCollectionChanged(onPlayingUserStatesChanged, true); - spectatorClient.OnNewFrames += userSentFrames; - managerUpdated = beatmaps.ItemUpdated.GetBoundCopy(); managerUpdated.BindValueChanged(beatmapUpdated); @@ -197,29 +193,6 @@ namespace osu.Game.Screens.Spectate Schedule(() => StartGameplay(userId, gameplayState)); } - private void userSentFrames(int userId, FrameDataBundle bundle) - { - if (!userMap.ContainsKey(userId)) - return; - - if (!gameplayStates.TryGetValue(userId, out var gameplayState)) - return; - - // The ruleset instance should be guaranteed to be in sync with the score via ScoreLock. - Debug.Assert(gameplayState.Ruleset != null && gameplayState.Ruleset.RulesetInfo.Equals(gameplayState.Score.ScoreInfo.Ruleset)); - - foreach (var frame in bundle.Frames) - { - IConvertibleReplayFrame convertibleFrame = gameplayState.Ruleset.CreateConvertibleReplayFrame(); - convertibleFrame.FromLegacy(frame, gameplayState.Beatmap.Beatmap); - - var convertedFrame = (ReplayFrame)convertibleFrame; - convertedFrame.Time = frame.Time; - - gameplayState.Score.Replay.Frames.Add(convertedFrame); - } - } - /// /// Invoked when a spectated user's state has changed. /// @@ -260,8 +233,6 @@ namespace osu.Game.Screens.Spectate if (spectatorClient != null) { - spectatorClient.OnNewFrames -= userSentFrames; - foreach (var (userId, _) in userMap) spectatorClient.StopWatchingUser(userId); } From c787c008a50f3a7d623f0af37f49175ffcf71f04 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 31 May 2021 20:21:26 +0900 Subject: [PATCH 3/9] Fix test potentially not waiting for player to load --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index e9894ff469..9606d8c828 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.Gameplay private double currentFrameStableTime => player.ChildrenOfType().First().FrameStableClock.CurrentTime; - private void waitForPlayer() => AddUntilStep("wait for player", () => Stack.CurrentScreen is Player); + private void waitForPlayer() => AddUntilStep("wait for player", () => (Stack.CurrentScreen as Player)?.IsLoaded == true); private void start(int? beatmapId = null) => AddStep("start play", () => testSpectatorClient.StartPlay(streamingUser.Id, beatmapId ?? importedBeatmapId)); From 420df124b5fba03eaf59196b5a2d70f2c973f4c8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jun 2021 17:27:21 +0900 Subject: [PATCH 4/9] Add framestable-bypassing seek for spectator --- .../Visual/Gameplay/TestSceneHitErrorMeter.cs | 1 + osu.Game/Rulesets/UI/DrawableRuleset.cs | 4 ++- osu.Game/Screens/Play/Player.cs | 18 ++++++++++++ osu.Game/Screens/Play/SpectatorPlayer.cs | 28 ++++++++++--------- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 2c5443fe08..ab13095af4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -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 Mods { get; } public override double GameplayStartTime { get; } diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index a2dade2627..0cd5804fd0 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.UI /// /// Whether to enable frame-stable playback. /// - internal bool FrameStablePlayback + internal override bool FrameStablePlayback { get => frameStablePlayback; set @@ -432,6 +432,8 @@ namespace osu.Game.Rulesets.UI /// public abstract IFrameStableClock FrameStableClock { get; } + internal abstract bool FrameStablePlayback { get; set; } + /// /// The mods which are to be applied. /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2258d509b7..f8f9103c89 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -576,6 +576,24 @@ namespace osu.Game.Screens.Play /// The destination time to seek to. public void Seek(double time) => GameplayClockContainer.Seek(time); + /// + /// Seeks to a specific time in gameplay, bypassing frame stability. + /// + /// + /// Intermediate hitobject judgements may not be applied or reverted correctly during this seek. + /// + /// The destination time to seek to. + 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); + } + /// /// Restart gameplay via a parent . /// This can be called from a child screen in order to trigger the restart process. diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index c5e26bdef6..605702c8e2 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . 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; From 3bc81fbb068b478abb16ae49670056a818079844 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jun 2021 17:27:24 +0900 Subject: [PATCH 5/9] Fix spectator tests --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 9606d8c828..6eeb3596a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -76,9 +76,9 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("screen hasn't changed", () => Stack.CurrentScreen is SoloSpectator); start(); - sendFrames(); - waitForPlayer(); + + sendFrames(); AddAssert("ensure frames arrived", () => replayHandler.HasFrames); AddUntilStep("wait for frame starvation", () => replayHandler.WaitingForFrame); @@ -116,12 +116,11 @@ namespace osu.Game.Tests.Visual.Gameplay start(); loadSpectatingScreen(); + waitForPlayer(); AddStep("advance frame count", () => nextFrame = 300); sendFrames(); - waitForPlayer(); - AddUntilStep("playing from correct point in time", () => player.ChildrenOfType().First().FrameStableClock.CurrentTime > 30000); } From 662bbed5d1206ca918d54a803ea52825ade0432d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jun 2021 17:38:51 +0900 Subject: [PATCH 6/9] Fix seeking to gameplay too soon --- osu.Game/Screens/Play/SpectatorPlayer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index 605702c8e2..1e6becff40 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -43,9 +43,9 @@ namespace osu.Game.Screens.Play }); } - protected override void LoadComplete() + protected override void StartGameplay() { - base.LoadComplete(); + base.StartGameplay(); spectatorClient.OnNewFrames += userSentFrames; seekToGameplay(); From be03a2d7d2dfa19a9f8fc1fe43aeb1c00f7c59f5 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jun 2021 17:47:22 +0900 Subject: [PATCH 7/9] Fix multiple calls to seek method potentially not working --- osu.Game/Screens/Play/Player.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 64d5aa6ef7..985eb32cca 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -583,6 +583,8 @@ namespace osu.Game.Screens.Play /// The destination time to seek to. public void Seek(double time) => GameplayClockContainer.Seek(time); + private ScheduledDelegate frameStablePlaybackResetDelegate; + /// /// Seeks to a specific time in gameplay, bypassing frame stability. /// @@ -592,13 +594,16 @@ namespace osu.Game.Screens.Play /// The destination time to seek to. public void NonFrameStableSeek(double time) { + if (frameStablePlaybackResetDelegate?.Cancelled == false && !frameStablePlaybackResetDelegate.Completed) + frameStablePlaybackResetDelegate.RunTask(); + 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); + frameStablePlaybackResetDelegate = ScheduleAfterChildren(() => DrawableRuleset.FrameStablePlayback = wasFrameStable); } /// @@ -931,11 +936,10 @@ namespace osu.Game.Screens.Play /// Creates the player's . /// /// The . - protected virtual Score CreateScore() => - new Score - { - ScoreInfo = new ScoreInfo { User = api.LocalUser.Value }, - }; + protected virtual Score CreateScore() => new Score + { + ScoreInfo = new ScoreInfo { User = api.LocalUser.Value }, + }; /// /// Imports the player's to the local database. From e887807ae7f186b03dad7525aa97b56ab1f586bb Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 3 Jun 2021 18:32:05 +0900 Subject: [PATCH 8/9] Apply review fixes --- osu.Game/Rulesets/UI/DrawableRuleset.cs | 6 +++--- osu.Game/Screens/Play/Player.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/UI/DrawableRuleset.cs b/osu.Game/Rulesets/UI/DrawableRuleset.cs index bd6da52654..2d171eb533 100644 --- a/osu.Game/Rulesets/UI/DrawableRuleset.cs +++ b/osu.Game/Rulesets/UI/DrawableRuleset.cs @@ -68,9 +68,6 @@ namespace osu.Game.Rulesets.UI private bool frameStablePlayback = true; - /// - /// Whether to enable frame-stable playback. - /// internal override bool FrameStablePlayback { get => frameStablePlayback; @@ -425,6 +422,9 @@ namespace osu.Game.Rulesets.UI /// public abstract IFrameStableClock FrameStableClock { get; } + /// + /// Whether to enable frame-stable playback. + /// internal abstract bool FrameStablePlayback { get; set; } /// diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 985eb32cca..a4aaeb5b1f 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -592,7 +592,7 @@ namespace osu.Game.Screens.Play /// Intermediate hitobject judgements may not be applied or reverted correctly during this seek. /// /// The destination time to seek to. - public void NonFrameStableSeek(double time) + internal void NonFrameStableSeek(double time) { if (frameStablePlaybackResetDelegate?.Cancelled == false && !frameStablePlaybackResetDelegate.Completed) frameStablePlaybackResetDelegate.RunTask(); From 009aa994d09eca2508af2f3d4ec4fb73fae3a7f6 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 4 Jun 2021 21:58:07 +0900 Subject: [PATCH 9/9] Fix potential race incorrectly pausing the source clock --- osu.Game/Screens/Play/MasterGameplayClockContainer.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs index fcbc6fae15..3fbb55872b 100644 --- a/osu.Game/Screens/Play/MasterGameplayClockContainer.cs +++ b/osu.Game/Screens/Play/MasterGameplayClockContainer.cs @@ -100,7 +100,13 @@ namespace osu.Game.Screens.Play { // The source is stopped by a frequency fade first. if (isPaused.NewValue) - this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => AdjustableSource.Stop()); + { + this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => + { + if (IsPaused.Value == isPaused.NewValue) + AdjustableSource.Stop(); + }); + } else this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); }