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);