From bd1f38cc3ef41c0ca8bbd586c81b1cbf8b6a6d9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 26 Jun 2020 23:21:44 +0900 Subject: [PATCH] Fix crash due to unsafe mod deserialisation --- .../Online/TestAPIModSerialization.cs | 59 ++++++++++++++++++- osu.Game/Rulesets/Mods/ModTimeRamp.cs | 4 +- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Online/TestAPIModSerialization.cs b/osu.Game.Tests/Online/TestAPIModSerialization.cs index d9318aa822..5948582d77 100644 --- a/osu.Game.Tests/Online/TestAPIModSerialization.cs +++ b/osu.Game.Tests/Online/TestAPIModSerialization.cs @@ -49,9 +49,32 @@ namespace osu.Game.Tests.Online Assert.That(converted.TestSetting.Value, Is.EqualTo(2)); } + [Test] + public void TestDeserialiseTimeRampMod() + { + // Create the mod with values different from default. + var apiMod = new APIMod(new TestModTimeRamp + { + AdjustPitch = { Value = false }, + InitialRate = { Value = 1.25 }, + FinalRate = { Value = 0.25 } + }); + + var deserialised = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(apiMod)); + var converted = (TestModTimeRamp)deserialised.ToMod(new TestRuleset()); + + Assert.That(converted.AdjustPitch.Value, Is.EqualTo(false)); + Assert.That(converted.InitialRate.Value, Is.EqualTo(1.25)); + Assert.That(converted.FinalRate.Value, Is.EqualTo(0.25)); + } + private class TestRuleset : Ruleset { - public override IEnumerable GetModsFor(ModType type) => new[] { new TestMod() }; + public override IEnumerable GetModsFor(ModType type) => new Mod[] + { + new TestMod(), + new TestModTimeRamp(), + }; public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => throw new System.NotImplementedException(); @@ -78,5 +101,39 @@ namespace osu.Game.Tests.Online Precision = 0.01, }; } + + private class TestModTimeRamp : ModTimeRamp + { + public override string Name => "Test Mod"; + public override string Acronym => "TMTR"; + public override double ScoreMultiplier => 1; + + [SettingSource("Initial rate", "The starting speed of the track")] + public override BindableNumber InitialRate { get; } = new BindableDouble + { + MinValue = 1, + MaxValue = 2, + Default = 1.5, + Value = 1.5, + Precision = 0.01, + }; + + [SettingSource("Final rate", "The speed increase to ramp towards")] + public override BindableNumber FinalRate { get; } = new BindableDouble + { + MinValue = 0, + MaxValue = 1, + Default = 0.5, + Value = 0.5, + Precision = 0.01, + }; + + [SettingSource("Adjust pitch", "Should pitch be adjusted with speed")] + public override BindableBool AdjustPitch { get; } = new BindableBool + { + Default = true, + Value = true + }; + } } } diff --git a/osu.Game/Rulesets/Mods/ModTimeRamp.cs b/osu.Game/Rulesets/Mods/ModTimeRamp.cs index cbd07efa97..839d97f04e 100644 --- a/osu.Game/Rulesets/Mods/ModTimeRamp.cs +++ b/osu.Game/Rulesets/Mods/ModTimeRamp.cs @@ -89,9 +89,9 @@ namespace osu.Game.Rulesets.Mods private void applyPitchAdjustment(ValueChangedEvent adjustPitchSetting) { // remove existing old adjustment - track.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); + track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange); - track.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); + track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange); } private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue)