1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 12:57:36 +08:00

Make a RulesetDatabase.

This commit is contained in:
Dean Herbert 2017-04-17 17:43:48 +09:00
parent 83b083ce64
commit a4e2f34ee7
No known key found for this signature in database
GPG Key ID: 46D71BF4958ABB49
38 changed files with 298 additions and 201 deletions

View File

@ -4,11 +4,6 @@
using NUnit.Framework; using NUnit.Framework;
using osu.Desktop.VisualTests; using osu.Desktop.VisualTests;
using osu.Framework.Desktop.Platform; using osu.Framework.Desktop.Platform;
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.Tests namespace osu.Desktop.Tests
{ {
@ -20,11 +15,6 @@ namespace osu.Desktop.Tests
{ {
using (var host = new HeadlessGameHost()) using (var host = new HeadlessGameHost())
{ {
RulesetCollection.Register(typeof(OsuRuleset));
RulesetCollection.Register(typeof(TaikoRuleset));
RulesetCollection.Register(typeof(ManiaRuleset));
RulesetCollection.Register(typeof(CatchRuleset));
host.Run(new AutomatedVisualTestGame()); host.Run(new AutomatedVisualTestGame());
} }
} }

View File

@ -4,11 +4,6 @@
using System; using System;
using osu.Framework.Desktop; using osu.Framework.Desktop;
using osu.Framework.Platform; using osu.Framework.Platform;
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.VisualTests namespace osu.Desktop.VisualTests
{ {
@ -21,11 +16,6 @@ namespace osu.Desktop.VisualTests
using (GameHost host = Host.GetSuitableHost(@"osu")) using (GameHost host = Host.GetSuitableHost(@"osu"))
{ {
RulesetCollection.Register(typeof(OsuRuleset));
RulesetCollection.Register(typeof(TaikoRuleset));
RulesetCollection.Register(typeof(ManiaRuleset));
RulesetCollection.Register(typeof(CatchRuleset));
if (benchmark) if (benchmark)
host.Run(new AutomatedVisualTestGame()); host.Run(new AutomatedVisualTestGame());
else else

View File

@ -1,10 +1,11 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Modes; using osu.Game.Database;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -13,6 +14,13 @@ namespace osu.Desktop.VisualTests.Tests
public override string Description => @"Tests the mod select overlay"; public override string Description => @"Tests the mod select overlay";
private ModSelectOverlay modSelect; private ModSelectOverlay modSelect;
private RulesetDatabase rulesets;
[BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
this.rulesets = rulesets;
}
public override void Reset() public override void Reset()
{ {
@ -27,8 +35,8 @@ namespace osu.Desktop.VisualTests.Tests
AddStep("Toggle", modSelect.ToggleVisibility); AddStep("Toggle", modSelect.ToggleVisibility);
foreach (var ruleset in RulesetCollection.AllRulesets) foreach (var ruleset in rulesets.AllRulesets)
AddStep(ruleset.Description, () => modSelect.Ruleset.Value = ruleset); AddStep(ruleset.CreateInstance().Description, () => modSelect.Ruleset.Value = ruleset);
} }
} }
} }

View File

@ -3,12 +3,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Desktop.VisualTests.Platform; using osu.Desktop.VisualTests.Platform;
using osu.Framework.Allocation;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using osu.Game.Screens.Select.Filter; using osu.Game.Screens.Select.Filter;
using osu.Game.Modes;
namespace osu.Desktop.VisualTests.Tests namespace osu.Desktop.VisualTests.Tests
{ {
@ -20,6 +20,14 @@ namespace osu.Desktop.VisualTests.Tests
public override string Description => @"with fake data"; public override string Description => @"with fake data";
private RulesetDatabase rulesets;
[BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
this.rulesets = rulesets;
}
public override void Reset() public override void Reset()
{ {
base.Reset(); base.Reset();
@ -72,7 +80,7 @@ namespace osu.Desktop.VisualTests.Tests
new BeatmapInfo new BeatmapInfo
{ {
OnlineBeatmapID = 1234 + i, OnlineBeatmapID = 1234 + i,
Ruleset = RulesetCollection.GetRuleset(0), Ruleset = rulesets.Query<RulesetInfo>().First(),
Path = "normal.osu", Path = "normal.osu",
Version = "Normal", Version = "Normal",
Difficulty = new BeatmapDifficulty Difficulty = new BeatmapDifficulty
@ -83,7 +91,7 @@ namespace osu.Desktop.VisualTests.Tests
new BeatmapInfo new BeatmapInfo
{ {
OnlineBeatmapID = 1235 + i, OnlineBeatmapID = 1235 + i,
Ruleset = RulesetCollection.GetRuleset(0), Ruleset = rulesets.Query<RulesetInfo>().First(),
Path = "hard.osu", Path = "hard.osu",
Version = "Hard", Version = "Hard",
Difficulty = new BeatmapDifficulty Difficulty = new BeatmapDifficulty
@ -94,7 +102,7 @@ namespace osu.Desktop.VisualTests.Tests
new BeatmapInfo new BeatmapInfo
{ {
OnlineBeatmapID = 1236 + i, OnlineBeatmapID = 1236 + i,
Ruleset = RulesetCollection.GetRuleset(0), Ruleset = rulesets.Query<RulesetInfo>().First(),
Path = "insane.osu", Path = "insane.osu",
Version = "Insane", Version = "Insane",
Difficulty = new BeatmapDifficulty Difficulty = new BeatmapDifficulty

View File

@ -37,7 +37,7 @@ namespace osu.Desktop.VisualTests.Tests
WorkingBeatmap beatmap = null; WorkingBeatmap beatmap = null;
var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.Ruleset is OsuRuleset); var beatmapInfo = db.Query<BeatmapInfo>().FirstOrDefault(b => b.Ruleset.CreateInstance() is OsuRuleset);
if (beatmapInfo != null) if (beatmapInfo != null)
beatmap = db.GetWorkingBeatmap(beatmapInfo); beatmap = db.GetWorkingBeatmap(beatmapInfo);

View File

@ -7,11 +7,6 @@ using osu.Desktop.Beatmaps.IO;
using osu.Framework.Desktop; using osu.Framework.Desktop;
using osu.Framework.Desktop.Platform; using osu.Framework.Desktop.Platform;
using osu.Game.IPC; 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 namespace osu.Desktop
{ {
@ -41,11 +36,6 @@ namespace osu.Desktop
} }
else else
{ {
RulesetCollection.Register(typeof(OsuRuleset));
RulesetCollection.Register(typeof(TaikoRuleset));
RulesetCollection.Register(typeof(ManiaRuleset));
RulesetCollection.Register(typeof(CatchRuleset));
host.Run(new OsuGameDesktop(args)); host.Run(new OsuGameDesktop(args));
} }
return 0; return 0;

View File

@ -90,5 +90,7 @@ namespace osu.Game.Modes.Catch
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor();
public override int LegacyID => 2;
} }
} }

View File

@ -105,5 +105,7 @@ namespace osu.Game.Modes.Mania
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor();
public override int LegacyID => 3;
} }
} }

View File

@ -110,5 +110,7 @@ namespace osu.Game.Modes.Osu
}; };
public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor();
public override int LegacyID => 0;
} }
} }

