diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs
index 825b60ae5f..5e538126b3 100644
--- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs
+++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs
@@ -12,6 +12,11 @@ namespace osu.Game.Beatmaps.ControlPoints
///
public double Time;
+ ///
+ /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap.
+ ///
+ internal bool AutoGenerated;
+
public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time);
///
diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
index b489b5e6d9..46a6197546 100644
--- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
@@ -374,14 +374,16 @@ namespace osu.Game.Beatmaps.Formats
handleDifficultyControlPoint(new DifficultyControlPoint
{
Time = time,
- SpeedMultiplier = speedMultiplier
+ SpeedMultiplier = speedMultiplier,
+ AutoGenerated = timingChange
});
handleEffectControlPoint(new EffectControlPoint
{
Time = time,
KiaiMode = kiaiMode,
- OmitFirstBarLine = omitFirstBarSignature
+ OmitFirstBarLine = omitFirstBarSignature,
+ AutoGenerated = timingChange
});
handleSampleControlPoint(new LegacySampleControlPoint
@@ -389,7 +391,8 @@ namespace osu.Game.Beatmaps.Formats
Time = time,
SampleBank = stringSampleSet,
SampleVolume = sampleVolume,
- CustomSampleBank = customSampleBank
+ CustomSampleBank = customSampleBank,
+ AutoGenerated = timingChange
});
}
catch (FormatException)
@@ -419,6 +422,11 @@ namespace osu.Game.Beatmaps.Formats
if (newPoint.EquivalentTo(existing))
return;
+ // autogenerated points should not replace non-autogenerated.
+ // this allows for incorrectly ordered timing points to still be correctly handled.
+ if (newPoint.AutoGenerated && !existing.AutoGenerated)
+ return;
+
if (existing.Time == newPoint.Time)
beatmap.ControlPointInfo.DifficultyPoints.Remove(existing);