From 4727aeda012f6c5f00f500d0eaf4c05ba8bbc58c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 31 Jan 2022 18:32:17 +0900 Subject: [PATCH] Give last bundled replay frame the frame header --- .../Visual/Gameplay/TestSceneSpectator.cs | 16 ++++++++++++++++ osu.Game/Online/Spectator/SpectatorClient.cs | 3 +++ osu.Game/Rulesets/Replays/ReplayFrame.cs | 13 +++++++++++++ osu.Game/Screens/Play/SpectatorPlayer.cs | 1 + 4 files changed, 33 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 917b3c89a8..a7b9d45f7a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -218,6 +218,22 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("last received frame has time = 1000", () => spectatorClient.LastReceivedUserFrames.First().Value.Time == 1000); } + [Test] + public void TestFinalFrameInBundleHasHeader() + { + FrameDataBundle lastBundle = null; + + AddStep("bind to client", () => spectatorClient.OnNewFrames += (_, bundle) => lastBundle = bundle); + + start(-1234); + sendFrames(); + finish(); + + AddUntilStep("bundle received", () => lastBundle != null); + AddAssert("first frame does not have header", () => lastBundle.Frames[0].Header == null); + AddAssert("last frame has header", () => lastBundle.Frames[^1].Header != null); + } + 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 fddb94fad7..67aa75727d 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -129,6 +129,9 @@ namespace osu.Game.Online.Spectator Task ISpectatorClient.UserSentFrames(int userId, FrameDataBundle data) { + if (data.Frames.Count > 0) + data.Frames[^1].Header = data.Header; + Schedule(() => OnNewFrames?.Invoke(userId, data)); return Task.CompletedTask; diff --git a/osu.Game/Rulesets/Replays/ReplayFrame.cs b/osu.Game/Rulesets/Replays/ReplayFrame.cs index 7de53211a2..2b67b60d8f 100644 --- a/osu.Game/Rulesets/Replays/ReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/ReplayFrame.cs @@ -1,16 +1,29 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +#nullable enable + using MessagePack; +using osu.Game.Online.Spectator; namespace osu.Game.Rulesets.Replays { [MessagePackObject] public class ReplayFrame { + /// + /// The time at which this takes place. + /// [Key(0)] public double Time; + /// + /// A containing the state of a play after this takes place. + /// May be omitted where exact per-frame accuracy is not required. + /// + [IgnoreMember] + public FrameHeader? Header; + public ReplayFrame() { } diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs index d42643c416..c415041081 100644 --- a/osu.Game/Screens/Play/SpectatorPlayer.cs +++ b/osu.Game/Screens/Play/SpectatorPlayer.cs @@ -72,6 +72,7 @@ namespace osu.Game.Screens.Play var convertedFrame = (ReplayFrame)convertibleFrame; convertedFrame.Time = frame.Time; + convertedFrame.Header = frame.Header; score.Replay.Frames.Add(convertedFrame); }