From 397971c6313eff22d645c07d782547a4e7683a2e Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 28 Jan 2022 22:06:34 +0900 Subject: [PATCH 1/4] Change FrameDataBundle.Frames into an IList --- osu.Game/Online/Spectator/FrameDataBundle.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Spectator/FrameDataBundle.cs b/osu.Game/Online/Spectator/FrameDataBundle.cs index 0e59cdf4ce..a4c4972989 100644 --- a/osu.Game/Online/Spectator/FrameDataBundle.cs +++ b/osu.Game/Online/Spectator/FrameDataBundle.cs @@ -20,16 +20,16 @@ namespace osu.Game.Online.Spectator public FrameHeader Header { get; set; } [Key(1)] - public IEnumerable Frames { get; set; } + public IList Frames { get; set; } - public FrameDataBundle(ScoreInfo score, IEnumerable frames) + public FrameDataBundle(ScoreInfo score, IList frames) { Frames = frames; Header = new FrameHeader(score); } [JsonConstructor] - public FrameDataBundle(FrameHeader header, IEnumerable frames) + public FrameDataBundle(FrameHeader header, IList frames) { Header = header; Frames = frames; From 3037a3a7696b7f00cef3820c5c5994949de78622 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 28 Jan 2022 22:26:05 +0900 Subject: [PATCH 2/4] Purge final spectator frames before ending play --- .../Visual/Gameplay/TestSceneSpectator.cs | 18 ++++++++++++++++++ osu.Game/Online/Spectator/SpectatorClient.cs | 10 ++++++++-- .../Visual/Spectator/TestSpectatorClient.cs | 11 +++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 0afd2c76dd..d1a25b07ec 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -15,11 +15,14 @@ using osu.Game.Online.Spectator; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.UI; +using osu.Game.Scoring; using osu.Game.Screens; using osu.Game.Screens.Play; +using osu.Game.Tests.Beatmaps; using osu.Game.Tests.Beatmaps.IO; using osu.Game.Tests.Visual.Multiplayer; using osu.Game.Tests.Visual.Spectator; +using osuTK; namespace osu.Game.Tests.Visual.Gameplay { @@ -200,6 +203,21 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("screen didn't change", () => Stack.CurrentScreen is SoloSpectator); } + [Test] + public void TestFinalFramesPurgedBeforeEndingPlay() + { + AddStep("begin playing", () => spectatorClient.BeginPlaying(new GameplayState(new TestBeatmap(new OsuRuleset().RulesetInfo), new OsuRuleset()), new Score())); + + AddStep("send frames and finish play", () => + { + spectatorClient.HandleFrame(new OsuReplayFrame(1000, Vector2.Zero)); + spectatorClient.EndPlaying(); + }); + + // We can't access API because we're an "online" test. + AddAssert("last received frame has time = 1000", () => spectatorClient.LastReceivedFrame.First().Value.Time == 1000); + } + private OsuFramedReplayInputHandler replayHandler => (OsuFramedReplayInputHandler)Stack.ChildrenOfType().First().ReplayInputHandler; diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 4da9bace70..fddb94fad7 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -167,6 +167,9 @@ namespace osu.Game.Online.Spectator if (!IsPlaying) return; + if (pendingFrames.Count > 0) + purgePendingFrames(true); + IsPlaying = false; currentBeatmap = null; @@ -238,9 +241,12 @@ namespace osu.Game.Online.Spectator purgePendingFrames(); } - private void purgePendingFrames() + private void purgePendingFrames(bool force = false) { - if (lastSend?.IsCompleted == false) + if (lastSend?.IsCompleted == false && !force) + return; + + if (pendingFrames.Count == 0) return; var frames = pendingFrames.ToArray(); diff --git a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs index f206d4f8b0..3f3d0f5b01 100644 --- a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs +++ b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs @@ -14,6 +14,7 @@ using osu.Framework.Utils; using osu.Game.Online.API; using osu.Game.Online.Spectator; using osu.Game.Replays.Legacy; +using osu.Game.Rulesets.Replays; using osu.Game.Scoring; namespace osu.Game.Tests.Visual.Spectator @@ -27,12 +28,22 @@ namespace osu.Game.Tests.Visual.Spectator public override IBindable IsConnected { get; } = new Bindable(true); + public readonly Dictionary LastReceivedFrame = new Dictionary(); private readonly Dictionary userBeatmapDictionary = new Dictionary(); private readonly Dictionary userNextFrameDictionary = new Dictionary(); [Resolved] private IAPIProvider api { get; set; } = null!; + public TestSpectatorClient() + { + OnNewFrames += (i, bundle) => + { + if (PlayingUsers.Contains(i)) + LastReceivedFrame[i] = bundle.Frames[^1]; + }; + } + /// /// Starts play for an arbitrary user. /// From 1253e1ecc1f7ec68f78f7b30878b673b2c37345d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 28 Jan 2022 20:25:12 +0100 Subject: [PATCH 3/4] Replace LINQ `Count()` invocation with count property access --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs index 4790bd44db..90abdf2ba3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorPlayback.cs @@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void onNewFrames(int userId, FrameDataBundle frames) { - Logger.Log($"Received {frames.Frames.Count()} new frames ({string.Join(',', frames.Frames.Select(f => ((int)f.Time).ToString()))})"); + Logger.Log($"Received {frames.Frames.Count} new frames ({string.Join(',', frames.Frames.Select(f => ((int)f.Time).ToString()))})"); foreach (var legacyFrame in frames.Frames) { From 57f793aff0e6f562198b732dea85f9bd8c154dee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 31 Jan 2022 15:12:08 +0900 Subject: [PATCH 4/4] Rename dictionary and make `private` for added safety --- osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs | 2 +- osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index d1a25b07ec..917b3c89a8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -215,7 +215,7 @@ namespace osu.Game.Tests.Visual.Gameplay }); // We can't access API because we're an "online" test. - AddAssert("last received frame has time = 1000", () => spectatorClient.LastReceivedFrame.First().Value.Time == 1000); + AddAssert("last received frame has time = 1000", () => spectatorClient.LastReceivedUserFrames.First().Value.Time == 1000); } private OsuFramedReplayInputHandler replayHandler => diff --git a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs index 3f3d0f5b01..1a1d493249 100644 --- a/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs +++ b/osu.Game/Tests/Visual/Spectator/TestSpectatorClient.cs @@ -28,7 +28,10 @@ namespace osu.Game.Tests.Visual.Spectator public override IBindable IsConnected { get; } = new Bindable(true); - public readonly Dictionary LastReceivedFrame = new Dictionary(); + public IReadOnlyDictionary LastReceivedUserFrames => lastReceivedUserFrames; + + private readonly Dictionary lastReceivedUserFrames = new Dictionary(); + private readonly Dictionary userBeatmapDictionary = new Dictionary(); private readonly Dictionary userNextFrameDictionary = new Dictionary(); @@ -40,7 +43,7 @@ namespace osu.Game.Tests.Visual.Spectator OnNewFrames += (i, bundle) => { if (PlayingUsers.Contains(i)) - LastReceivedFrame[i] = bundle.Frames[^1]; + lastReceivedUserFrames[i] = bundle.Frames[^1]; }; }