View File

@ -91,5 +91,7 @@ namespace osu.Game.Modes.Taiko
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap);
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor();
public override int LegacyID => 1;
} }
} }

View File

@ -6,7 +6,6 @@ using NUnit.Framework;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Formats;
using osu.Game.Modes;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
using osu.Game.Modes.Osu; using osu.Game.Modes.Osu;
using osu.Game.Modes.Objects.Legacy; using osu.Game.Modes.Objects.Legacy;
@ -22,7 +21,6 @@ namespace osu.Game.Tests.Beatmaps.Formats
public void SetUp() public void SetUp()
{ {
OsuLegacyDecoder.Register(); OsuLegacyDecoder.Register();
RulesetCollection.Register(typeof(OsuRuleset));
} }
[Test] [Test]
@ -58,7 +56,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.AreEqual(false, beatmapInfo.Countdown); Assert.AreEqual(false, beatmapInfo.Countdown);
Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency);
Assert.AreEqual(false, beatmapInfo.SpecialStyle); Assert.AreEqual(false, beatmapInfo.SpecialStyle);
Assert.IsTrue(beatmapInfo.Ruleset is OsuRuleset); Assert.IsTrue(beatmapInfo.Ruleset.CreateInstance() is OsuRuleset);
Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks); Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks);
Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard); Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard);
} }

View File

