diff --git a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj
index 2866508a02..c872af766a 100644
--- a/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj
+++ b/osu.Game.Rulesets.Mania.Tests.Android/osu.Game.Rulesets.Mania.Tests.Android.csproj
@@ -19,6 +19,7 @@
+
diff --git a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj
index d51e541e95..7cfa89b7d1 100644
--- a/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj
+++ b/osu.Game.Rulesets.Mania.Tests.iOS/osu.Game.Rulesets.Mania.Tests.iOS.csproj
@@ -13,6 +13,7 @@
+
diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs
index 92a01f8627..edf36c8c93 100644
--- a/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs
+++ b/osu.Game.Rulesets.Mania.Tests/ManiaBeatmapConversionTest.cs
@@ -27,6 +27,24 @@ namespace osu.Game.Rulesets.Mania.Tests
[TestCase("100374")]
[TestCase("1450162")]
[TestCase("4869637")]
+ [TestCase("1K")]
+ [TestCase("2K")]
+ [TestCase("3K")]
+ [TestCase("4K")]
+ [TestCase("5K")]
+ [TestCase("6K")]
+ [TestCase("7K")]
+ [TestCase("8K")]
+ [TestCase("9K")]
+ [TestCase("10K")]
+ // [TestCase("11K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("12K")]
+ // [TestCase("13K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("14K")]
+ // [TestCase("15K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("16K")]
+ // [TestCase("17K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("18K")]
public void Test(string name) => base.Test(name);
protected override IEnumerable CreateConvertValue(HitObject hitObject)
diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyBeatmapEncoderTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyBeatmapEncoderTest.cs
new file mode 100644
index 0000000000..9e2620bed5
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyBeatmapEncoderTest.cs
@@ -0,0 +1,45 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Framework.IO.Stores;
+using static osu.Game.Tests.Beatmaps.Formats.LegacyBeatmapEncoderTest;
+
+namespace osu.Game.Rulesets.Mania.Tests
+{
+ [TestFixture]
+ public class ManiaLegacyBeatmapEncoderTest
+ {
+ private static readonly DllResourceStore beatmaps_resource_store = new DllResourceStore(typeof(ManiaLegacyBeatmapEncoderTest).Assembly);
+
+ [TestCase("1K")]
+ [TestCase("2K")]
+ [TestCase("3K")]
+ [TestCase("4K")]
+ [TestCase("5K")]
+ [TestCase("6K")]
+ [TestCase("7K")]
+ [TestCase("8K")]
+ [TestCase("9K")]
+ [TestCase("10K")]
+ // [TestCase("11K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("12K")]
+ // [TestCase("13K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("14K")]
+ // [TestCase("15K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("16K")]
+ // [TestCase("17K")] <- See comment in `ManiaBeatmapConverter` ctor for disable reason.
+ [TestCase("18K")]
+ [TestCase("7K+1")]
+ public void TestEncodeDecodeStability(string name)
+ {
+ var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream($"Resources/Testing/Beatmaps/{name}.osu"), beatmaps_resource_store, name);
+ var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
+
+ Sort(decoded.beatmap);
+ Sort(decodedAfterEncode.beatmap);
+
+ CompareBeatmaps(decoded, decodedAfterEncode);
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs
index f6e79114de..baea2bab27 100644
--- a/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs
+++ b/osu.Game.Rulesets.Mania.Tests/Mods/TestSceneManiaModNoRelease.cs
@@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Mods
{
public partial class TestSceneManiaModNoRelease : RateAdjustedBeatmapTestScene
{
+ protected override Ruleset CreateRuleset() => new ManiaRuleset();
+
private const double time_before_head = 250;
private const double time_head = 1500;
private const double time_during_hold_1 = 2500;
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/10K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/10K-expected-conversion.json
new file mode 100644
index 0000000000..8d2d2e662a
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/10K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":511,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/10K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/10K.osu
new file mode 100644
index 0000000000..932f223c44
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/10K.osu
@@ -0,0 +1,46 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:10K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:10
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+25,192,0,1,0,0:0:0:0:
+76,192,125,1,0,0:0:0:0:
+128,192,250,1,0,0:0:0:0:
+179,192,375,1,0,0:0:0:0:
+230,192,500,1,0,0:0:0:0:
+281,192,625,1,0,0:0:0:0:
+332,192,750,1,0,0:0:0:0:
+384,192,875,1,0,0:0:0:0:
+435,192,1000,1,0,0:0:0:0:
+486,192,1125,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/11K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/11K-expected-conversion.json
new file mode 100644
index 0000000000..f1dc1f3fd0
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/11K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":531,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/11K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/11K.osu
new file mode 100644
index 0000000000..34be4e0756
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/11K.osu
@@ -0,0 +1,47 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:11K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:11
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+23,192,0,1,0,0:0:0:0:
+69,192,125,1,0,0:0:0:0:
+116,192,250,1,0,0:0:0:0:
+162,192,375,1,0,0:0:0:0:
+209,192,500,1,0,0:0:0:0:
+256,192,625,1,0,0:0:0:0:
+302,192,750,1,0,0:0:0:0:
+349,192,875,1,0,0:0:0:0:
+395,192,1000,1,0,0:0:0:0:
+442,192,1125,1,0,0:0:0:0:
+488,192,1250,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/12K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/12K-expected-conversion.json
new file mode 100644
index 0000000000..791b42eb68
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/12K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":551,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/12K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/12K.osu
new file mode 100644
index 0000000000..12557dffe2
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/12K.osu
@@ -0,0 +1,48 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:12K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:12
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+21,192,0,1,0,0:0:0:0:
+64,192,125,1,0,0:0:0:0:
+106,192,250,1,0,0:0:0:0:
+149,192,375,1,0,0:0:0:0:
+192,192,500,1,0,0:0:0:0:
+234,192,625,1,0,0:0:0:0:
+277,192,750,1,0,0:0:0:0:
+320,192,875,1,0,0:0:0:0:
+362,192,1000,1,0,0:0:0:0:
+405,192,1125,1,0,0:0:0:0:
+448,192,1250,1,0,0:0:0:0:
+490,192,1375,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/13K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/13K-expected-conversion.json
new file mode 100644
index 0000000000..f25ccac804
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/13K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":571,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/13K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/13K.osu
new file mode 100644
index 0000000000..896dcbca1c
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/13K.osu
@@ -0,0 +1,49 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:13K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:13
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+19,192,0,1,0,0:0:0:0:
+59,192,125,1,0,0:0:0:0:
+98,192,250,1,0,0:0:0:0:
+137,192,375,1,0,0:0:0:0:
+177,192,500,1,0,0:0:0:0:
+216,192,625,1,0,0:0:0:0:
+256,192,750,1,0,0:0:0:0:
+295,192,875,1,0,0:0:0:0:
+334,192,1000,1,0,0:0:0:0:
+374,192,1125,1,0,0:0:0:0:
+413,192,1250,1,0,0:0:0:0:
+452,192,1375,1,0,0:0:0:0:
+492,192,1500,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/14K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/14K-expected-conversion.json
new file mode 100644
index 0000000000..c8cf9d828e
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/14K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":591,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/14K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/14K.osu
new file mode 100644
index 0000000000..b5c74a7e9d
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/14K.osu
@@ -0,0 +1,50 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:14K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:14
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+18,192,0,1,0,0:0:0:0:
+54,192,125,1,0,0:0:0:0:
+91,192,250,1,0,0:0:0:0:
+128,192,375,1,0,0:0:0:0:
+164,192,500,1,0,0:0:0:0:
+201,192,625,1,0,0:0:0:0:
+237,192,750,1,0,0:0:0:0:
+274,192,875,1,0,0:0:0:0:
+310,192,1000,1,0,0:0:0:0:
+347,192,1125,1,0,0:0:0:0:
+384,192,1250,1,0,0:0:0:0:
+420,192,1375,1,0,0:0:0:0:
+457,192,1500,1,0,0:0:0:0:
+493,192,1625,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/15K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/15K-expected-conversion.json
new file mode 100644
index 0000000000..6c81cbbb9e
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/15K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":611,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/15K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/15K.osu
new file mode 100644
index 0000000000..4d17b040ad
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/15K.osu
@@ -0,0 +1,51 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:15K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:15
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+17,192,0,1,0,0:0:0:0:
+51,192,125,1,0,0:0:0:0:
+85,192,250,1,0,0:0:0:0:
+119,192,375,1,0,0:0:0:0:
+153,192,500,1,0,0:0:0:0:
+187,192,625,1,0,0:0:0:0:
+221,192,750,1,0,0:0:0:0:
+256,192,875,1,0,0:0:0:0:
+290,192,1000,1,0,0:0:0:0:
+324,192,1125,1,0,0:0:0:0:
+358,192,1250,1,0,0:0:0:0:
+392,192,1375,1,0,0:0:0:0:
+426,192,1500,1,0,0:0:0:0:
+460,192,1625,1,0,0:0:0:0:
+494,192,1750,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/16K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/16K-expected-conversion.json
new file mode 100644
index 0000000000..ad7ab06125
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/16K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]},{"RandomW":273326509,"RandomX":631,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1875.0,"Objects":[{"StartTime":1875.0,"EndTime":1875.0,"Column":15}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/16K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/16K.osu
new file mode 100644
index 0000000000..51cf4f682e
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/16K.osu
@@ -0,0 +1,52 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:16K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:16
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+16,192,0,1,0,0:0:0:0:
+48,192,125,1,0,0:0:0:0:
+80,192,250,1,0,0:0:0:0:
+112,192,375,1,0,0:0:0:0:
+144,192,500,1,0,0:0:0:0:
+176,192,625,1,0,0:0:0:0:
+208,192,750,1,0,0:0:0:0:
+240,192,875,1,0,0:0:0:0:
+272,192,1000,1,0,0:0:0:0:
+304,192,1125,1,0,0:0:0:0:
+336,192,1250,1,0,0:0:0:0:
+368,192,1375,1,0,0:0:0:0:
+400,192,1500,1,0,0:0:0:0:
+432,192,1625,1,0,0:0:0:0:
+464,192,1750,1,0,0:0:0:0:
+496,192,1875,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/17K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/17K-expected-conversion.json
new file mode 100644
index 0000000000..1606d0d35d
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/17K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1875.0,"Objects":[{"StartTime":1875.0,"EndTime":1875.0,"Column":15}]},{"RandomW":273326509,"RandomX":651,"RandomY":842502087,"RandomZ":3579807591,"StartTime":2000.0,"Objects":[{"StartTime":2000.0,"EndTime":2000.0,"Column":16}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/17K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/17K.osu
new file mode 100644
index 0000000000..6ee76334ff
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/17K.osu
@@ -0,0 +1,53 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:17K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:17
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+15,192,0,1,0,0:0:0:0:
+45,192,125,1,0,0:0:0:0:
+75,192,250,1,0,0:0:0:0:
+105,192,375,1,0,0:0:0:0:
+135,192,500,1,0,0:0:0:0:
+165,192,625,1,0,0:0:0:0:
+195,192,750,1,0,0:0:0:0:
+225,192,875,1,0,0:0:0:0:
+256,192,1000,1,0,0:0:0:0:
+286,192,1125,1,0,0:0:0:0:
+316,192,1250,1,0,0:0:0:0:
+346,192,1375,1,0,0:0:0:0:
+376,192,1500,1,0,0:0:0:0:
+406,192,1625,1,0,0:0:0:0:
+436,192,1750,1,0,0:0:0:0:
+466,192,1875,1,0,0:0:0:0:
+496,192,2000,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/18K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/18K-expected-conversion.json
new file mode 100644
index 0000000000..53aa06d7d5
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/18K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1125.0,"Objects":[{"StartTime":1125.0,"EndTime":1125.0,"Column":9}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1250.0,"Objects":[{"StartTime":1250.0,"EndTime":1250.0,"Column":10}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1375.0,"Objects":[{"StartTime":1375.0,"EndTime":1375.0,"Column":11}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1500.0,"Objects":[{"StartTime":1500.0,"EndTime":1500.0,"Column":12}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1625.0,"Objects":[{"StartTime":1625.0,"EndTime":1625.0,"Column":13}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1750.0,"Objects":[{"StartTime":1750.0,"EndTime":1750.0,"Column":14}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1875.0,"Objects":[{"StartTime":1875.0,"EndTime":1875.0,"Column":15}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":2000.0,"Objects":[{"StartTime":2000.0,"EndTime":2000.0,"Column":16}]},{"RandomW":273326509,"RandomX":671,"RandomY":842502087,"RandomZ":3579807591,"StartTime":2125.0,"Objects":[{"StartTime":2125.0,"EndTime":2125.0,"Column":17}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/18K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/18K.osu
new file mode 100644
index 0000000000..8dee918e05
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/18K.osu
@@ -0,0 +1,54 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:18K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:18
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+14,192,0,1,0,0:0:0:0:
+42,192,125,1,0,0:0:0:0:
+71,192,250,1,0,0:0:0:0:
+99,192,375,1,0,0:0:0:0:
+128,192,500,1,0,0:0:0:0:
+156,192,625,1,0,0:0:0:0:
+184,192,750,1,0,0:0:0:0:
+213,192,875,1,0,0:0:0:0:
+241,192,1000,1,0,0:0:0:0:
+270,192,1125,1,0,0:0:0:0:
+298,192,1250,1,0,0:0:0:0:
+327,192,1375,1,0,0:0:0:0:
+355,192,1500,1,0,0:0:0:0:
+384,192,1625,1,0,0:0:0:0:
+412,192,1750,1,0,0:0:0:0:
+440,192,1875,1,0,0:0:0:0:
+469,192,2000,1,0,0:0:0:0:
+497,192,2125,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/1K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/1K-expected-conversion.json
new file mode 100644
index 0000000000..16323f5736
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/1K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":331,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/1K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/1K.osu
new file mode 100644
index 0000000000..137ec5cd29
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/1K.osu
@@ -0,0 +1,37 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:1K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:1
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+256,192,0,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/2K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/2K-expected-conversion.json
new file mode 100644
index 0000000000..9b742e9a1b
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/2K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":351,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":351,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/2K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/2K.osu
new file mode 100644
index 0000000000..7fff9d648c
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/2K.osu
@@ -0,0 +1,38 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:2K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:2
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+128,192,0,1,0,0:0:0:0:
+384,192,125,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/3K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/3K-expected-conversion.json
new file mode 100644
index 0000000000..d81ad5dbb8
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/3K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":371,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":371,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":371,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/3K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/3K.osu
new file mode 100644
index 0000000000..256831b57b
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/3K.osu
@@ -0,0 +1,39 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:3K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:3
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+85,192,0,1,0,0:0:0:0:
+256,192,125,1,0,0:0:0:0:
+426,192,250,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/4K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/4K-expected-conversion.json
new file mode 100644
index 0000000000..9a3bd53cec
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/4K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":391,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/4K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/4K.osu
new file mode 100644
index 0000000000..6212b1e9f7
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/4K.osu
@@ -0,0 +1,40 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:4K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:4
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+64,192,0,1,0,0:0:0:0:
+192,192,125,1,0,0:0:0:0:
+320,192,250,1,0,0:0:0:0:
+448,192,375,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/5K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/5K-expected-conversion.json
new file mode 100644
index 0000000000..fc00115829
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/5K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":411,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/5K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/5K.osu
new file mode 100644
index 0000000000..1a2aa9ab41
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/5K.osu
@@ -0,0 +1,41 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:5K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:5
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+51,192,0,1,0,0:0:0:0:
+153,192,125,1,0,0:0:0:0:
+256,192,250,1,0,0:0:0:0:
+358,192,375,1,0,0:0:0:0:
+460,192,500,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/6K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/6K-expected-conversion.json
new file mode 100644
index 0000000000..d867f586fe
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/6K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":431,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/6K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/6K.osu
new file mode 100644
index 0000000000..e5734b392b
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/6K.osu
@@ -0,0 +1,42 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:6K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:6
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+42,192,0,1,0,0:0:0:0:
+128,192,125,1,0,0:0:0:0:
+213,192,250,1,0,0:0:0:0:
+298,192,375,1,0,0:0:0:0:
+384,192,500,1,0,0:0:0:0:
+469,192,625,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K+1.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K+1.osu
new file mode 100644
index 0000000000..2523db164d
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K+1.osu
@@ -0,0 +1,45 @@
+osu file format v14
+
+[General]
+Mode: 3
+SpecialStyle:1
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:8K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:8
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+32,192,0,1,0,0:0:0:0:
+96,192,125,1,0,0:0:0:0:
+160,192,250,1,0,0:0:0:0:
+224,192,375,1,0,0:0:0:0:
+288,192,500,1,0,0:0:0:0:
+352,192,625,1,0,0:0:0:0:
+416,192,750,1,0,0:0:0:0:
+480,192,875,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K-expected-conversion.json
new file mode 100644
index 0000000000..bd4de99a56
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":451,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K.osu
new file mode 100644
index 0000000000..9575b98cd7
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/7K.osu
@@ -0,0 +1,43 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:7K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:7
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+36,192,0,1,0,0:0:0:0:
+109,192,125,1,0,0:0:0:0:
+182,192,250,1,0,0:0:0:0:
+256,192,375,1,0,0:0:0:0:
+329,192,500,1,0,0:0:0:0:
+402,192,625,1,0,0:0:0:0:
+475,192,750,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/8K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/8K-expected-conversion.json
new file mode 100644
index 0000000000..e8b198eecc
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/8K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":471,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/8K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/8K.osu
new file mode 100644
index 0000000000..f0bfbced46
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/8K.osu
@@ -0,0 +1,44 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:8K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:8
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+32,192,0,1,0,0:0:0:0:
+96,192,125,1,0,0:0:0:0:
+160,192,250,1,0,0:0:0:0:
+224,192,375,1,0,0:0:0:0:
+288,192,500,1,0,0:0:0:0:
+352,192,625,1,0,0:0:0:0:
+416,192,750,1,0,0:0:0:0:
+480,192,875,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/9K-expected-conversion.json b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/9K-expected-conversion.json
new file mode 100644
index 0000000000..7c08050b78
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/9K-expected-conversion.json
@@ -0,0 +1 @@
+{"Mappings":[{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":0.0,"Objects":[{"StartTime":0.0,"EndTime":0.0,"Column":0}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":125.0,"Objects":[{"StartTime":125.0,"EndTime":125.0,"Column":1}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":250.0,"Objects":[{"StartTime":250.0,"EndTime":250.0,"Column":2}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":375.0,"Objects":[{"StartTime":375.0,"EndTime":375.0,"Column":3}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":500.0,"Objects":[{"StartTime":500.0,"EndTime":500.0,"Column":4}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":625.0,"Objects":[{"StartTime":625.0,"EndTime":625.0,"Column":5}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":750.0,"Objects":[{"StartTime":750.0,"EndTime":750.0,"Column":6}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":875.0,"Objects":[{"StartTime":875.0,"EndTime":875.0,"Column":7}]},{"RandomW":273326509,"RandomX":491,"RandomY":842502087,"RandomZ":3579807591,"StartTime":1000.0,"Objects":[{"StartTime":1000.0,"EndTime":1000.0,"Column":8}]}]}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/9K.osu b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/9K.osu
new file mode 100644
index 0000000000..2405f19005
--- /dev/null
+++ b/osu.Game.Rulesets.Mania.Tests/Resources/Testing/Beatmaps/9K.osu
@@ -0,0 +1,45 @@
+osu file format v14
+
+[General]
+Mode: 3
+
+[Metadata]
+Title:keycount test
+TitleUnicode:keycount test
+Artist:mania
+ArtistUnicode:mania
+Creator:spaceman_atlas
+Version:9K
+
+[Difficulty]
+HPDrainRate:5
+CircleSize:9
+OverallDifficulty:5
+ApproachRate:5
+SliderMultiplier:1.4
+SliderTickRate:1
+
+[Events]
+//Background and Video events
+//Break Periods
+//Storyboard Layer 0 (Background)
+//Storyboard Layer 1 (Fail)
+//Storyboard Layer 2 (Pass)
+//Storyboard Layer 3 (Foreground)
+//Storyboard Layer 4 (Overlay)
+//Storyboard Sound Samples
+
+[TimingPoints]
+0,500,4,2,0,100,1,0
+
+
+[HitObjects]
+28,192,0,1,0,0:0:0:0:
+85,192,125,1,0,0:0:0:0:
+142,192,250,1,0,0:0:0:0:
+199,192,375,1,0,0:0:0:0:
+256,192,500,1,0,0:0:0:0:
+312,192,625,1,0,0:0:0:0:
+369,192,750,1,0,0:0:0:0:
+426,192,875,1,0,0:0:0:0:
+483,192,1000,1,0,0:0:0:0:
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs
index cd709c46dc..d0b5174748 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs
@@ -33,6 +33,8 @@ namespace osu.Game.Rulesets.Mania.Tests
///
public partial class TestSceneHoldNoteInput : RateAdjustedBeatmapTestScene
{
+ protected override Ruleset CreateRuleset() => new ManiaRuleset();
+
private const double time_before_head = 250;
private const double time_head = 1500;
private const double time_during_hold_1 = 2500;
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneMaximumScore.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneMaximumScore.cs
index ee6d999932..98310adb8c 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneMaximumScore.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneMaximumScore.cs
@@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Mania.Tests
{
public partial class TestSceneMaximumScore : RateAdjustedBeatmapTestScene
{
+ protected override Ruleset CreateRuleset() => new ManiaRuleset();
+
private ScoreAccessibleReplayPlayer currentPlayer = null!;
private List judgementResults = new List();
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs
index e49b259615..3dc82e09e7 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneOutOfOrderHits.cs
@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Tests
{
public partial class TestSceneOutOfOrderHits : RateAdjustedBeatmapTestScene
{
+ protected override Ruleset CreateRuleset() => new ManiaRuleset();
+
[Test]
public void TestPreviousHitWindowDoesNotExtendPastNextObject()
{
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRewinding.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRewinding.cs
index 5216358a8b..c182ce7d5d 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRewinding.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneReplayRewinding.cs
@@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Mania.Tests
{
public partial class TestSceneReplayRewinding : RateAdjustedBeatmapTestScene
{
+ protected override Ruleset CreateRuleset() => new ManiaRuleset();
+
private ReplayPlayer currentPlayer = null!;
[Test]
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs
index eb47e96670..37316e348c 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneTimingBasedNoteColouring.cs
@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Mania.Tests
[TestFixture]
public partial class TestSceneTimingBasedNoteColouring : OsuTestScene
{
+ protected override Ruleset CreateRuleset() => new ManiaRuleset();
+
private Bindable configTimingBasedNoteColouring;
private ManualClock clock;
diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
index 8d5c4d9da6..57bc6d744c 100644
--- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
+++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj
@@ -11,5 +11,6 @@
+
diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
index c55465762b..c6be45e312 100644
--- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
@@ -66,6 +66,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
if (IsForCurrentRuleset && TargetColumns > ManiaRuleset.MAX_STAGE_KEYS)
{
+ // If support for odd key counts above 10 (11 / 13 / 15 / 17K) is ever desired, this code needs to go.
+ // For now, it's probably fine, as stable doesn't support them outside of manual .osu edits either.
TargetColumns /= 2;
Dual = true;
}
diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs
index c18bb9e902..3e2bcd7b43 100644
--- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapEncoderTest.cs
@@ -46,11 +46,11 @@ namespace osu.Game.Tests.Beatmaps.Formats
{
const string name = "Resources/storyboard_only_video.osu";
- var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
+ var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
Assert.That(decoded.beatmap.UnhandledEventLines.Count, Is.EqualTo(1));
Assert.That(decoded.beatmap.UnhandledEventLines.Single(), Is.EqualTo("Video,0,\"video.avi\""));
- var memoryStream = encodeToLegacy(decoded);
+ var memoryStream = EncodeToLegacy(decoded);
var storyboard = new LegacyStoryboardDecoder().Decode(new LineBufferedReader(memoryStream));
StoryboardLayer video = storyboard.Layers.Single(l => l.Name == "Video");
@@ -60,42 +60,42 @@ namespace osu.Game.Tests.Beatmaps.Formats
[TestCaseSource(nameof(allBeatmaps))]
public void TestEncodeDecodeStability(string name)
{
- var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy(decoded), name);
+ var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
+ var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
- sort(decoded.beatmap);
- sort(decodedAfterEncode.beatmap);
+ Sort(decoded.beatmap);
+ Sort(decodedAfterEncode.beatmap);
- compareBeatmaps(decoded, decodedAfterEncode);
+ CompareBeatmaps(decoded, decodedAfterEncode);
}
[TestCaseSource(nameof(allBeatmaps))]
public void TestEncodeDecodeStabilityDoubleConvert(string name)
{
- var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy(decoded), name);
+ var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
+ var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
// run an extra convert. this is expected to be stable.
decodedAfterEncode.beatmap = convert(decodedAfterEncode.beatmap);
- sort(decoded.beatmap);
- sort(decodedAfterEncode.beatmap);
+ Sort(decoded.beatmap);
+ Sort(decodedAfterEncode.beatmap);
- compareBeatmaps(decoded, decodedAfterEncode);
+ CompareBeatmaps(decoded, decodedAfterEncode);
}
[TestCaseSource(nameof(allBeatmaps))]
public void TestEncodeDecodeStabilityWithNonLegacyControlPoints(string name)
{
- var decoded = decodeFromLegacy(beatmaps_resource_store.GetStream(name), name);
+ var decoded = DecodeFromLegacy(beatmaps_resource_store.GetStream(name), beatmaps_resource_store, name);
// we are testing that the transfer of relevant data to hitobjects (from legacy control points) sticks through encode/decode.
// before the encode step, the legacy information is removed here.
decoded.beatmap.ControlPointInfo = removeLegacyControlPointTypes(decoded.beatmap.ControlPointInfo);
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy(decoded), name);
+ var decodedAfterEncode = DecodeFromLegacy(EncodeToLegacy(decoded), beatmaps_resource_store, name);
- compareBeatmaps(decoded, decodedAfterEncode);
+ CompareBeatmaps(decoded, decodedAfterEncode);
static ControlPointInfo removeLegacyControlPointTypes(ControlPointInfo controlPointInfo)
{
@@ -120,7 +120,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
}
- private void compareBeatmaps((IBeatmap beatmap, TestLegacySkin skin) expected, (IBeatmap beatmap, TestLegacySkin skin) actual)
+ public static void CompareBeatmaps((IBeatmap beatmap, TestLegacySkin skin) expected, (IBeatmap beatmap, TestLegacySkin skin) actual)
{
// Check all control points that are still considered to be at a global level.
Assert.That(actual.beatmap.ControlPointInfo.TimingPoints.Serialize(), Is.EqualTo(expected.beatmap.ControlPointInfo.TimingPoints.Serialize()));
@@ -153,7 +153,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
+ var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
+ var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
var decodedSlider = (Slider)decodedAfterEncode.beatmap.HitObjects[0];
Assert.That(decodedSlider.Path.ControlPoints.Count, Is.EqualTo(4));
Assert.That(decodedSlider.Path.ControlPoints[0].Type, Is.EqualTo(PathType.BSpline(3)));
@@ -182,7 +183,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
+ var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
+ var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
var decodedSlider = (Slider)decodedAfterEncode.beatmap.HitObjects[0];
Assert.That(decodedSlider.Path.ControlPoints.Count, Is.EqualTo(5));
}
@@ -209,7 +211,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((new Beatmap(), beatmapSkin)), string.Empty);
+ var encoded = EncodeToLegacy((new Beatmap(), beatmapSkin));
+ var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
Assert.That(decodedAfterEncode.skin.Configuration.CustomComboColours, Has.Count.EqualTo(8));
}
@@ -231,8 +234,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
HitObjects = { originalSlider }
};
- var encoded = encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
- var decodedAfterEncode = decodeFromLegacy(encoded, string.Empty, version: LegacyBeatmapEncoder.FIRST_LAZER_VERSION);
+ var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
+ var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty, version: LegacyBeatmapEncoder.FIRST_LAZER_VERSION);
var decodedSlider = (Slider)decodedAfterEncode.beatmap.HitObjects[0];
Assert.That(decodedSlider.Path.ControlPoints.Select(p => p.Position),
Is.EquivalentTo(originalSlider.Path.ControlPoints.Select(p => p.Position)));
@@ -251,7 +254,8 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
};
- var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
+ var encoded = EncodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty)));
+ var decodedAfterEncode = DecodeFromLegacy(encoded, beatmaps_resource_store, string.Empty);
Assert.That(decodedAfterEncode.beatmap.HitObjects[0].Samples[0].Suffix, Is.Null);
Assert.That(decodedAfterEncode.beatmap.HitObjects[0].Samples[0].UseBeatmapSamples, Is.False);
@@ -263,7 +267,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.That(decodedAfterEncode.beatmap.HitObjects[2].Samples[0].UseBeatmapSamples, Is.True);
}
- private bool areComboColoursEqual(IHasComboColours a, IHasComboColours b)
+ private static bool areComboColoursEqual(IHasComboColours a, IHasComboColours b)
{
// equal to null, no need to SequenceEqual
if (a.ComboColours == null && b.ComboColours == null)
@@ -275,7 +279,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
return a.ComboColours.SequenceEqual(b.ComboColours);
}
- private void sort(IBeatmap beatmap)
+ public static void Sort(IBeatmap beatmap)
{
// Sort control points to ensure a sane ordering, as they may be parsed in different orders. This works because each group contains only uniquely-typed control points.
foreach (var g in beatmap.ControlPointInfo.Groups)
@@ -285,19 +289,19 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
}
- private (IBeatmap beatmap, TestLegacySkin skin) decodeFromLegacy(Stream stream, string name, int version = LegacyDecoder.LATEST_VERSION)
+ public static (IBeatmap beatmap, TestLegacySkin skin) DecodeFromLegacy(Stream stream, IResourceStore beatmapsResourceStore, string name, int version = LegacyDecoder.LATEST_VERSION)
{
using (var reader = new LineBufferedReader(stream))
{
var beatmap = new LegacyBeatmapDecoder(version) { ApplyOffsets = false }.Decode(reader);
- var beatmapSkin = new TestLegacySkin(beatmaps_resource_store, name);
+ var beatmapSkin = new TestLegacySkin(beatmapsResourceStore, name);
stream.Seek(0, SeekOrigin.Begin);
beatmapSkin.Configuration = new LegacySkinDecoder().Decode(reader);
return (convert(beatmap), beatmapSkin);
}
}
- private class TestLegacySkin : LegacySkin
+ public class TestLegacySkin : LegacySkin
{
public TestLegacySkin(IResourceStore fallbackStore, string fileName)
: base(new SkinInfo { Name = "Test Skin", Creator = "Craftplacer" }, null, fallbackStore, fileName)
@@ -305,7 +309,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
}
}
- private MemoryStream encodeToLegacy((IBeatmap beatmap, ISkin skin) fullBeatmap)
+ public static MemoryStream EncodeToLegacy((IBeatmap beatmap, ISkin skin) fullBeatmap)
{
var (beatmap, beatmapSkin) = fullBeatmap;
var stream = new MemoryStream();
@@ -318,7 +322,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
return stream;
}
- private IBeatmap convert(IBeatmap beatmap)
+ private static IBeatmap convert(IBeatmap beatmap)
{
switch (beatmap.BeatmapInfo.Ruleset.OnlineID)
{
diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs
index 24976717c1..c5749b9ce8 100644
--- a/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapEncoder.cs
@@ -400,7 +400,8 @@ namespace osu.Game.Beatmaps.Formats
case 3:
int totalColumns = (int)Math.Max(1, beatmap.Difficulty.CircleSize);
- position.X = (int)Math.Ceiling(((IHasXPosition)hitObject).X * (512f / totalColumns));
+ // compare: https://github.com/peppy/osu-stable-reference/blob/c34a74fb61c17c5667486a12548485d1f03baa2e/osu!/GameModes/Play/Rulesets/Mania/Stage/StageMania_Calculations.cs#L159
+ position.X = (int)Math.Floor((((IHasXPosition)hitObject).X + 0.5f) * (512f / totalColumns));
break;
}
diff --git a/osu.Game/Tests/Visual/EditorSavingTestScene.cs b/osu.Game/Tests/Visual/EditorSavingTestScene.cs
index 5a3f5c432e..28bcf05dd0 100644
--- a/osu.Game/Tests/Visual/EditorSavingTestScene.cs
+++ b/osu.Game/Tests/Visual/EditorSavingTestScene.cs
@@ -35,6 +35,8 @@ namespace osu.Game.Tests.Visual
{
base.SetUpSteps();
+ AddStep("set ruleset", () => Game.Ruleset.Value = CreateRuleset()?.RulesetInfo ?? Game.Ruleset.Value);
+
if (CreateInitialBeatmap == null)
AddStep("set default beatmap", () => Game.Beatmap.SetDefault());
else