Bail from score submission if audio playback rate is too far from reality

Closes https://github.com/ppy/osu/issues/23149.
This commit is contained in:
Dean Herbert 2023-12-26 19:20:41 +09:00
parent ef4191fb57
commit 225528d519
No known key found for this signature in database
2 changed files with 63 additions and 0 deletions

View File

@ -8,6 +8,7 @@ using osu.Framework.Audio;
using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
@ -39,6 +40,14 @@ namespace osu.Game.Screens.Play
Precision = 0.1,
};
/// <summary>
/// Whether the audio playback is within acceptable ranges.
/// Will become false if audio playback is not going as expected.
/// </summary>
public IBindable<bool> PlaybackRateValid => playbackRateValid;
private readonly Bindable<bool> playbackRateValid = new Bindable<bool>(true);
private readonly WorkingBeatmap beatmap;
private Track track;
@ -128,6 +137,7 @@ namespace osu.Game.Screens.Play
{
// Safety in case the clock is seeked while stopped.
LastStopTime = null;
elapsedValidationTime = null;
base.Seek(time);
}
@ -197,6 +207,51 @@ namespace osu.Game.Screens.Play
addAdjustmentsToTrack();
}
protected override void Update()
{
base.Update();
checkPlaybackValidity();
}
#region Clock validation (ensure things are running correctly for local gameplay)
private double elapsedGameplayClockTime;
private double? elapsedValidationTime;
private int playbackDiscrepancyCount;
private const int allowed_playback_discrepancies = 5;
private void checkPlaybackValidity()
{
if (GameplayClock.IsRunning)
{
elapsedGameplayClockTime += GameplayClock.ElapsedFrameTime;
elapsedValidationTime ??= elapsedGameplayClockTime;
elapsedValidationTime += GameplayClock.Rate * Time.Elapsed;
if (Math.Abs(elapsedGameplayClockTime - elapsedValidationTime!.Value) > 300)
{
if (playbackDiscrepancyCount++ > allowed_playback_discrepancies)
{
if (playbackRateValid.Value)
{
playbackRateValid.Value = false;
Logger.Log("System audio playback is not working as expected. Some online functionality will not work.\n\nPlease check your audio drivers.", level: LogLevel.Important);
}
}
else
{
Logger.Log($"Playback discrepancy detected ({playbackDiscrepancyCount} of allowed {allowed_playback_discrepancies}): {elapsedGameplayClockTime:N1} vs {elapsedValidationTime:N1}");
}
elapsedValidationTime = null;
}
}
}
#endregion
private bool speedAdjustmentsApplied;
private void addAdjustmentsToTrack()

View File

@ -208,6 +208,14 @@ namespace osu.Game.Screens.Play
private Task submitScore(Score score)
{
var masterClock = GameplayClockContainer as MasterGameplayClockContainer;
if (masterClock?.PlaybackRateValid.Value != true)
{
Logger.Log("Score submission cancelled due to audio playback rate discrepancy.");
return Task.CompletedTask;
}
// token may be null if the request failed but gameplay was still allowed (see HandleTokenRetrievalFailure).
if (token == null)
{