Remove all usage of `LegacyDifficultyControlPoint`

This commit is contained in:
Dean Herbert 2023-09-07 17:41:28 +09:00
parent 4d12678c9d
commit b34a36f6ce
8 changed files with 46 additions and 83 deletions

View File

@ -10,10 +10,10 @@
using osu.Framework.Extensions.EnumExtensions;
using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Utils;
namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
@ -50,10 +50,11 @@ public DistanceObjectPatternGenerator(LegacyRandom random, HitObject hitObject,
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(hitObject.StartTime);
double beatLength;
if (hitObject.LegacyBpmMultiplier.HasValue)
beatLength = timingPoint.BeatLength * hitObject.LegacyBpmMultiplier.Value;
else if (hitObject is IHasSliderVelocity hasSliderVelocity)
beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocityMultiplier;
if (hitObject is IHasSliderVelocity hasSliderVelocity)
{
beatLength = timingPoint.BeatLength / hasSliderVelocity.GetPrecisionAdjustedSliderVelocityMultiplier(ManiaRuleset.SHORT_NAME);
}
else
beatLength = timingPoint.BeatLength;

View File

@ -186,10 +186,9 @@ private bool shouldConvertSliderToHits(HitObject obj, IBeatmap beatmap, IHasDist
TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(obj.StartTime);
double beatLength;
if (obj.LegacyBpmMultiplier.HasValue)
beatLength = timingPoint.BeatLength * obj.LegacyBpmMultiplier.Value;
else if (obj is IHasSliderVelocity hasSliderVelocity)
beatLength = timingPoint.BeatLength / hasSliderVelocity.SliderVelocityMultiplier;
if (obj is IHasSliderVelocity hasSliderVelocity)
beatLength = timingPoint.BeatLength / hasSliderVelocity.GetPrecisionAdjustedSliderVelocityMultiplier(TaikoRuleset.SHORT_NAME);
else
beatLength = timingPoint.BeatLength;

View File

@ -1025,8 +1025,8 @@ public void TestNaNControlPoints()
Assert.That(controlPoints.DifficultyPointAt(3000).SliderVelocity, Is.EqualTo(1));
#pragma warning disable 618
Assert.That(((LegacyBeatmapDecoder.LegacyDifficultyControlPoint)controlPoints.DifficultyPointAt(2000)).GenerateTicks, Is.False);
Assert.That(((LegacyBeatmapDecoder.LegacyDifficultyControlPoint)controlPoints.DifficultyPointAt(3000)).GenerateTicks, Is.True);
Assert.That(controlPoints.DifficultyPointAt(2000).GenerateTicks, Is.False);
Assert.That(controlPoints.DifficultyPointAt(3000).GenerateTicks, Is.True);
#pragma warning restore 618
}
}

View File

@ -28,6 +28,12 @@ public class DifficultyControlPoint : ControlPoint, IEquatable<DifficultyControl
MaxValue = 10
};
/// <summary>
/// Whether or not slider ticks should be generated at this control point.
/// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991).
/// </summary>
public bool GenerateTicks { get; set; } = true;
public override Color4 GetRepresentingColour(OsuColour colours) => colours.Lime1;
/// <summary>
@ -41,11 +47,13 @@ public double SliderVelocity
public override bool IsRedundant(ControlPoint? existing)
=> existing is DifficultyControlPoint existingDifficulty
&& GenerateTicks == existingDifficulty.GenerateTicks
&& SliderVelocity == existingDifficulty.SliderVelocity;
public override void CopyFrom(ControlPoint other)
{
SliderVelocity = ((DifficultyControlPoint)other).SliderVelocity;
GenerateTicks = ((DifficultyControlPoint)other).GenerateTicks;
base.CopyFrom(other);
}
@ -56,8 +64,10 @@ public override bool Equals(ControlPoint? other)
public bool Equals(DifficultyControlPoint? other)
=> base.Equals(other)
&& GenerateTicks == other.GenerateTicks
&& SliderVelocity == other.SliderVelocity;
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), SliderVelocity);
// ReSharper disable once NonReadonlyMemberInGetHashCode
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), SliderVelocity, GenerateTicks);
}
}

View File