@ -12,11 +12,7 @@ using osu.Framework.Desktop.Platform;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.IPC; 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.Osu;
using osu.Game.Modes.Taiko;
namespace osu.Game.Tests.Beatmaps.IO namespace osu.Game.Tests.Beatmaps.IO
{ {
@ -25,15 +21,6 @@ namespace osu.Game.Tests.Beatmaps.IO
{ {
private const string osz_path = @"../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz"; private const string osz_path = @"../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz";
[OneTimeSetUp]
public void SetUp()
{
RulesetCollection.Register(typeof(OsuRuleset));
RulesetCollection.Register(typeof(TaikoRuleset));
RulesetCollection.Register(typeof(ManiaRuleset));
RulesetCollection.Register(typeof(CatchRuleset));
}
[Test] [Test]
public void TestImportWhenClosed() public void TestImportWhenClosed()
{ {
@ -166,7 +153,7 @@ namespace osu.Game.Tests.Beatmaps.IO
Assert.IsTrue(set.Beatmaps.Count > 0); Assert.IsTrue(set.Beatmaps.Count > 0);
var beatmap = osu.Dependencies.Get<BeatmapDatabase>().GetWorkingBeatmap(set.Beatmaps.First(b => b.Ruleset is OsuRuleset))?.Beatmap; var beatmap = osu.Dependencies.Get<BeatmapDatabase>().GetWorkingBeatmap(set.Beatmaps.First(b => b.Ruleset.CreateInstance() is OsuRuleset))?.Beatmap;
Assert.IsTrue(beatmap?.HitObjects.Count > 0); Assert.IsTrue(beatmap?.HitObjects.Count > 0);
} }

View File

@ -4,8 +4,6 @@
using System.IO; using System.IO;
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Beatmaps.IO; using osu.Game.Beatmaps.IO;
using osu.Game.Modes;
using osu.Game.Modes.Osu;
using osu.Game.Tests.Resources; using osu.Game.Tests.Resources;
using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Formats;
using osu.Game.Database; using osu.Game.Database;
@ -19,7 +17,6 @@ namespace osu.Game.Tests.Beatmaps.IO
public void SetUp() public void SetUp()
{ {
OszArchiveReader.Register(); OszArchiveReader.Register();
RulesetCollection.Register(typeof(OsuRuleset));
} }
[Test] [Test]

View File

@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps
/// Calculates the star difficulty for this Beatmap. /// Calculates the star difficulty for this Beatmap.
/// </summary> /// </summary>
/// <returns>The star difficulty.</returns> /// <returns>The star difficulty.</returns>
public double CalculateStarDifficulty() => BeatmapInfo.Ruleset.CreateDifficultyCalculator(this).Calculate(); public double CalculateStarDifficulty() => BeatmapInfo.Ruleset.CreateInstance().CreateDifficultyCalculator(this).Calculate();
/// <summary> /// <summary>
/// Constructs a new beatmap. /// Constructs a new beatmap.

View File

@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps.Drawables
Origin = Anchor.Centre, Origin = Anchor.Centre,
TextSize = Size.X, TextSize = Size.X,
Colour = Color4.White, Colour = Color4.White,
Icon = beatmap.Ruleset.Icon Icon = beatmap.Ruleset.CreateInstance().Icon
} }
}; };
} }

View File

@ -83,7 +83,7 @@ namespace osu.Game.Beatmaps.Formats
beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo); beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo);
break; break;
case @"Mode": case @"Mode":
beatmap.BeatmapInfo.Mode = int.Parse(val); beatmap.BeatmapInfo.RulesetID = int.Parse(val);
break; break;
case @"LetterboxInBreaks": case @"LetterboxInBreaks":
beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1; beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1;

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Platform; using osu.Framework.Platform;
@ -77,6 +76,8 @@ namespace osu.Game.Database
public override void Reset() public override void Reset()
{ {
Storage.DeleteDatabase(@"beatmaps");
foreach (var setInfo in Query<BeatmapSetInfo>()) foreach (var setInfo in Query<BeatmapSetInfo>())
{ {
if (Storage.Exists(setInfo.Path)) if (Storage.Exists(setInfo.Path))
@ -89,6 +90,13 @@ namespace osu.Game.Database
Connection.DeleteAll<BeatmapInfo>(); Connection.DeleteAll<BeatmapInfo>();
} }
protected override Type[] ValidTypes => new[] {
typeof(BeatmapSetInfo),
typeof(BeatmapInfo),
typeof(BeatmapMetadata),
typeof(BeatmapDifficulty),
};
/// <summary> /// <summary>
/// Import multiple <see cref="BeatmapSetInfo"/> from <paramref name="paths"/>. /// Import multiple <see cref="BeatmapSetInfo"/> from <paramref name="paths"/>.
/// </summary> /// </summary>
@ -275,47 +283,6 @@ namespace osu.Game.Database
return working; return working;
} }
public TableQuery<T> Query<T>() where T : class
{
return Connection.Table<T>();
}
public T GetWithChildren<T>(object id) where T : class
{
return Connection.GetWithChildren<T>(id);
}
public List<T> GetAllWithChildren<T>(Expression<Func<T, bool>> filter = null, bool recursive = true)
where T : class
{
return Connection.GetAllWithChildren(filter, recursive);
}
public T GetChildren<T>(T item, bool recursive = false)
{
if (item == null) return default(T);
Connection.GetChildren(item, recursive);
return item;
}
private readonly Type[] validTypes = {
typeof(BeatmapSetInfo),
typeof(BeatmapInfo),
typeof(BeatmapMetadata),
typeof(BeatmapDifficulty),
};
public void Update<T>(T record, bool cascade = true) where T : class
{
if (validTypes.All(t => t != typeof(T)))
throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T));
if (cascade)
Connection.UpdateWithChildren(record);
else
Connection.Update(record);
}
public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path); public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path);
} }
} }

