1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 08:13:31 +08:00

Fix overriding control points incorrectly

This commit is contained in:
smoogipoo 2020-04-21 14:19:05 +09:00
parent ea77fc222d
commit 72fb34f82c
2 changed files with 20 additions and 15 deletions

View File

@ -241,6 +241,11 @@ namespace osu.Game.Tests.Beatmaps.Formats
{ {
var controlPoints = decoder.Decode(stream).ControlPointInfo; var controlPoints = decoder.Decode(stream).ControlPointInfo;
Assert.That(controlPoints.TimingPoints.Count, Is.EqualTo(4));
Assert.That(controlPoints.DifficultyPoints.Count, Is.EqualTo(3));
Assert.That(controlPoints.EffectPoints.Count, Is.EqualTo(3));
Assert.That(controlPoints.SamplePoints.Count, Is.EqualTo(3));
Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1));
Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1));

View File

@ -386,17 +386,10 @@ namespace osu.Game.Beatmaps.Formats
SampleVolume = sampleVolume, SampleVolume = sampleVolume,
CustomSampleBank = customSampleBank, CustomSampleBank = customSampleBank,
}, timingChange); }, timingChange);
// To handle the scenario where a non-timing line shares the same time value as a subsequent timing line but
// appears earlier in the file, we buffer non-timing control points and rewrite them *after* control points from the timing line
// with the same time value (allowing them to overwrite as necessary).
//
// The expected outcome is that we prefer the non-timing line's adjustments over the timing line's adjustments when time is equal.
if (timingChange)
flushPendingPoints();
} }
private readonly List<ControlPoint> pendingControlPoints = new List<ControlPoint>(); private readonly List<ControlPoint> pendingControlPoints = new List<ControlPoint>();
private readonly HashSet<Type> pendingControlPointTypes = new HashSet<Type>();
private double pendingControlPointsTime; private double pendingControlPointsTime;
private void addControlPoint(double time, ControlPoint point, bool timingChange) private void addControlPoint(double time, ControlPoint point, bool timingChange)
@ -405,21 +398,28 @@ namespace osu.Game.Beatmaps.Formats
flushPendingPoints(); flushPendingPoints();
if (timingChange) if (timingChange)
{ pendingControlPoints.Insert(0, point);
beatmap.ControlPointInfo.Add(time, point); else
return;
}
pendingControlPoints.Add(point); pendingControlPoints.Add(point);
pendingControlPointsTime = time; pendingControlPointsTime = time;
} }
private void flushPendingPoints() private void flushPendingPoints()
{ {
foreach (var p in pendingControlPoints) // Changes from non-timing-points are added to the end of the list (see addControlPoint()) and should override any changes from timing-points (added to the start of the list).
beatmap.ControlPointInfo.Add(pendingControlPointsTime, p); for (int i = pendingControlPoints.Count - 1; i >= 0; i--)
{
var type = pendingControlPoints[i].GetType();
if (pendingControlPointTypes.Contains(type))
continue;
pendingControlPointTypes.Add(type);
beatmap.ControlPointInfo.Add(pendingControlPointsTime, pendingControlPoints[i]);
}
pendingControlPoints.Clear(); pendingControlPoints.Clear();
pendingControlPointTypes.Clear();
} }
private void handleHitObject(string line) private void handleHitObject(string line)