@ -103,12 +103,8 @@ private void applyDefaults(HitObject hitObject)
{
DifficultyControlPoint difficultyControlPoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.DifficultyPointAt(hitObject.StartTime) ?? DifficultyControlPoint.DEFAULT;
if (difficultyControlPoint is LegacyDifficultyControlPoint legacyDifficultyControlPoint)
{
hitObject.LegacyBpmMultiplier = legacyDifficultyControlPoint.BpmMultiplier;
if (hitObject is IHasGenerateTicks hasGenerateTicks)
hasGenerateTicks.GenerateTicks = legacyDifficultyControlPoint.GenerateTicks;
}
if (hitObject is IHasGenerateTicks hasGenerateTicks)
hasGenerateTicks.GenerateTicks = difficultyControlPoint.GenerateTicks;
if (hitObject is IHasSliderVelocity hasSliderVelocity)
hasSliderVelocity.SliderVelocityMultiplier = difficultyControlPoint.SliderVelocity;
@ -497,8 +493,9 @@ private void handleTimingPoint(string line)
int onlineRulesetID = beatmap.BeatmapInfo.Ruleset.OnlineID;
addControlPoint(time, new LegacyDifficultyControlPoint(onlineRulesetID, beatLength)
addControlPoint(time, new DifficultyControlPoint
{
GenerateTicks = !double.IsNaN(beatLength),
SliderVelocity = speedMultiplier,
}, timingChange);

View File

@ -163,63 +163,6 @@ public enum Section
Mania,
}
[Obsolete("Do not use unless you're a legacy ruleset and 100% sure.")]
public class LegacyDifficultyControlPoint : DifficultyControlPoint, IEquatable<LegacyDifficultyControlPoint>
{
/// <summary>
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
/// DO NOT USE THIS UNLESS 100% SURE.
/// </summary>
public double BpmMultiplier { get; private set; }
/// <summary>
/// Whether or not slider ticks should be generated at this control point.
/// This exists for backwards compatibility with maps that abuse NaN slider velocity behavior on osu!stable (e.g. /b/2628991).
/// </summary>
public bool GenerateTicks { get; private set; } = true;
public LegacyDifficultyControlPoint(int rulesetId, double beatLength)
: this()
{
// Note: In stable, the division occurs on floats, but with compiler optimisations turned on actually seems to occur on doubles via some .NET black magic (possibly inlining?).
if (rulesetId == 1 || rulesetId == 3)
BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100.0 : 1;
else
BpmMultiplier = beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 1000) / 100.0 : 1;
GenerateTicks = !double.IsNaN(beatLength);
}
public LegacyDifficultyControlPoint()
{
SliderVelocityBindable.Precision = double.Epsilon;
}
public override bool IsRedundant(ControlPoint? existing)
=> base.IsRedundant(existing)
&& GenerateTicks == ((existing as LegacyDifficultyControlPoint)?.GenerateTicks ?? true);
public override void CopyFrom(ControlPoint other)
{
base.CopyFrom(other);
BpmMultiplier = ((LegacyDifficultyControlPoint)other).BpmMultiplier;
GenerateTicks = ((LegacyDifficultyControlPoint)other).GenerateTicks;
}
public override bool Equals(ControlPoint? other)
=> other is LegacyDifficultyControlPoint otherLegacyDifficultyControlPoint
&& Equals(otherLegacyDifficultyControlPoint);
public bool Equals(LegacyDifficultyControlPoint? other)
=> base.Equals(other)
&& BpmMultiplier == other.BpmMultiplier
&& GenerateTicks == other.GenerateTicks;
// ReSharper disable twice NonReadonlyMemberInGetHashCode
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), BpmMultiplier, GenerateTicks);
}
internal class LegacySampleControlPoint : SampleControlPoint, IEquatable<LegacySampleControlPoint>
{
public int CustomSampleBank;

View File

@ -76,12 +76,6 @@ public IList<HitSampleInfo> Samples
/// </summary>
public virtual IList<HitSampleInfo> AuxiliarySamples => ImmutableList<HitSampleInfo>.Empty;
/// <summary>
/// Legacy BPM multiplier that introduces floating-point errors for rulesets that depend on it.
/// DO NOT USE THIS UNLESS 100% SURE.
/// </summary>
public double? LegacyBpmMultiplier { get; set; }
/// <summary>
/// Whether this <see cref="HitObject"/> is in Kiai time.
/// </summary>

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Bindables;
namespace osu.Game.Rulesets.Objects.Types
@ -16,5 +17,23 @@ public interface IHasSliderVelocity
double SliderVelocityMultiplier { get; set; }
BindableNumber<double> SliderVelocityMultiplierBindable { get; }
/// <summary>
/// Introduces floating-point errors for rulesets that depend on it.
/// </summary>
public double GetPrecisionAdjustedSliderVelocityMultiplier(string rulesetShortName)
{
double beatLength = -100 / SliderVelocityMultiplier;
switch (rulesetShortName)
{
case "taiko":
case "mania":
return 1 / (beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 10000) / 100.0 : 1);
default:
return 1 / (beatLength < 0 ? Math.Clamp((float)-beatLength, 10, 1000) / 100.0 : 1);
}
}
}
}