View File

@ -3,7 +3,6 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.IO.Serialization; using osu.Game.IO.Serialization;
using osu.Game.Modes;
using SQLite.Net.Attributes; using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes; using SQLiteNetExtensions.Attributes;
using System; using System;
@ -55,15 +54,12 @@ namespace osu.Game.Database
public float StackLeniency { get; set; } public float StackLeniency { get; set; }
public bool SpecialStyle { get; set; } public bool SpecialStyle { get; set; }
public int Mode { get; set; } [ForeignKey(typeof(RulesetInfo))]
public int RulesetID { get; set; }
[OneToOne(CascadeOperations = CascadeOperation.All)]
public RulesetInfo Ruleset { get; set; }
[Ignore]
public Ruleset Ruleset
{
get { return RulesetCollection.GetRuleset(Mode); }
set { Mode = RulesetCollection.GetId(value); }
}
public bool LetterboxInBreaks { get; set; } public bool LetterboxInBreaks { get; set; }
public bool WidescreenStoryboard { get; set; } public bool WidescreenStoryboard { get; set; }

View File

@ -2,9 +2,13 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Platform; using osu.Framework.Platform;
using SQLite.Net; using SQLite.Net;
using SQLiteNetExtensions.Extensions;
namespace osu.Game.Database namespace osu.Game.Database
{ {
@ -24,8 +28,7 @@ namespace osu.Game.Database
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database..."); Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database...");
storage.DeleteDatabase(@"beatmaps");
Reset(); Reset();
Prepare(); Prepare();
} }
@ -40,5 +43,41 @@ namespace osu.Game.Database
/// Reset this database to a default state. Undo all changes to database and storage backings. /// Reset this database to a default state. Undo all changes to database and storage backings.
/// </summary> /// </summary>
public abstract void Reset(); public abstract void Reset();
public TableQuery<T> Query<T>() where T : class
{
return Connection.Table<T>();
}
public T GetWithChildren<T>(object id) where T : class
{
return Connection.GetWithChildren<T>(id);
}
public List<T> GetAllWithChildren<T>(Expression<Func<T, bool>> filter = null, bool recursive = true)
where T : class
{
return Connection.GetAllWithChildren(filter, recursive);
}
public T GetChildren<T>(T item, bool recursive = false)
{
if (item == null) return default(T);
Connection.GetChildren(item, recursive);
return item;
}
protected abstract Type[] ValidTypes { get; }
public void Update<T>(T record, bool cascade = true) where T : class
{
if (ValidTypes.All(t => t != typeof(T)))
throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T));
if (cascade)
Connection.UpdateWithChildren(record);
else
Connection.Update(record);
}
} }
} }

View File

@ -0,0 +1,107 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using osu.Framework.Platform;
using osu.Game.Modes;
using SQLite.Net;
namespace osu.Game.Database
{
/// <summary>
/// Todo: All of this needs to be moved to a RulesetDatabase.
/// </summary>
public class RulesetDatabase : Database
{
public IEnumerable<RulesetInfo> AllRulesets => Query<RulesetInfo>().Where(r => r.Available);
public RulesetDatabase(Storage storage, SQLiteConnection connection)
: base(storage, connection)
{
}
protected override void Prepare()
{
Connection.CreateTable<RulesetInfo>();
List<Ruleset> instances = new List<Ruleset>();
foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, @"osu.Game.Modes.*.dll"))
{
try
{
var assembly = Assembly.LoadFile(file);
var rulesets = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Ruleset)));
if (rulesets.Count() != 1)
continue;
Assembly.LoadFile(file);
foreach (Type rulesetType in rulesets)
instances.Add((Ruleset)Activator.CreateInstance(rulesetType));
}
catch (Exception) { }
}
Connection.BeginTransaction();
//add all legacy modes in correct order
foreach (var r in instances.Where(r => r.LegacyID >= 0).OrderBy(r => r.LegacyID))
{
Connection.InsertOrReplace(createRulesetInfo(r));
}
//add any other modes
foreach (var r in instances.Where(r => r.LegacyID < 0))
{
var us = createRulesetInfo(r);
var existing = Query<RulesetInfo>().FirstOrDefault(ri => ri.InstantiationInfo == us.InstantiationInfo);
if (existing == null)
Connection.Insert(us);
}
//perform a consistency check
foreach (var r in Query<RulesetInfo>())
{
try
{
r.CreateInstance();
r.Available = true;
}
catch
{
r.Available = false;
}
Connection.Update(r);
}
Connection.Commit();
}
private RulesetInfo createRulesetInfo(Ruleset ruleset) => new RulesetInfo
{
Name = ruleset.Description,
InstantiationInfo = ruleset.GetType().AssemblyQualifiedName,
ID = ruleset.LegacyID
};
public override void Reset()
{
Connection.DeleteAll<RulesetInfo>();
}
protected override Type[] ValidTypes => new[] { typeof(RulesetInfo) };
public RulesetInfo GetRuleset(int id) => Query<RulesetInfo>().First(r => r.ID == id);
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Game.Modes;
using SQLite.Net.Attributes;
namespace osu.Game.Database
{
public class RulesetInfo
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
public string InstantiationInfo { get; set; }
[Indexed]
public bool Available { get; set; }
public Ruleset CreateInstance() => (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo));
}
}

