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

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

View File

@ -12,6 +12,7 @@ using osu.Framework.Allocation;
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 @@ namespace osu.Game.Online.Spectator
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 @@ namespace osu.Game.Online.Spectator
});
}
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 @@ namespace osu.Game.Online.Spectator
private Task? lastSend;
private int totalBundledFrames;
private const int max_pending_frames = 30;
protected override void Update()
@ -246,20 +266,6 @@ namespace osu.Game.Online.Spectator
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 @@ namespace osu.Game.Online.Spectator
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;