Fix frames potentially getting lost due to non-matching `Schedule` usage

This commit is contained in:
Dean Herbert 2022-02-24 00:59:25 +09:00
parent 260cf793fe
commit 694c6ad872
1 changed files with 24 additions and 14 deletions

View File

@ -12,6 +12,7 @@
using osu.Framework.Bindables;
using osu.Framework.Development;
using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Replays.Legacy;
@ -156,6 +157,8 @@ public void BeginPlaying(GameplayState state, Score score)
IsPlaying = true;
totalBundledFrames = 0;
// transfer state at point of beginning play
currentState.BeatmapID = score.ScoreInfo.BeatmapInfo.OnlineID;
currentState.RulesetID = score.ScoreInfo.RulesetID;
@ -169,6 +172,21 @@ public void BeginPlaying(GameplayState state, Score score)
});
}
public void HandleFrame(ReplayFrame frame) => Schedule(() =>
{
if (!IsPlaying)
{
Logger.Log($"Frames arrived at {nameof(SpectatorClient)} outside of gameplay scope and will be ignored.");
return;
}
if (frame is IConvertibleReplayFrame convertible)
pendingFrames.Enqueue(convertible.ToLegacy(currentBeatmap));
if (pendingFrames.Count > max_pending_frames)
purgePendingFrames();
});
public void EndPlaying(GameplayState state)
{
// This method is most commonly called via Dispose(), which is can be asynchronous (via the AsyncDisposalQueue).
@ -236,6 +254,8 @@ public void StopWatchingUser(int userId)
private Task? lastSend;
private int totalBundledFrames;
private const int max_pending_frames = 30;
protected override void Update()
@ -246,20 +266,6 @@ protected override void Update()
purgePendingFrames();
}
public void HandleFrame(ReplayFrame frame)
{
Debug.Assert(ThreadSafety.IsUpdateThread);
if (!IsPlaying)
return;
if (frame is IConvertibleReplayFrame convertible)
pendingFrames.Enqueue(convertible.ToLegacy(currentBeatmap));
if (pendingFrames.Count > max_pending_frames)
purgePendingFrames();
}
private void purgePendingFrames()
{
if (pendingFrames.Count == 0)
@ -270,6 +276,10 @@ private void purgePendingFrames()
var frames = pendingFrames.ToArray();
var bundle = new FrameDataBundle(currentScore.ScoreInfo, frames);
totalBundledFrames += frames.Length;
Console.WriteLine($"Purging {pendingFrames.Count} frames (total {totalBundledFrames})");
pendingFrames.Clear();
lastPurgeTime = Time.Current;