View File

@ -7,7 +7,6 @@ using System.Linq;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game.IO.Legacy; using osu.Game.IO.Legacy;
using osu.Game.IPC; using osu.Game.IPC;
using osu.Game.Modes;
using osu.Game.Modes.Scoring; using osu.Game.Modes.Scoring;
using SharpCompress.Compressors.LZMA; using SharpCompress.Compressors.LZMA;
using SQLite.Net; using SQLite.Net;
@ -17,17 +16,20 @@ namespace osu.Game.Database
public class ScoreDatabase : Database public class ScoreDatabase : Database
{ {
private readonly Storage storage; private readonly Storage storage;
private readonly BeatmapDatabase beatmaps; private readonly BeatmapDatabase beatmaps;
private readonly RulesetDatabase rulesets;
private const string replay_folder = @"replays"; private const string replay_folder = @"replays";
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
private ScoreIPCChannel ipc; private ScoreIPCChannel ipc;
public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null) : base(storage, connection) public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null, RulesetDatabase rulesets = null) : base(storage, connection)
{ {
this.storage = storage; this.storage = storage;
this.beatmaps = beatmaps; this.beatmaps = beatmaps;
this.rulesets = rulesets;
if (importHost != null) if (importHost != null)
ipc = new ScoreIPCChannel(importHost, this); ipc = new ScoreIPCChannel(importHost, this);
@ -40,7 +42,7 @@ namespace osu.Game.Database
using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename)))
using (SerializationReader sr = new SerializationReader(s)) using (SerializationReader sr = new SerializationReader(s))
{ {
var ruleset = RulesetCollection.GetRuleset(sr.ReadByte()); var ruleset = rulesets.GetRuleset(sr.ReadByte()).CreateInstance();
score = ruleset.CreateScoreProcessor().CreateScore(); score = ruleset.CreateScoreProcessor().CreateScore();
/* score.Pass = true;*/ /* score.Pass = true;*/
@ -116,5 +118,7 @@ namespace osu.Game.Database
public override void Reset() public override void Reset()
{ {
} }
protected override Type[] ValidTypes => new[] { typeof(Score) };
} }
} }

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics;
namespace osu.Game.Modes
{
public class BeatmapStatistic
{
public FontAwesome Icon;
public string Content;
public string Name;
}
}

View File

@ -11,13 +11,6 @@ using osu.Game.Modes.Scoring;
namespace osu.Game.Modes namespace osu.Game.Modes
{ {
public class BeatmapStatistic
{
public FontAwesome Icon;
public string Content;
public string Name;
}
public abstract class Ruleset public abstract class Ruleset
{ {
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
@ -35,5 +28,10 @@ namespace osu.Game.Modes
public abstract string Description { get; } public abstract string Description { get; }
public abstract IEnumerable<KeyCounter> CreateGameplayKeys(); public abstract IEnumerable<KeyCounter> CreateGameplayKeys();
/// <summary>
/// Do not override this unless you are a legacy mode.
/// </summary>
public virtual int LegacyID => -1;
} }
} }

View File

@ -1,42 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace osu.Game.Modes
{
/// <summary>
/// Todo: All of this needs to be moved to a RulesetDatabase.
/// </summary>
public static class RulesetCollection
{
private static readonly ConcurrentDictionary<int, Ruleset> available_rulesets = new ConcurrentDictionary<int, Ruleset>();
public static void Register(Type type)
{
var ruleset = Activator.CreateInstance(type) as Ruleset;
if (ruleset == null)
return;
available_rulesets.TryAdd(available_rulesets.Count, ruleset);
}
public static Ruleset GetRuleset(int rulesetId)
{
Ruleset ruleset;
if (!available_rulesets.TryGetValue(rulesetId, out ruleset))
return null;
return ruleset;
}
public static int GetId(Ruleset ruleset) => available_rulesets.First(kvp => kvp.Value == ruleset).Key;
public static IEnumerable<Ruleset> AllRulesets => available_rulesets.Values;
}
}

