1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 21:12:55 +08:00

Delay map completion one frame after the last judgment

This is a workaround of a timing issue.
KeyCounter is disabled while break time (`HasCompleted == true`).
When the last keypress is exactly at the same time the map ends, the last frame was considered in a break time while forward play but considered not in a break time while rewinding. This inconsistency made the last keypress not decremented in the key counter when a replay is rewound.
The situation regularly happens in osu!standard because the map ends right after the player hits the last hit circle. It was caught by `TestSceneGameplayRewinding`.

This commit makes the update of the map completion delayed one frame. The problematic keypress frame is now processed strictly before the map completion, and the map completion status is correctly rewound before the keypress frame.
This commit is contained in:
ekrctb 2021-04-13 14:29:47 +09:00
parent 38d10755cb
commit d0f30b7b42

View File

@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.Scoring
/// </summary> /// </summary>
public int JudgedHits { get; private set; } public int JudgedHits { get; private set; }
private JudgementResult lastAppliedResult;
private readonly BindableBool hasCompleted = new BindableBool(); private readonly BindableBool hasCompleted = new BindableBool();
/// <summary> /// <summary>
@ -53,12 +55,11 @@ namespace osu.Game.Rulesets.Scoring
public void ApplyResult(JudgementResult result) public void ApplyResult(JudgementResult result)
{ {
JudgedHits++; JudgedHits++;
lastAppliedResult = result;
ApplyResultInternal(result); ApplyResultInternal(result);
NewJudgement?.Invoke(result); NewJudgement?.Invoke(result);
updateHasCompleted();
} }
/// <summary> /// <summary>
@ -69,8 +70,6 @@ namespace osu.Game.Rulesets.Scoring
{ {
JudgedHits--; JudgedHits--;
updateHasCompleted();
RevertResultInternal(result); RevertResultInternal(result);
} }
@ -134,6 +133,10 @@ namespace osu.Game.Rulesets.Scoring
} }
} }
private void updateHasCompleted() => hasCompleted.Value = JudgedHits == MaxHits; protected override void Update()
{
base.Update();
hasCompleted.Value = JudgedHits == MaxHits && (JudgedHits == 0 || lastAppliedResult.TimeAbsolute < Clock.CurrentTime);
}
} }
} }