diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs
index 18009417cb..47575ca208 100644
--- a/osu.Desktop/Program.cs
+++ b/osu.Desktop/Program.cs
@@ -10,6 +10,11 @@ using osu.Framework.Desktop.Platform;
using osu.Framework.Platform;
using osu.Game;
using osu.Game.IPC;
+using osu.Game.Modes;
+using osu.Game.Modes.Catch;
+using osu.Game.Modes.Mania;
+using osu.Game.Modes.Osu;
+using osu.Game.Modes.Taiko;
namespace osu.Desktop
{
@@ -31,6 +36,11 @@ namespace osu.Desktop
}
else
{
+ Ruleset.Register(new OsuRuleset());
+ Ruleset.Register(new TaikoRuleset());
+ Ruleset.Register(new ManiaRuleset());
+ Ruleset.Register(new CatchRuleset());
+
BaseGame osu = new OsuGame(args);
host.Add(osu);
host.Run();
diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj
index 28e591a558..95d3ad64c5 100644
--- a/osu.Desktop/osu.Desktop.csproj
+++ b/osu.Desktop/osu.Desktop.csproj
@@ -134,6 +134,18 @@
{c92a607b-1fdd-4954-9f92-03ff547d9080}
osu.Game.Modes.Osu
+
+ {58f6c80c-1253-4a0e-a465-b8c85ebeadf3}
+ osu.Game.Modes.Catch
+
+
+ {48f4582b-7687-4621-9cbe-5c24197cb536}
+ osu.Game.Modes.Mania
+
+
+ {f167e17a-7de6-4af5-b920-a5112296c695}
+ osu.Game.Modes.Taiko
+
{0d3fbf8a-7464-4cf7-8c90-3e7886df2d4d}
osu.Game
diff --git a/osu.Game.Mode.Osu/Objects/OsuBaseHit.cs b/osu.Game.Mode.Osu/Objects/OsuBaseHit.cs
index 81c9e0b4e9..0bd3d62d9e 100644
--- a/osu.Game.Mode.Osu/Objects/OsuBaseHit.cs
+++ b/osu.Game.Mode.Osu/Objects/OsuBaseHit.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Modes.Osu.Objects
public Vector2 Position { get; set; }
[Flags]
- private enum HitObjectType
+ internal enum HitObjectType
{
Circle = 1,
Slider = 2,
@@ -25,35 +25,5 @@ namespace osu.Game.Modes.Osu.Objects
Hold = 128,
ManiaLong = 128,
}
-
- public static OsuBaseHit Parse(string val)
- {
- string[] split = val.Split(',');
- var type = (HitObjectType)int.Parse(split[3]);
- bool combo = type.HasFlag(HitObjectType.NewCombo);
- type &= (HitObjectType)0xF;
- type &= ~HitObjectType.NewCombo;
- OsuBaseHit result;
- switch (type)
- {
- case HitObjectType.Circle:
- result = new Circle();
- break;
- case HitObjectType.Slider:
- result = new Slider();
- break;
- case HitObjectType.Spinner:
- result = new Spinner();
- break;
- default:
- throw new InvalidOperationException($@"Unknown hit object type {type}");
- }
- result.Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]));
- result.StartTime = double.Parse(split[2]);
- result.Sample = new HitSampleInfo { Type = (SampleType)int.Parse(split[4]) };
- result.NewCombo = combo;
- // TODO: "addition" field
- return result;
- }
}
}
diff --git a/osu.Game.Mode.Osu/Objects/OsuHitObjectParser.cs b/osu.Game.Mode.Osu/Objects/OsuHitObjectParser.cs
new file mode 100644
index 0000000000..81c218e8e1
--- /dev/null
+++ b/osu.Game.Mode.Osu/Objects/OsuHitObjectParser.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using osu.Game.Beatmaps.Samples;
+using osu.Game.Modes.Objects;
+using OpenTK;
+
+namespace osu.Game.Modes.Osu.Objects
+{
+ public class OsuHitObjectParser : HitObjectParser
+ {
+ public override HitObject Parse(string text)
+ {
+ string[] split = text.Split(',');
+ var type = (OsuBaseHit.HitObjectType)int.Parse(split[3]);
+ bool combo = type.HasFlag(OsuBaseHit.HitObjectType.NewCombo);
+ type &= (OsuBaseHit.HitObjectType)0xF;
+ type &= ~OsuBaseHit.HitObjectType.NewCombo;
+ OsuBaseHit result;
+ switch (type)
+ {
+ case OsuBaseHit.HitObjectType.Circle:
+ result = new Circle();
+ break;
+ case OsuBaseHit.HitObjectType.Slider:
+ result = new Slider();
+ break;
+ case OsuBaseHit.HitObjectType.Spinner:
+ result = new Spinner();
+ break;
+ default:
+ //throw new InvalidOperationException($@"Unknown hit object type {type}");
+ return null;
+ }
+ result.Position = new Vector2(int.Parse(split[0]), int.Parse(split[1]));
+ result.StartTime = double.Parse(split[2]);
+ result.Sample = new HitSampleInfo { Type = (SampleType)int.Parse(split[4]) };
+ result.NewCombo = combo;
+ // TODO: "addition" field
+ return result;
+ }
+ }
+}
diff --git a/osu.Game.Mode.Osu/OsuRuleset.cs b/osu.Game.Mode.Osu/OsuRuleset.cs
index 666f51f041..4e8b8fde2b 100644
--- a/osu.Game.Mode.Osu/OsuRuleset.cs
+++ b/osu.Game.Mode.Osu/OsuRuleset.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using osu.Game.Modes.Objects;
+using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
@@ -13,5 +14,7 @@ namespace osu.Game.Modes.Osu
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List objects) => new UI.OsuHitRenderer { Objects = objects };
+
+ public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
}
}
diff --git a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj
index 2c38463e9d..9a5668b35e 100644
--- a/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj
+++ b/osu.Game.Mode.Osu/osu.Game.Modes.Osu.csproj
@@ -41,6 +41,7 @@
+
diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs
index 992d0fff59..5a55db5ede 100644
--- a/osu.Game.Modes.Catch/CatchRuleset.cs
+++ b/osu.Game.Modes.Catch/CatchRuleset.cs
@@ -4,15 +4,18 @@
using System.Collections.Generic;
using osu.Game.Modes.Catch.UI;
using osu.Game.Modes.Objects;
+using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Catch
{
- class CatchRuleset : Ruleset
+ public class CatchRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List objects) => new CatchHitRenderer { Objects = objects };
+
+ public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
}
}
diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs
index 07f2545fd3..f92ce9ba1a 100644
--- a/osu.Game.Modes.Mania/ManiaRuleset.cs
+++ b/osu.Game.Modes.Mania/ManiaRuleset.cs
@@ -5,15 +5,18 @@ using System.Collections.Generic;
using osu.Game.Modes.Mania.UI;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu;
+using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Mania
{
- class ManiaRuleset : Ruleset
+ public class ManiaRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List objects) => new ManiaHitRenderer { Objects = objects };
+
+ public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
}
}
diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs
index f8322e32dc..a85c2c7a32 100644
--- a/osu.Game.Modes.Taiko/TaikoRuleset.cs
+++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs
@@ -3,16 +3,19 @@
using System.Collections.Generic;
using osu.Game.Modes.Objects;
+using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Osu.UI;
using osu.Game.Modes.Taiko.UI;
using osu.Game.Modes.UI;
namespace osu.Game.Modes.Taiko
{
- class TaikoRuleset : Ruleset
+ public class TaikoRuleset : Ruleset
{
public override ScoreOverlay CreateScoreOverlay() => new OsuScoreOverlay();
public override HitRenderer CreateHitRendererWith(List objects) => new TaikoHitRenderer { Objects = objects };
+
+ public override HitObjectParser CreateHitObjectParser() => new OsuHitObjectParser();
}
}
diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs
index db2e4b7d7e..90b62ef98a 100644
--- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs
@@ -7,6 +7,7 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.Beatmaps.Samples;
using osu.Game.Modes;
+using osu.Game.Modes.Osu;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Screens.Play;
using osu.Game.Tests.Resources;
@@ -20,6 +21,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
public void SetUp()
{
OsuLegacyDecoder.Register();
+ Ruleset.Register(new OsuRuleset());
}
[Test]
public void TestDecodeMetadata()
diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
index 0c53ef380c..7acbdbf3d9 100644
--- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
+++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
@@ -9,6 +9,10 @@ using osu.Framework.Platform;
using osu.Game.Database;
using osu.Game.IPC;
using osu.Game.Modes;
+using osu.Game.Modes.Catch;
+using osu.Game.Modes.Mania;
+using osu.Game.Modes.Osu;
+using osu.Game.Modes.Taiko;
using osu.Game.Screens.Play;
namespace osu.Game.Tests.Beatmaps.IO
@@ -21,6 +25,10 @@ namespace osu.Game.Tests.Beatmaps.IO
[OneTimeSetUp]
public void SetUp()
{
+ Ruleset.Register(new OsuRuleset());
+ Ruleset.Register(new TaikoRuleset());
+ Ruleset.Register(new ManiaRuleset());
+ Ruleset.Register(new CatchRuleset());
}
[Test]
diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs
index 8a0364a03b..1343ae7241 100644
--- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs
+++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs
@@ -2,6 +2,8 @@
using System.IO;
using NUnit.Framework;
using osu.Game.Beatmaps.IO;
+using osu.Game.Modes;
+using osu.Game.Modes.Osu;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Beatmaps.IO
@@ -13,8 +15,9 @@ namespace osu.Game.Tests.Beatmaps.IO
public void SetUp()
{
OszArchiveReader.Register();
+ Ruleset.Register(new OsuRuleset());
}
-
+
[Test]
public void TestReadBeatmaps()
{
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 646ee756d5..d59e90c2f4 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -70,6 +70,18 @@
{c92a607b-1fdd-4954-9f92-03ff547d9080}
osu.Game.Modes.Osu
+
+ {58f6c80c-1253-4a0e-a465-b8c85ebeadf3}
+ osu.Game.Modes.Catch
+
+
+ {48f4582b-7687-4621-9cbe-5c24197cb536}
+ osu.Game.Modes.Mania
+
+
+ {f167e17a-7de6-4af5-b920-a5112296c695}
+ osu.Game.Modes.Taiko
+
{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}
osu.Game
diff --git a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs
index 7ff3dbac2b..b5dd0c995e 100644
--- a/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/BeatmapDecoder.cs
@@ -48,6 +48,8 @@ namespace osu.Game.Beatmaps.Formats
new Color4(121,9,13, 255),
};
+ if (colours.Count == 0) return;
+
int i = -1;
foreach (HitObject h in b.HitObjects)
diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs
index 2cf4e66927..5468e616f0 100644
--- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs
@@ -221,7 +221,9 @@ namespace osu.Game.Beatmaps.Formats
BaseDifficulty = new BaseDifficulty(),
},
};
-
+
+ HitObjectParser parser = null;
+
var section = Section.None;
string line;
while (true)
@@ -233,14 +235,14 @@ namespace osu.Game.Beatmaps.Formats
continue;
if (line.StartsWith(@"osu file format v"))
continue;
-
+
if (line.StartsWith(@"[") && line.EndsWith(@"]"))
{
if (!Enum.TryParse(line.Substring(1, line.Length - 2), out section))
throw new InvalidDataException($@"Unknown osu section {line}");
continue;
}
-
+
string val = line, key = null;
if (section != Section.Events && section != Section.TimingPoints && section != Section.HitObjects)
{
@@ -251,6 +253,7 @@ namespace osu.Game.Beatmaps.Formats
{
case Section.General:
handleGeneral(beatmap, key, val);
+ parser = Ruleset.GetRuleset(beatmap.BeatmapInfo.Mode).CreateHitObjectParser();
break;
case Section.Editor:
handleEditor(beatmap, key, val);
@@ -271,13 +274,13 @@ namespace osu.Game.Beatmaps.Formats
handleColours(beatmap, key, val);
break;
case Section.HitObjects:
- var h = HitObject.Parse(beatmap.BeatmapInfo.Mode, val);
- if (h != null)
- beatmap.HitObjects.Add(h);
+ var obj = parser?.Parse(val);
+ if (obj != null)
+ beatmap.HitObjects.Add(obj);
break;
}
}
-
+
return beatmap;
}
}
diff --git a/osu.Game/Modes/Objects/HitObject.cs b/osu.Game/Modes/Objects/HitObject.cs
index 62c47d7059..abb88726b6 100644
--- a/osu.Game/Modes/Objects/HitObject.cs
+++ b/osu.Game/Modes/Objects/HitObject.cs
@@ -21,17 +21,5 @@ namespace osu.Game.Modes.Objects
public double Duration => EndTime - StartTime;
public HitSampleInfo Sample;
-
- public static HitObject Parse(PlayMode mode, string val)
- {
- //TODO: move to modular HitObjectParser system rather than static parsing. (https://github.com/ppy/osu/pull/60/files#r83135780)
- switch (mode)
- {
- case PlayMode.Osu:
- return null; //return OsuBaseHit.Parse(val);
- default:
- return null;
- }
- }
}
}
diff --git a/osu.Game/Modes/Objects/HitObjectParser.cs b/osu.Game/Modes/Objects/HitObjectParser.cs
new file mode 100644
index 0000000000..261e92ff96
--- /dev/null
+++ b/osu.Game/Modes/Objects/HitObjectParser.cs
@@ -0,0 +1,16 @@
+//Copyright (c) 2007-2016 ppy Pty Ltd .
+//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace osu.Game.Modes.Objects
+{
+ public abstract class HitObjectParser
+ {
+ public abstract HitObject Parse(string text);
+ }
+}
diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs
index 64a91f2108..7fc4b3221d 100644
--- a/osu.Game/Modes/Ruleset.cs
+++ b/osu.Game/Modes/Ruleset.cs
@@ -13,17 +13,19 @@ namespace osu.Game.Modes
{
public abstract class Ruleset
{
+ private static List availableRulesets = new List();
+
public abstract ScoreOverlay CreateScoreOverlay();
public abstract HitRenderer CreateHitRendererWith(List objects);
+ public abstract HitObjectParser CreateHitObjectParser();
+
+ public static void Register(Ruleset ruleset) => availableRulesets.Add(ruleset.GetType());
+
public static Ruleset GetRuleset(PlayMode mode)
{
- Type type = AppDomain.CurrentDomain
- .GetAssemblies()
- .Where(a => a.FullName.Contains($@"osu.Game.Modes.{mode}"))
- .SelectMany(a => a.GetTypes())
- .FirstOrDefault(t => t.Name == $@"{mode}Ruleset");
+ Type type = availableRulesets.FirstOrDefault(t => t.Name == $@"{mode}Ruleset");
if (type == null)
return null;
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index ede412f27c..88f78b57be 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -63,6 +63,7 @@
+