View File

@ -15,7 +15,6 @@ using osu.Framework.Logging;
using osu.Game.Graphics.UserInterface.Volume; using osu.Game.Graphics.UserInterface.Volume;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Modes;
using osu.Game.Overlays.Toolbar; using osu.Game.Overlays.Toolbar;
using osu.Game.Screens; using osu.Game.Screens;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
@ -24,6 +23,7 @@ using System.Linq;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Game.Database;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Modes.Scoring; using osu.Game.Modes.Scoring;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
@ -59,7 +59,7 @@ namespace osu.Game
private VolumeControl volume; private VolumeControl volume;
private Bindable<int> configRuleset; private Bindable<int> configRuleset;
public Bindable<Ruleset> Ruleset = new Bindable<Ruleset>(); public Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
private readonly string[] args; private readonly string[] args;
@ -90,8 +90,8 @@ namespace osu.Game
Dependencies.Cache(this); Dependencies.Cache(this);
configRuleset = LocalConfig.GetBindable<int>(OsuConfig.Ruleset); configRuleset = LocalConfig.GetBindable<int>(OsuConfig.Ruleset);
Ruleset.Value = RulesetCollection.GetRuleset(configRuleset.Value); Ruleset.Value = RulesetDatabase.GetRuleset(configRuleset.Value);
Ruleset.ValueChanged += r => configRuleset.Value = RulesetCollection.GetId(r); Ruleset.ValueChanged += r => configRuleset.Value = r.ID;
} }
private ScheduledDelegate scoreLoad; private ScheduledDelegate scoreLoad;

View File

@ -28,6 +28,8 @@ namespace osu.Game
protected BeatmapDatabase BeatmapDatabase; protected BeatmapDatabase BeatmapDatabase;
protected RulesetDatabase RulesetDatabase;
protected ScoreDatabase ScoreDatabase; protected ScoreDatabase ScoreDatabase;
protected override string MainResourceFile => @"osu.Game.Resources.dll"; protected override string MainResourceFile => @"osu.Game.Resources.dll";
@ -85,6 +87,7 @@ namespace osu.Game
SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); SQLiteConnection connection = Host.Storage.GetDatabase(@"client");
Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, Host)); Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, Host));
Dependencies.Cache(RulesetDatabase = new RulesetDatabase(Host.Storage, connection));
Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase)); Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase));
Dependencies.Cache(new OsuColour()); Dependencies.Cache(new OsuColour());

View File

@ -13,11 +13,11 @@ using osu.Framework.Graphics.Sprites;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Modes;
using osu.Game.Modes.Mods; using osu.Game.Modes.Mods;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Database;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
@ -37,12 +37,14 @@ namespace osu.Game.Overlays.Mods
public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>(); public readonly Bindable<IEnumerable<Mod>> SelectedMods = new Bindable<IEnumerable<Mod>>();
public readonly Bindable<Ruleset> Ruleset = new Bindable<Ruleset>(RulesetCollection.GetRuleset(0)); public readonly Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
private void rulesetChanged(Ruleset newRuleset) private void rulesetChanged(RulesetInfo newRuleset)
{ {
var instance = newRuleset.CreateInstance();
foreach (ModSection section in modSectionsContainer.Children) foreach (ModSection section in modSectionsContainer.Children)
section.Buttons = newRuleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); section.Buttons = instance.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray();
refreshSelectedMods(); refreshSelectedMods();
} }

View File

@ -6,9 +6,9 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Game.Database;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Modes;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Options
public class OptionsFooter : FillFlowContainer public class OptionsFooter : FillFlowContainer
{ {
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuGameBase game, OsuColour colours) private void load(OsuGameBase game, OsuColour colours, RulesetDatabase rulesets)
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
@ -26,11 +26,11 @@ namespace osu.Game.Overlays.Options
var modes = new List<Drawable>(); var modes = new List<Drawable>();
foreach (var ruleset in RulesetCollection.AllRulesets) foreach (var ruleset in rulesets.AllRulesets)
{ {
modes.Add(new TextAwesome modes.Add(new TextAwesome
{ {
Icon = ruleset.Icon, Icon = ruleset.CreateInstance().Icon,
Colour = Color4.Gray, Colour = Color4.Gray,
TextSize = 20 TextSize = 20
}); });

View File

@ -8,8 +8,8 @@ using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Database;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Modes;
using OpenTK; using OpenTK;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Toolbar
public const float TOOLTIP_HEIGHT = 30; public const float TOOLTIP_HEIGHT = 30;
public Action OnHome; public Action OnHome;
public Action<Ruleset> OnRulesetChange; public Action<RulesetInfo> OnRulesetChange;
private readonly ToolbarModeSelector modeSelector; private readonly ToolbarModeSelector modeSelector;
private readonly ToolbarUserArea userArea; private readonly ToolbarUserArea userArea;
@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Toolbar
} }
} }
public void SetGameMode(Ruleset ruleset) => modeSelector.SetGameMode(ruleset); public void SetGameMode(RulesetInfo ruleset) => modeSelector.SetGameMode(ruleset);
protected override void PopIn() protected override void PopIn()
{ {

View File

@ -2,23 +2,26 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Modes; using osu.Game.Database;
using OpenTK.Graphics; using OpenTK.Graphics;
namespace osu.Game.Overlays.Toolbar namespace osu.Game.Overlays.Toolbar
{ {
public class ToolbarModeButton : ToolbarButton public class ToolbarModeButton : ToolbarButton
{ {
private Ruleset ruleset; private RulesetInfo ruleset;
public Ruleset Ruleset public RulesetInfo Ruleset
{ {
get { return ruleset; } get { return ruleset; }
set set
{ {
ruleset = value; ruleset = value;
TooltipMain = ruleset.Description;
TooltipSub = $"Play some {ruleset.Description}"; var rInstance = ruleset.CreateInstance();
Icon = ruleset.Icon;
TooltipMain = rInstance.Description;
TooltipSub = $"Play some {rInstance.Description}";
Icon = rInstance.Icon;
} }
} }

View File

@ -3,12 +3,13 @@
using System; using System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Caching; using osu.Framework.Caching;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Game.Modes; using osu.Game.Database;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Toolbar
private readonly Drawable modeButtonLine; private readonly Drawable modeButtonLine;
private ToolbarModeButton activeButton; private ToolbarModeButton activeButton;
public Action<Ruleset> OnRulesetChange; public Action<RulesetInfo> OnRulesetChange;
public ToolbarModeSelector() public ToolbarModeSelector()
{ {
@ -62,8 +63,12 @@ namespace osu.Game.Overlays.Toolbar
} }
} }
}; };
}
foreach (var ruleset in RulesetCollection.AllRulesets) [BackgroundDependencyLoader]
private void load(RulesetDatabase rulesets)
{
foreach (var ruleset in rulesets.AllRulesets)
{ {
modeButtons.Add(new ToolbarModeButton modeButtons.Add(new ToolbarModeButton
{ {
@ -84,11 +89,11 @@ namespace osu.Game.Overlays.Toolbar
Size = new Vector2(modeButtons.DrawSize.X, 1); Size = new Vector2(modeButtons.DrawSize.X, 1);
} }
public void SetGameMode(Ruleset ruleset) public void SetGameMode(RulesetInfo ruleset)
{ {
foreach (ToolbarModeButton m in modeButtons.Children.Cast<ToolbarModeButton>()) foreach (ToolbarModeButton m in modeButtons.Children.Cast<ToolbarModeButton>())
{ {
bool isActive = m.Ruleset == ruleset; bool isActive = m.Ruleset.ID == ruleset.ID;
m.Active = isActive; m.Active = isActive;
if (isActive) if (isActive)
activeButton = m; activeButton = m;

View File

@ -102,7 +102,7 @@ namespace osu.Game.Screens.Play
sourceClock.Reset(); sourceClock.Reset();
}); });
ruleset = Beatmap.BeatmapInfo.Ruleset; ruleset = Beatmap.BeatmapInfo.Ruleset.CreateInstance();
// Todo: This should be done as early as possible, and should check if the hit renderer // Todo: This should be done as early as possible, and should check if the hit renderer
// can actually convert the hit objects... Somehow... // can actually convert the hit objects... Somehow...

View File

@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select
})); }));
//get statistics fromt he current ruleset. //get statistics fromt he current ruleset.
labels.AddRange(beatmap.BeatmapInfo.Ruleset.GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); labels.AddRange(beatmap.BeatmapInfo.Ruleset.CreateInstance().GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s)));
} }
AlwaysPresent = true; AlwaysPresent = true;

View File

@ -16,7 +16,7 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Select.Filter; using osu.Game.Screens.Select.Filter;
using Container = osu.Framework.Graphics.Containers.Container; using Container = osu.Framework.Graphics.Containers.Container;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Modes; using osu.Game.Database;
namespace osu.Game.Screens.Select namespace osu.Game.Screens.Select
{ {
@ -163,7 +163,7 @@ namespace osu.Game.Screens.Select
searchTextBox.HoldFocus = true; searchTextBox.HoldFocus = true;
} }
private readonly Bindable<Ruleset> ruleset = new Bindable<Ruleset>(RulesetCollection.GetRuleset(0)); private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
[BackgroundDependencyLoader(permitNulls:true)] [BackgroundDependencyLoader(permitNulls:true)]
private void load(OsuColour colours, OsuGame osu) private void load(OsuColour colours, OsuGame osu)

View File

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Beatmaps.Drawables; using osu.Game.Beatmaps.Drawables;
using osu.Game.Modes; using osu.Game.Database;
using osu.Game.Screens.Select.Filter; using osu.Game.Screens.Select.Filter;
namespace osu.Game.Screens.Select namespace osu.Game.Screens.Select
@ -15,7 +15,7 @@ namespace osu.Game.Screens.Select
public GroupMode Group; public GroupMode Group;
public SortMode Sort; public SortMode Sort;
public string SearchText; public string SearchText;
public Ruleset Ruleset; public RulesetInfo Ruleset;
public void Filter(List<BeatmapGroup> groups) public void Filter(List<BeatmapGroup> groups)
{ {

View File

@ -20,7 +20,6 @@ using osu.Game.Beatmaps.Drawables;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Modes;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Backgrounds;
using osu.Game.Screens.Select.Options; using osu.Game.Screens.Select.Options;
@ -29,7 +28,7 @@ namespace osu.Game.Screens.Select
{ {
public abstract class SongSelect : OsuScreen public abstract class SongSelect : OsuScreen
{ {
private readonly Bindable<Ruleset> ruleset = new Bindable<Ruleset>(RulesetCollection.GetRuleset(0)); private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
private BeatmapDatabase database; private BeatmapDatabase database;
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap);

View File

@ -79,6 +79,7 @@
<Compile Include="Beatmaps\Timing\TimingInfo.cs" /> <Compile Include="Beatmaps\Timing\TimingInfo.cs" />
<Compile Include="Database\BeatmapMetrics.cs" /> <Compile Include="Database\BeatmapMetrics.cs" />
<Compile Include="Database\Database.cs" /> <Compile Include="Database\Database.cs" />
<Compile Include="Database\RulesetInfo.cs" />
<Compile Include="Database\ScoreDatabase.cs" /> <Compile Include="Database\ScoreDatabase.cs" />
<Compile Include="Graphics\Backgrounds\Triangles.cs" /> <Compile Include="Graphics\Backgrounds\Triangles.cs" />
<Compile Include="Graphics\Cursor\CursorTrail.cs" /> <Compile Include="Graphics\Cursor\CursorTrail.cs" />
@ -102,6 +103,7 @@
<Compile Include="IO\Legacy\SerializationWriter.cs" /> <Compile Include="IO\Legacy\SerializationWriter.cs" />
<Compile Include="IO\Serialization\IJsonSerializable.cs" /> <Compile Include="IO\Serialization\IJsonSerializable.cs" />
<Compile Include="IPC\ScoreIPCChannel.cs" /> <Compile Include="IPC\ScoreIPCChannel.cs" />
<Compile Include="Modes\BeatmapStatistic.cs" />
<Compile Include="Modes\Replays\Replay.cs" /> <Compile Include="Modes\Replays\Replay.cs" />
<Compile Include="Modes\Judgements\DrawableJudgement.cs" /> <Compile Include="Modes\Judgements\DrawableJudgement.cs" />
<Compile Include="Modes\Judgements\IPartialJudgement.cs" /> <Compile Include="Modes\Judgements\IPartialJudgement.cs" />
@ -133,7 +135,7 @@
<Compile Include="Modes\Objects\Legacy\LegacyHitObjectType.cs" /> <Compile Include="Modes\Objects\Legacy\LegacyHitObjectType.cs" />
<Compile Include="Modes\Replays\ReplayButtonState.cs" /> <Compile Include="Modes\Replays\ReplayButtonState.cs" />
<Compile Include="Modes\Replays\ReplayFrame.cs" /> <Compile Include="Modes\Replays\ReplayFrame.cs" />
<Compile Include="Modes\RulesetCollection.cs" /> <Compile Include="Database\RulesetDatabase.cs" />
<Compile Include="Modes\Scoring\Score.cs" /> <Compile Include="Modes\Scoring\Score.cs" />
<Compile Include="Modes\Scoring\ScoreProcessor.cs" /> <Compile Include="Modes\Scoring\ScoreProcessor.cs" />
<Compile Include="Modes\UI\HealthDisplay.cs" /> <Compile Include="Modes\UI\HealthDisplay.cs" />