From 59bfc7abad4c043fcae479017ad46c258e897018 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 04:53:37 +0900 Subject: [PATCH 01/22] Move statics to RulesetCollection to avoid conflicts later on. --- osu.Desktop.Tests/VisualTests.cs | 8 ++-- osu.Desktop.VisualTests/Program.cs | 8 ++-- osu.Desktop/Program.cs | 8 ++-- .../Beatmaps/Formats/OsuLegacyDecoderTest.cs | 2 +- .../Beatmaps/IO/ImportBeatmapTest.cs | 8 ++-- .../Beatmaps/IO/OszArchiveReaderTest.cs | 2 +- osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- osu.Game/Database/ScoreDatabase.cs | 2 +- osu.Game/Modes/Ruleset.cs | 17 -------- osu.Game/Modes/RulesetCollection.cs | 41 +++++++++++++++++++ osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- osu.Game/Overlays/Options/OptionsFooter.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/osu.Game.csproj | 1 + 16 files changed, 67 insertions(+), 42 deletions(-) create mode 100644 osu.Game/Modes/RulesetCollection.cs diff --git a/osu.Desktop.Tests/VisualTests.cs b/osu.Desktop.Tests/VisualTests.cs index 6519dbe917..36dce18b05 100644 --- a/osu.Desktop.Tests/VisualTests.cs +++ b/osu.Desktop.Tests/VisualTests.cs @@ -20,10 +20,10 @@ namespace osu.Desktop.Tests { using (var host = new HeadlessGameHost()) { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); + RulesetCollection.Register(typeof(OsuRuleset)); + RulesetCollection.Register(typeof(TaikoRuleset)); + RulesetCollection.Register(typeof(ManiaRuleset)); + RulesetCollection.Register(typeof(CatchRuleset)); host.Run(new AutomatedVisualTestGame()); } diff --git a/osu.Desktop.VisualTests/Program.cs b/osu.Desktop.VisualTests/Program.cs index fe1cdfd7f0..912034a927 100644 --- a/osu.Desktop.VisualTests/Program.cs +++ b/osu.Desktop.VisualTests/Program.cs @@ -21,10 +21,10 @@ namespace osu.Desktop.VisualTests using (GameHost host = Host.GetSuitableHost(@"osu")) { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); + RulesetCollection.Register(typeof(OsuRuleset)); + RulesetCollection.Register(typeof(TaikoRuleset)); + RulesetCollection.Register(typeof(ManiaRuleset)); + RulesetCollection.Register(typeof(CatchRuleset)); if (benchmark) host.Run(new AutomatedVisualTestGame()); diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index ddf58ac363..e9117cf533 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -41,10 +41,10 @@ namespace osu.Desktop } else { - Ruleset.Register(new OsuRuleset()); - Ruleset.Register(new TaikoRuleset()); - Ruleset.Register(new ManiaRuleset()); - Ruleset.Register(new CatchRuleset()); + RulesetCollection.Register(typeof(OsuRuleset)); + RulesetCollection.Register(typeof(TaikoRuleset)); + RulesetCollection.Register(typeof(ManiaRuleset)); + RulesetCollection.Register(typeof(CatchRuleset)); host.Run(new OsuGameDesktop(args)); } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 8183bc952e..59a5790bea 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Beatmaps.Formats public void SetUp() { OsuLegacyDecoder.Register(); - Ruleset.Register(new OsuRuleset()); + RulesetCollection.Register(typeof(OsuRuleset)); } [Test] diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 5d15b43761..66ed27adbb 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -28,10 +28,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()); + RulesetCollection.Register(typeof(OsuRuleset)); + RulesetCollection.Register(typeof(TaikoRuleset)); + RulesetCollection.Register(typeof(ManiaRuleset)); + RulesetCollection.Register(typeof(CatchRuleset)); } [Test] diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index b9c4cf780a..add00d8f4d 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Beatmaps.IO public void SetUp() { OszArchiveReader.Register(); - Ruleset.Register(new OsuRuleset()); + RulesetCollection.Register(typeof(OsuRuleset)); } [Test] diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 5709bdc8c5..420b23eb62 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps /// Calculates the star difficulty for this Beatmap. /// /// The star difficulty. - public double CalculateStarDifficulty() => Ruleset.GetRuleset(BeatmapInfo.Mode).CreateDifficultyCalculator(this).Calculate(); + public double CalculateStarDifficulty() => RulesetCollection.GetRuleset(BeatmapInfo.Mode).CreateDifficultyCalculator(this).Calculate(); /// /// Constructs a new beatmap. diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 47ae4d7985..3fb5194382 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -45,7 +45,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, TextSize = Size.X, Colour = Color4.White, - Icon = Ruleset.GetRuleset(beatmap.Mode).Icon + Icon = RulesetCollection.GetRuleset((int)beatmap.Mode).Icon } }; } diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index 642bb4aff6..e602b2373e 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -39,7 +39,7 @@ namespace osu.Game.Database using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) using (SerializationReader sr = new SerializationReader(s)) { - var ruleset = Ruleset.GetRuleset((PlayMode)sr.ReadByte()); + var ruleset = RulesetCollection.GetRuleset((PlayMode)sr.ReadByte()); score = ruleset.CreateScoreProcessor().CreateScore(); /* score.Pass = true;*/ diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index c97420fbe3..42f2fe789f 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -22,10 +22,6 @@ namespace osu.Game.Modes public abstract class Ruleset { - private static readonly ConcurrentDictionary available_rulesets = new ConcurrentDictionary(); - - public static IEnumerable PlayModes => available_rulesets.Keys; - public virtual IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; public abstract IEnumerable GetModsFor(ModType type); @@ -36,8 +32,6 @@ namespace osu.Game.Modes public abstract ScoreProcessor CreateScoreProcessor(); - public static void Register(Ruleset ruleset) => available_rulesets.TryAdd(ruleset.PlayMode, ruleset.GetType()); - protected abstract PlayMode PlayMode { get; } public virtual FontAwesome Icon => FontAwesome.fa_question_circle; @@ -45,16 +39,5 @@ namespace osu.Game.Modes public abstract string Description { get; } public abstract IEnumerable CreateGameplayKeys(); - - public static Ruleset GetRuleset(PlayMode mode) - { - Type type; - - if (!available_rulesets.TryGetValue(mode, out type)) - return null; - - return Activator.CreateInstance(type) as Ruleset; - } - } } diff --git a/osu.Game/Modes/RulesetCollection.cs b/osu.Game/Modes/RulesetCollection.cs new file mode 100644 index 0000000000..95d0df4e6a --- /dev/null +++ b/osu.Game/Modes/RulesetCollection.cs @@ -0,0 +1,41 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace osu.Game.Modes +{ + public static class RulesetCollection + { + private static readonly ConcurrentDictionary available_rulesets = new ConcurrentDictionary(); + + public static void Register(Type type) + { + Ruleset ruleset = Activator.CreateInstance(type) as Ruleset; + + if (ruleset == null) + return; + + available_rulesets.TryAdd(available_rulesets.Count, ruleset); + } + + public static Ruleset GetRuleset(PlayMode playMode) + { + return GetRuleset((int)playMode); + } + + public static Ruleset GetRuleset(int rulesetId) + { + Ruleset ruleset; + + if (!available_rulesets.TryGetValue(rulesetId, out ruleset)) + throw new InvalidOperationException($"Ruleset id {rulesetId} doesn't exist. How did you trigger this?"); + + return ruleset; + } + + public static IEnumerable AllRulesets => available_rulesets.Values; + } +} diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 2b9f8e86a9..7a21b36da9 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Mods private void modeChanged(PlayMode newMode) { - var ruleset = Ruleset.GetRuleset(newMode); + var ruleset = RulesetCollection.GetRuleset(newMode); foreach (ModSection section in modSectionsContainer.Children) section.Buttons = ruleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); refreshSelectedMods(); diff --git a/osu.Game/Overlays/Options/OptionsFooter.cs b/osu.Game/Overlays/Options/OptionsFooter.cs index c42fe42428..fde4d8a925 100644 --- a/osu.Game/Overlays/Options/OptionsFooter.cs +++ b/osu.Game/Overlays/Options/OptionsFooter.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Options foreach (PlayMode m in Enum.GetValues(typeof(PlayMode))) modes.Add(new TextAwesome { - Icon = Ruleset.GetRuleset(m).Icon, + Icon = RulesetCollection.GetRuleset(m).Icon, Colour = Color4.Gray, TextSize = 20 }); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fa564cdd61..e43eb6cd73 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Play sourceClock.Reset(); }); - ruleset = Ruleset.GetRuleset(Beatmap.PlayMode); + ruleset = RulesetCollection.GetRuleset(Beatmap.PlayMode); HitRenderer = ruleset.CreateHitRendererWith(Beatmap); scoreProcessor = HitRenderer.CreateScoreProcessor(); diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 768cef4645..586100c47d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select })); //get statistics fromt he current ruleset. - labels.AddRange(Ruleset.GetRuleset(beatmap.BeatmapInfo.Mode).GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); + labels.AddRange(RulesetCollection.GetRuleset(beatmap.BeatmapInfo.Mode).GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); } AlwaysPresent = true; diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f810eeec96..b89f7a3b65 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -131,6 +131,7 @@ + From a89af273be58b7b7388ef34edd9ad999d97e2cea Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 05:01:36 +0900 Subject: [PATCH 02/22] Make BeatmapInfo expose Ruleset instead of PlayMode. --- osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs | 7 +++---- osu.Desktop.VisualTests/Tests/TestCasePlayer.cs | 4 ++-- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 2 +- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- osu.Game/Database/BeatmapInfo.cs | 5 ++++- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/FilterCriteria.cs | 2 +- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 1a43425dda..4047c4b95f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -6,7 +6,6 @@ using osu.Desktop.VisualTests.Platform; using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Database; -using osu.Game.Modes; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; @@ -72,7 +71,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1234 + i, - Mode = PlayMode.Osu, + Mode = 0, Path = "normal.osu", Version = "Normal", Difficulty = new BeatmapDifficulty @@ -83,7 +82,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1235 + i, - Mode = PlayMode.Osu, + Mode = 0, Path = "hard.osu", Version = "Hard", Difficulty = new BeatmapDifficulty @@ -94,7 +93,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1236 + i, - Mode = PlayMode.Osu, + Mode = 0, Path = "insane.osu", Version = "Insane", Difficulty = new BeatmapDifficulty diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 624723ed35..2a9c31b2e9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -9,12 +9,12 @@ using osu.Game.Beatmaps; using OpenTK; using osu.Framework.Graphics.Sprites; using osu.Game.Database; -using osu.Game.Modes; using osu.Game.Modes.Objects; using osu.Game.Modes.Osu.Objects; using osu.Game.Screens.Play; using OpenTK.Graphics; using osu.Desktop.VisualTests.Beatmaps; +using osu.Game.Modes.Osu; namespace osu.Desktop.VisualTests.Tests { @@ -37,7 +37,7 @@ namespace osu.Desktop.VisualTests.Tests WorkingBeatmap beatmap = null; - var beatmapInfo = db.Query().FirstOrDefault(b => b.Mode == PlayMode.Osu); + var beatmapInfo = db.Query().FirstOrDefault(b => b.Ruleset is OsuRuleset); if (beatmapInfo != null) beatmap = db.GetWorkingBeatmap(beatmapInfo); diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 66ed27adbb..e110da59b9 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -166,7 +166,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.Mode == PlayMode.Osu))?.Beatmap; + var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.Ruleset is OsuRuleset))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); } diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 35d81311d2..4e39b48f96 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -84,7 +84,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo); break; case @"Mode": - beatmap.BeatmapInfo.Mode = (PlayMode)int.Parse(val); + beatmap.BeatmapInfo.Mode = int.Parse(val); break; case @"LetterboxInBreaks": beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 5bea1d0986..dd0bdef3b7 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -24,7 +24,7 @@ namespace osu.Game.Beatmaps /// public PlayMode? PreferredPlayMode; - public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > PlayMode.Osu ? Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu; + public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > (int)PlayMode.Osu ? (PlayMode)Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu; public readonly Bindable> Mods = new Bindable>(); diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index 3e84825919..72ff078d9e 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -54,7 +54,10 @@ namespace osu.Game.Database public bool Countdown { get; set; } public float StackLeniency { get; set; } public bool SpecialStyle { get; set; } - public PlayMode Mode { get; set; } + + public int Mode { get; set; } + public Ruleset Ruleset => RulesetCollection.GetRuleset(Mode); + public bool LetterboxInBreaks { get; set; } public bool WidescreenStoryboard { get; set; } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e43eb6cd73..134400d531 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -63,7 +63,7 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config) { - if (Beatmap.Beatmap.BeatmapInfo?.Mode > PlayMode.Taiko) + if (Beatmap.Beatmap.BeatmapInfo?.Mode > (int)PlayMode.Taiko) { //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. Exit(); diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 2654129a44..19d3645e45 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Select { var set = g.BeatmapSet; - bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Mode == Mode); + bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Mode == (int)Mode); bool match = hasCurrentMode; From 0a1376c2db4bbdd1a2b667843f4ec0ffaf39537f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 05:22:41 +0900 Subject: [PATCH 03/22] Remove PlayMode game-wide. --- .../Tests/TestCaseModSelectOverlay.cs | 7 +++---- osu.Game.Modes.Catch/CatchRuleset.cs | 2 -- osu.Game.Modes.Mania/ManiaRuleset.cs | 2 -- osu.Game.Modes.Osu/OsuRuleset.cs | 2 -- osu.Game.Modes.Taiko/TaikoRuleset.cs | 2 -- .../Beatmaps/Formats/OsuLegacyDecoderTest.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 8 -------- osu.Game/Configuration/OsuConfigManager.cs | 4 +--- osu.Game/Database/ScoreDatabase.cs | 2 +- osu.Game/Modes/PlayMode.cs | 13 ------------- osu.Game/Modes/Ruleset.cs | 2 -- osu.Game/Modes/RulesetCollection.cs | 5 ----- osu.Game/OsuGame.cs | 11 ++++++----- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 13 ++++++------- osu.Game/Overlays/Options/OptionsFooter.cs | 6 ++++-- osu.Game/Overlays/Toolbar/Toolbar.cs | 8 ++++---- osu.Game/Overlays/Toolbar/ToolbarModeButton.cs | 14 +++++++------- osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs | 14 +++++++------- osu.Game/Screens/Play/Player.cs | 9 +-------- osu.Game/Screens/Select/FilterControl.cs | 11 ++++++----- osu.Game/Screens/Select/FilterCriteria.cs | 4 ++-- osu.Game/Screens/Select/SongSelect.cs | 7 +++---- osu.Game/osu.Game.csproj | 1 - 23 files changed, 52 insertions(+), 97 deletions(-) delete mode 100644 osu.Game/Modes/PlayMode.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index 7677682ac8..c569f5f64a 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -26,10 +26,9 @@ namespace osu.Desktop.VisualTests.Tests }); AddStep("Toggle", modSelect.ToggleVisibility); - AddStep("osu!", () => modSelect.PlayMode.Value = PlayMode.Osu); - AddStep("osu!taiko", () => modSelect.PlayMode.Value = PlayMode.Taiko); - AddStep("osu!catch", () => modSelect.PlayMode.Value = PlayMode.Catch); - AddStep("osu!mania", () => modSelect.PlayMode.Value = PlayMode.Mania); + + foreach (var ruleset in RulesetCollection.AllRulesets) + AddStep(ruleset.Description, () => modSelect.Ruleset.Value = ruleset); } } } diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs index 09d8bdb9e5..02c170d0ac 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Modes.Catch/CatchRuleset.cs @@ -76,8 +76,6 @@ namespace osu.Game.Modes.Catch } } - protected override PlayMode PlayMode => PlayMode.Catch; - public override string Description => "osu!catch"; public override FontAwesome Icon => FontAwesome.fa_osu_fruits_o; diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs index bd995d87d6..7d25ea93c9 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Modes.Mania/ManiaRuleset.cs @@ -96,8 +96,6 @@ namespace osu.Game.Modes.Mania } } - protected override PlayMode PlayMode => PlayMode.Mania; - public override string Description => "osu!mania"; public override FontAwesome Icon => FontAwesome.fa_osu_mania_o; diff --git a/osu.Game.Modes.Osu/OsuRuleset.cs b/osu.Game.Modes.Osu/OsuRuleset.cs index 12df7d3f3c..6ca19bb5bb 100644 --- a/osu.Game.Modes.Osu/OsuRuleset.cs +++ b/osu.Game.Modes.Osu/OsuRuleset.cs @@ -99,8 +99,6 @@ namespace osu.Game.Modes.Osu public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new OsuDifficultyCalculator(beatmap); - protected override PlayMode PlayMode => PlayMode.Osu; - public override string Description => "osu!"; public override IEnumerable CreateGameplayKeys() => new KeyCounter[] diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index 1b3c3fc0eb..e88b50bb95 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -76,8 +76,6 @@ namespace osu.Game.Modes.Taiko } } - protected override PlayMode PlayMode => PlayMode.Taiko; - public override string Description => "osu!taiko"; public override FontAwesome Icon => FontAwesome.fa_osu_taiko_o; diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 59a5790bea..9d783c7e91 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(false, beatmapInfo.Countdown); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); Assert.AreEqual(false, beatmapInfo.SpecialStyle); - Assert.AreEqual(PlayMode.Osu, beatmapInfo.Mode); + Assert.IsTrue(beatmapInfo.Ruleset is OsuRuleset); Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks); Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard); } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index dd0bdef3b7..47f31ddffc 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -18,14 +18,6 @@ namespace osu.Game.Beatmaps public readonly BeatmapSetInfo BeatmapSetInfo; - /// - /// A play mode that is preferred for this beatmap. PlayMode will become this mode where conversion is feasible, - /// or otherwise to the beatmap's default. - /// - public PlayMode? PreferredPlayMode; - - public PlayMode PlayMode => Beatmap?.BeatmapInfo?.Mode > (int)PlayMode.Osu ? (PlayMode)Beatmap.BeatmapInfo.Mode : PreferredPlayMode ?? PlayMode.Osu; - public readonly Bindable> Mods = new Bindable>(); public readonly bool WithStoryboard; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index e2f33479c0..2f37717286 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -17,8 +17,6 @@ namespace osu.Game.Configuration Set(OsuConfig.Username, string.Empty); Set(OsuConfig.Token, string.Empty); - Set(OsuConfig.PlayMode, PlayMode.Osu); - Set(OsuConfig.AudioDevice, string.Empty); Set(OsuConfig.SavePassword, false); Set(OsuConfig.SaveUsername, true); @@ -196,7 +194,7 @@ namespace osu.Game.Configuration public enum OsuConfig { // New osu: - PlayMode, + Ruleset, Token, // Imported from old osu: BeatmapDirectory, diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index e602b2373e..3b5c0575d5 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -39,7 +39,7 @@ namespace osu.Game.Database using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) using (SerializationReader sr = new SerializationReader(s)) { - var ruleset = RulesetCollection.GetRuleset((PlayMode)sr.ReadByte()); + var ruleset = RulesetCollection.GetRuleset((int)sr.ReadByte()); score = ruleset.CreateScoreProcessor().CreateScore(); /* score.Pass = true;*/ diff --git a/osu.Game/Modes/PlayMode.cs b/osu.Game/Modes/PlayMode.cs deleted file mode 100644 index fa6d94a650..0000000000 --- a/osu.Game/Modes/PlayMode.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Modes -{ - public enum PlayMode - { - Osu = 0, - Taiko = 1, - Catch = 2, - Mania = 3 - } -} diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index 42f2fe789f..9a5099c675 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -32,8 +32,6 @@ namespace osu.Game.Modes public abstract ScoreProcessor CreateScoreProcessor(); - protected abstract PlayMode PlayMode { get; } - public virtual FontAwesome Icon => FontAwesome.fa_question_circle; public abstract string Description { get; } diff --git a/osu.Game/Modes/RulesetCollection.cs b/osu.Game/Modes/RulesetCollection.cs index 95d0df4e6a..a8cb8f8e26 100644 --- a/osu.Game/Modes/RulesetCollection.cs +++ b/osu.Game/Modes/RulesetCollection.cs @@ -21,11 +21,6 @@ namespace osu.Game.Modes available_rulesets.TryAdd(available_rulesets.Count, ruleset); } - public static Ruleset GetRuleset(PlayMode playMode) - { - return GetRuleset((int)playMode); - } - public static Ruleset GetRuleset(int rulesetId) { Ruleset ruleset; diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ccea6ef458..44c1188ab3 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -58,7 +58,7 @@ namespace osu.Game private VolumeControl volume; - public Bindable PlayMode; + public Bindable Ruleset; private readonly string[] args; @@ -88,7 +88,8 @@ namespace osu.Game Dependencies.Cache(this); - PlayMode = LocalConfig.GetBindable(OsuConfig.PlayMode); + // Todo: I don't think this'll work, need BindableRuleset + Ruleset = new Bindable(); } private ScheduledDelegate scoreLoad; @@ -199,11 +200,11 @@ namespace osu.Game { Depth = -3, OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); }, - OnPlayModeChange = m => PlayMode.Value = m, + OnRulesetChange = r => Ruleset.Value = r, }, t => { - PlayMode.ValueChanged += delegate { Toolbar.SetGameMode(PlayMode.Value); }; - PlayMode.TriggerChange(); + Ruleset.ValueChanged += delegate { Toolbar.SetGameMode(Ruleset.Value); }; + Ruleset.TriggerChange(); overlayContent.Add(Toolbar); }); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 7a21b36da9..5041ab237c 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -37,13 +37,12 @@ namespace osu.Game.Overlays.Mods public readonly Bindable> SelectedMods = new Bindable>(); - public readonly Bindable PlayMode = new Bindable(); + public readonly Bindable Ruleset = new Bindable(); - private void modeChanged(PlayMode newMode) + private void rulesetChanged(Ruleset newRuleset) { - var ruleset = RulesetCollection.GetRuleset(newMode); foreach (ModSection section in modSectionsContainer.Children) - section.Buttons = ruleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); + section.Buttons = newRuleset.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray(); refreshSelectedMods(); } @@ -54,9 +53,9 @@ namespace osu.Game.Overlays.Mods highMultiplierColour = colours.Green; if (osu != null) - PlayMode.BindTo(osu.PlayMode); - PlayMode.ValueChanged += modeChanged; - PlayMode.TriggerChange(); + Ruleset.BindTo(osu.Ruleset); + Ruleset.ValueChanged += rulesetChanged; + Ruleset.TriggerChange(); } protected override void PopOut() diff --git a/osu.Game/Overlays/Options/OptionsFooter.cs b/osu.Game/Overlays/Options/OptionsFooter.cs index fde4d8a925..d68fe18f36 100644 --- a/osu.Game/Overlays/Options/OptionsFooter.cs +++ b/osu.Game/Overlays/Options/OptionsFooter.cs @@ -27,13 +27,15 @@ namespace osu.Game.Overlays.Options var modes = new List(); - foreach (PlayMode m in Enum.GetValues(typeof(PlayMode))) + foreach (var ruleset in RulesetCollection.AllRulesets) + { modes.Add(new TextAwesome { - Icon = RulesetCollection.GetRuleset(m).Icon, + Icon = ruleset.Icon, Colour = Color4.Gray, TextSize = 20 }); + } Children = new Drawable[] { diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index 9e7b4f1519..ec76a37e6e 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Toolbar public const float TOOLTIP_HEIGHT = 30; public Action OnHome; - public Action OnPlayModeChange; + public Action OnRulesetChange; private readonly ToolbarModeSelector modeSelector; private readonly ToolbarUserArea userArea; @@ -55,9 +55,9 @@ namespace osu.Game.Overlays.Toolbar }, modeSelector = new ToolbarModeSelector { - OnPlayModeChange = mode => + OnRulesetChange = mode => { - OnPlayModeChange?.Invoke(mode); + OnRulesetChange?.Invoke(mode); } } } @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Toolbar } } - public void SetGameMode(PlayMode mode) => modeSelector.SetGameMode(mode); + public void SetGameMode(Ruleset ruleset) => modeSelector.SetGameMode(ruleset); protected override void PopIn() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index 62359b05ae..6ace90bcb4 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -9,16 +9,16 @@ namespace osu.Game.Overlays.Toolbar { public class ToolbarModeButton : ToolbarButton { - private PlayMode mode; - public PlayMode Mode + private Ruleset ruleset; + public Ruleset Ruleset { - get { return mode; } + get { return ruleset; } set { - mode = value; - TooltipMain = Ruleset.GetRuleset(mode).Description; - TooltipSub = $"Play some {Ruleset.GetRuleset(mode).Description}"; - Icon = Ruleset.GetRuleset(mode).Icon; + ruleset = value; + TooltipMain = ruleset.Description; + TooltipSub = $"Play some {ruleset.Description}"; + Icon = ruleset.Icon; } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index e117089166..0d673eb3fe 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Toolbar private readonly Drawable modeButtonLine; private ToolbarModeButton activeButton; - public Action OnPlayModeChange; + public Action OnRulesetChange; public ToolbarModeSelector() { @@ -63,15 +63,15 @@ namespace osu.Game.Overlays.Toolbar } }; - foreach (PlayMode m in Ruleset.PlayModes) + foreach (var ruleset in RulesetCollection.AllRulesets) { modeButtons.Add(new ToolbarModeButton { - Mode = m, + Ruleset = ruleset, Action = delegate { - SetGameMode(m); - OnPlayModeChange?.Invoke(m); + SetGameMode(ruleset); + OnRulesetChange?.Invoke(ruleset); } }); } @@ -84,11 +84,11 @@ namespace osu.Game.Overlays.Toolbar Size = new Vector2(modeButtons.DrawSize.X, 1); } - public void SetGameMode(PlayMode mode) + public void SetGameMode(Ruleset ruleset) { foreach (ToolbarModeButton m in modeButtons.Children.Cast()) { - bool isActive = m.Mode == mode; + bool isActive = m.Ruleset == ruleset; m.Active = isActive; if (isActive) activeButton = m; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 134400d531..2887e7fa70 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -63,13 +63,6 @@ namespace osu.Game.Screens.Play [BackgroundDependencyLoader] private void load(AudioManager audio, BeatmapDatabase beatmaps, OsuConfigManager config) { - if (Beatmap.Beatmap.BeatmapInfo?.Mode > (int)PlayMode.Taiko) - { - //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor. - Exit(); - return; - } - dimLevel = config.GetBindable(OsuConfig.DimLevel); mouseWheelDisabled = config.GetBindable(OsuConfig.MouseDisableWheel); @@ -109,7 +102,7 @@ namespace osu.Game.Screens.Play sourceClock.Reset(); }); - ruleset = RulesetCollection.GetRuleset(Beatmap.PlayMode); + ruleset = Beatmap.BeatmapInfo.Ruleset; HitRenderer = ruleset.CreateHitRendererWith(Beatmap); scoreProcessor = HitRenderer.CreateScoreProcessor(); diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 7596af1484..b2c53c9126 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -61,7 +61,7 @@ namespace osu.Game.Screens.Select Group = group, Sort = sort, SearchText = searchTextBox.Text, - Mode = playMode + Ruleset = ruleset }; public Action Exit; @@ -163,16 +163,17 @@ namespace osu.Game.Screens.Select searchTextBox.HoldFocus = true; } - private readonly Bindable playMode = new Bindable(); + private readonly Bindable ruleset = new Bindable(); [BackgroundDependencyLoader(permitNulls:true)] private void load(OsuColour colours, OsuGame osu) { sortTabs.AccentColour = colours.GreenLight; - if (osu != null) playMode.BindTo(osu.PlayMode); - playMode.ValueChanged += val => FilterChanged?.Invoke(CreateCriteria()); - playMode.TriggerChange(); + if (osu != null) + ruleset.BindTo(osu.Ruleset); + ruleset.ValueChanged += val => FilterChanged?.Invoke(CreateCriteria()); + ruleset.TriggerChange(); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 19d3645e45..0b750ef8d3 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; public string SearchText; - public PlayMode Mode; + public Ruleset Ruleset; public void Filter(List groups) { @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Select { var set = g.BeatmapSet; - bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Mode == (int)Mode); + bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Ruleset == Ruleset); bool match = hasCurrentMode; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 3e8ddc0f64..f25d3d4df9 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen { - private readonly Bindable playMode = new Bindable(); + private readonly Bindable ruleset = new Bindable(); private BeatmapDatabase database; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); @@ -170,8 +170,8 @@ namespace osu.Game.Screens.Select if (database == null) database = beatmaps; - playMode.ValueChanged += val => { if (Beatmap != null) Beatmap.PreferredPlayMode = val; }; - if (osu != null) playMode.BindTo(osu.PlayMode); + if (osu != null) + ruleset.BindTo(osu.Ruleset); database.BeatmapSetAdded += onBeatmapSetAdded; database.BeatmapSetRemoved += onBeatmapSetRemoved; @@ -200,7 +200,6 @@ namespace osu.Game.Screens.Select { if (Beatmap == null) return; - Beatmap.PreferredPlayMode = playMode.Value; OnSelected(); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b89f7a3b65..7d20668f26 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -217,7 +217,6 @@ - From 6dbc75283cdc8261812620bf61c3388f358c3490 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 05:52:46 +0900 Subject: [PATCH 04/22] Re-implement config value. --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Modes/RulesetCollection.cs | 3 +++ osu.Game/OsuGame.cs | 8 +++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 2f37717286..8e82406dee 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -17,6 +17,8 @@ namespace osu.Game.Configuration Set(OsuConfig.Username, string.Empty); Set(OsuConfig.Token, string.Empty); + Set(OsuConfig.Ruleset, 0, 0, int.MaxValue); + Set(OsuConfig.AudioDevice, string.Empty); Set(OsuConfig.SavePassword, false); Set(OsuConfig.SaveUsername, true); diff --git a/osu.Game/Modes/RulesetCollection.cs b/osu.Game/Modes/RulesetCollection.cs index a8cb8f8e26..d699bbfabe 100644 --- a/osu.Game/Modes/RulesetCollection.cs +++ b/osu.Game/Modes/RulesetCollection.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Modes { @@ -31,6 +32,8 @@ namespace osu.Game.Modes return ruleset; } + public static int GetId(Ruleset ruleset) => available_rulesets.First(kvp => kvp.Value == ruleset).Key; + public static IEnumerable AllRulesets => available_rulesets.Values; } } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 44c1188ab3..3379787d6d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -58,7 +58,8 @@ namespace osu.Game private VolumeControl volume; - public Bindable Ruleset; + private Bindable configRuleset; + public Bindable Ruleset = new Bindable(); private readonly string[] args; @@ -88,8 +89,9 @@ namespace osu.Game Dependencies.Cache(this); - // Todo: I don't think this'll work, need BindableRuleset - Ruleset = new Bindable(); + configRuleset = LocalConfig.GetBindable(OsuConfig.Ruleset); + Ruleset.Value = RulesetCollection.GetRuleset(configRuleset.Value); + Ruleset.ValueChanged += r => configRuleset.Value = RulesetCollection.GetId(r); } private ScheduledDelegate scoreLoad; From 3845ab2a72c91247d319c3ea9a366596f1aa5dcd Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 05:55:38 +0900 Subject: [PATCH 05/22] Add comment. --- osu.Game/Screens/Play/Player.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2887e7fa70..b59b3bf0c1 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -103,6 +103,9 @@ namespace osu.Game.Screens.Play }); ruleset = Beatmap.BeatmapInfo.Ruleset; + + // Todo: This should be done as early as possible, and should check if the hit renderer + // can actually convert the hit objects... Somehow... HitRenderer = ruleset.CreateHitRendererWith(Beatmap); scoreProcessor = HitRenderer.CreateScoreProcessor(); From 0333e1a05003d2f30ebba3ff288101c0e66b5b47 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 05:57:18 +0900 Subject: [PATCH 06/22] Remove unused usings. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 1 - osu.Game/Beatmaps/WorkingBeatmap.cs | 1 - osu.Game/Configuration/OsuConfigManager.cs | 1 - osu.Game/Modes/Ruleset.cs | 2 -- osu.Game/Overlays/Options/OptionsFooter.cs | 1 - 5 files changed, 6 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 4e39b48f96..36f025d1ff 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -7,7 +7,6 @@ using System.IO; using OpenTK.Graphics; using osu.Game.Beatmaps.Events; using osu.Game.Beatmaps.Timing; -using osu.Game.Modes; using osu.Game.Modes.Objects; using osu.Game.Beatmaps.Legacy; diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 47f31ddffc..8ffec25882 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -5,7 +5,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Configuration; using osu.Framework.Graphics.Textures; using osu.Game.Database; -using osu.Game.Modes; using osu.Game.Modes.Mods; using System; using System.Collections.Generic; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 8e82406dee..a31c1f882d 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -4,7 +4,6 @@ using System; using osu.Framework.Configuration; using osu.Framework.Platform; -using osu.Game.Modes; namespace osu.Game.Configuration { diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index 9a5099c675..284a71d518 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -6,8 +6,6 @@ using osu.Game.Graphics; using osu.Game.Modes.Mods; using osu.Game.Modes.UI; using osu.Game.Screens.Play; -using System; -using System.Collections.Concurrent; using System.Collections.Generic; using osu.Game.Modes.Scoring; diff --git a/osu.Game/Overlays/Options/OptionsFooter.cs b/osu.Game/Overlays/Options/OptionsFooter.cs index d68fe18f36..ad184c8838 100644 --- a/osu.Game/Overlays/Options/OptionsFooter.cs +++ b/osu.Game/Overlays/Options/OptionsFooter.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Graphics; From 4a149c4ab80c0f435543691cf6c80b67315d2391 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 06:14:31 +0900 Subject: [PATCH 07/22] Better default values + don't set Mode from outside. --- osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs | 7 ++++--- osu.Game/Database/BeatmapInfo.cs | 8 +++++++- osu.Game/Modes/RulesetCollection.cs | 9 ++++++--- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 4047c4b95f..c22726491d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -8,6 +8,7 @@ using osu.Framework.MathUtils; using osu.Game.Database; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; +using osu.Game.Modes; namespace osu.Desktop.VisualTests.Tests { @@ -71,7 +72,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1234 + i, - Mode = 0, + Ruleset = RulesetCollection.GetRuleset(0), Path = "normal.osu", Version = "Normal", Difficulty = new BeatmapDifficulty @@ -82,7 +83,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1235 + i, - Mode = 0, + Ruleset = RulesetCollection.GetRuleset(0), Path = "hard.osu", Version = "Hard", Difficulty = new BeatmapDifficulty @@ -93,7 +94,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1236 + i, - Mode = 0, + Ruleset = RulesetCollection.GetRuleset(0), Path = "insane.osu", Version = "Insane", Difficulty = new BeatmapDifficulty diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index 72ff078d9e..be4faebde2 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -56,7 +56,13 @@ namespace osu.Game.Database public bool SpecialStyle { get; set; } public int Mode { get; set; } - public Ruleset Ruleset => RulesetCollection.GetRuleset(Mode); + + [Ignore] + public Ruleset Ruleset + { + get { return RulesetCollection.GetRuleset(Mode); } + set { Mode = RulesetCollection.GetId(value); } + } public bool LetterboxInBreaks { get; set; } public bool WidescreenStoryboard { get; set; } diff --git a/osu.Game/Modes/RulesetCollection.cs b/osu.Game/Modes/RulesetCollection.cs index d699bbfabe..221fa6f5ba 100644 --- a/osu.Game/Modes/RulesetCollection.cs +++ b/osu.Game/Modes/RulesetCollection.cs @@ -8,13 +8,16 @@ using System.Linq; namespace osu.Game.Modes { + /// + /// Todo: All of this needs to be moved to a RulesetDatabase. + /// public static class RulesetCollection { private static readonly ConcurrentDictionary available_rulesets = new ConcurrentDictionary(); public static void Register(Type type) { - Ruleset ruleset = Activator.CreateInstance(type) as Ruleset; + var ruleset = Activator.CreateInstance(type) as Ruleset; if (ruleset == null) return; @@ -25,9 +28,9 @@ namespace osu.Game.Modes public static Ruleset GetRuleset(int rulesetId) { Ruleset ruleset; - + if (!available_rulesets.TryGetValue(rulesetId, out ruleset)) - throw new InvalidOperationException($"Ruleset id {rulesetId} doesn't exist. How did you trigger this?"); + return null; return ruleset; } diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 5041ab237c..02df95ff8a 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Mods public readonly Bindable> SelectedMods = new Bindable>(); - public readonly Bindable Ruleset = new Bindable(); + public readonly Bindable Ruleset = new Bindable(RulesetCollection.GetRuleset(0)); private void rulesetChanged(Ruleset newRuleset) { diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b2c53c9126..1e2f074939 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -163,7 +163,7 @@ namespace osu.Game.Screens.Select searchTextBox.HoldFocus = true; } - private readonly Bindable ruleset = new Bindable(); + private readonly Bindable ruleset = new Bindable(RulesetCollection.GetRuleset(0)); [BackgroundDependencyLoader(permitNulls:true)] private void load(OsuColour colours, OsuGame osu) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index f25d3d4df9..183eb7de32 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen { - private readonly Bindable ruleset = new Bindable(); + private readonly Bindable ruleset = new Bindable(RulesetCollection.GetRuleset(0)); private BeatmapDatabase database; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); From ddce3c157f084a80e9f72c702bb9f538f38e7f79 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Sat, 15 Apr 2017 06:15:55 +0900 Subject: [PATCH 08/22] Clean up a few remaining stragglers. --- osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 420b23eb62..221cd5a37c 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps /// Calculates the star difficulty for this Beatmap. /// /// The star difficulty. - public double CalculateStarDifficulty() => RulesetCollection.GetRuleset(BeatmapInfo.Mode).CreateDifficultyCalculator(this).Calculate(); + public double CalculateStarDifficulty() => BeatmapInfo.Ruleset.CreateDifficultyCalculator(this).Calculate(); /// /// Constructs a new beatmap. diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 3fb5194382..252965fee5 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -45,7 +45,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, TextSize = Size.X, Colour = Color4.White, - Icon = RulesetCollection.GetRuleset((int)beatmap.Mode).Icon + Icon = beatmap.Ruleset.Icon } }; } diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 586100c47d..775efd5a40 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select })); //get statistics fromt he current ruleset. - labels.AddRange(RulesetCollection.GetRuleset(beatmap.BeatmapInfo.Mode).GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); + labels.AddRange(beatmap.BeatmapInfo.Ruleset.GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); } AlwaysPresent = true; From 83b083ce64c99c5c6e945533b2a8e213169a9017 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2017 14:37:52 +0900 Subject: [PATCH 09/22] Move SQLite connections out of database classes; make abstract Database. --- .../Tests/TestCasePlaySongSelect.cs | 2 +- osu.Game/Beatmaps/Beatmap.cs | 1 - osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 1 - osu.Game/Database/BeatmapDatabase.cs | 110 +++++++----------- osu.Game/Database/Database.cs | 44 +++++++ osu.Game/Database/ScoreDatabase.cs | 15 ++- osu.Game/OsuGameBase.cs | 8 +- osu.Game/osu.Game.csproj | 1 + 8 files changed, 105 insertions(+), 77 deletions(-) create mode 100644 osu.Game/Database/Database.cs diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index c22726491d..dd17d62739 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -26,7 +26,7 @@ namespace osu.Desktop.VisualTests.Tests if (db == null) { storage = new TestStorage(@"TestCasePlaySongSelect"); - db = new BeatmapDatabase(storage); + db = new BeatmapDatabase(storage, storage.GetDatabase(@"client")); var sets = new List(); diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 221cd5a37c..6099b1e115 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -4,7 +4,6 @@ using OpenTK.Graphics; using osu.Game.Beatmaps.Timing; using osu.Game.Database; -using osu.Game.Modes; using osu.Game.Modes.Objects; using System.Collections.Generic; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 252965fee5..02595df77a 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -6,7 +6,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Database; using osu.Game.Graphics; -using osu.Game.Modes; using OpenTK; using OpenTK.Graphics; diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index 41ddd8df39..9695ba8bd0 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -18,37 +18,19 @@ using SQLiteNetExtensions.Extensions; namespace osu.Game.Database { - public class BeatmapDatabase + public class BeatmapDatabase : Database { - private SQLiteConnection connection { get; } - private readonly Storage storage; + public event Action BeatmapSetAdded; public event Action BeatmapSetRemoved; // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private BeatmapIPCChannel ipc; - public BeatmapDatabase(Storage storage, IIpcHost importHost = null) + public BeatmapDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null) : base(storage, connection) { - this.storage = storage; - if (importHost != null) ipc = new BeatmapIPCChannel(importHost, this); - - if (connection == null) - { - try - { - connection = prepareConnection(); - deletePending(); - } - catch (Exception e) - { - Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database..."); - storage.DeleteDatabase(@"beatmaps"); - connection = prepareConnection(); - } - } } private void deletePending() @@ -57,20 +39,20 @@ namespace osu.Game.Database { try { - storage.Delete(b.Path); + Storage.Delete(b.Path); GetChildren(b, true); foreach (var i in b.Beatmaps) { - if (i.Metadata != null) connection.Delete(i.Metadata); - if (i.Difficulty != null) connection.Delete(i.Difficulty); + if (i.Metadata != null) Connection.Delete(i.Metadata); + if (i.Difficulty != null) Connection.Delete(i.Difficulty); - connection.Delete(i); + Connection.Delete(i); } - if (b.Metadata != null) connection.Delete(b.Metadata); - connection.Delete(b); + if (b.Metadata != null) Connection.Delete(b.Metadata); + Connection.Delete(b); } catch (Exception e) { @@ -80,41 +62,31 @@ namespace osu.Game.Database //this is required because sqlite migrations don't work, initially inserting nulls into this field. //see https://github.com/praeclarum/sqlite-net/issues/326 - connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); + Connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); } - private SQLiteConnection prepareConnection() + protected override void Prepare() { - var conn = storage.GetDatabase(@"beatmaps"); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); - try - { - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - } - catch - { - conn.Close(); - throw; - } - - return conn; + deletePending(); } - public void Reset() + public override void Reset() { foreach (var setInfo in Query()) { - if (storage.Exists(setInfo.Path)) - storage.Delete(setInfo.Path); + if (Storage.Exists(setInfo.Path)) + Storage.Delete(setInfo.Path); } - connection.DeleteAll(); - connection.DeleteAll(); - connection.DeleteAll(); - connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); } /// @@ -174,7 +146,7 @@ namespace osu.Game.Database BeatmapMetadata metadata; - using (var reader = ArchiveReader.GetReader(storage, path)) + using (var reader = ArchiveReader.GetReader(Storage, path)) { using (var stream = new StreamReader(reader.GetStream(reader.BeatmapFilenames[0]))) metadata = BeatmapDecoder.GetDecoder(stream).Decode(stream).Metadata; @@ -182,18 +154,18 @@ namespace osu.Game.Database if (File.Exists(path)) // Not always the case, i.e. for LegacyFilesystemReader { - using (var input = storage.GetStream(path)) + using (var input = Storage.GetStream(path)) { hash = input.GetMd5Hash(); input.Seek(0, SeekOrigin.Begin); path = Path.Combine(@"beatmaps", hash.Remove(1), hash.Remove(2), hash); - if (!storage.Exists(path)) - using (var output = storage.GetStream(path, FileAccess.Write)) + if (!Storage.Exists(path)) + using (var output = Storage.GetStream(path, FileAccess.Write)) input.CopyTo(output); } } - var existing = connection.Table().FirstOrDefault(b => b.Hash == hash); + var existing = Connection.Table().FirstOrDefault(b => b.Hash == hash); if (existing != null) { @@ -216,7 +188,7 @@ namespace osu.Game.Database Metadata = metadata }; - using (var archive = ArchiveReader.GetReader(storage, path)) + using (var archive = ArchiveReader.GetReader(Storage, path)) { string[] mapNames = archive.BeatmapFilenames; foreach (var name in mapNames) @@ -248,17 +220,17 @@ namespace osu.Game.Database public void Import(IEnumerable beatmapSets) { - lock (connection) + lock (Connection) { - connection.BeginTransaction(); + Connection.BeginTransaction(); foreach (var s in beatmapSets) { - connection.InsertWithChildren(s, true); + Connection.InsertWithChildren(s, true); BeatmapSetAdded?.Invoke(s); } - connection.Commit(); + Connection.Commit(); } } @@ -275,7 +247,7 @@ namespace osu.Game.Database if (string.IsNullOrEmpty(beatmapSet.Path)) return null; - return ArchiveReader.GetReader(storage, beatmapSet.Path); + return ArchiveReader.GetReader(Storage, beatmapSet.Path); } public BeatmapSetInfo GetBeatmapSet(int id) @@ -305,25 +277,25 @@ namespace osu.Game.Database public TableQuery Query() where T : class { - return connection.Table(); + return Connection.Table(); } public T GetWithChildren(object id) where T : class { - return connection.GetWithChildren(id); + return Connection.GetWithChildren(id); } public List GetAllWithChildren(Expression> filter = null, bool recursive = true) where T : class { - return connection.GetAllWithChildren(filter, recursive); + return Connection.GetAllWithChildren(filter, recursive); } public T GetChildren(T item, bool recursive = false) { if (item == null) return default(T); - connection.GetChildren(item, recursive); + Connection.GetChildren(item, recursive); return item; } @@ -339,11 +311,11 @@ namespace osu.Game.Database if (validTypes.All(t => t != typeof(T))) throw new ArgumentException("Must be a type managed by BeatmapDatabase", nameof(T)); if (cascade) - connection.UpdateWithChildren(record); + Connection.UpdateWithChildren(record); else - connection.Update(record); + Connection.Update(record); } - public bool Exists(BeatmapSetInfo beatmapSet) => storage.Exists(beatmapSet.Path); + public bool Exists(BeatmapSetInfo beatmapSet) => Storage.Exists(beatmapSet.Path); } } diff --git a/osu.Game/Database/Database.cs b/osu.Game/Database/Database.cs new file mode 100644 index 0000000000..6f8e902663 --- /dev/null +++ b/osu.Game/Database/Database.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using osu.Framework.Logging; +using osu.Framework.Platform; +using SQLite.Net; + +namespace osu.Game.Database +{ + public abstract class Database + { + protected SQLiteConnection Connection { get; } + protected Storage Storage { get; } + + protected Database(Storage storage, SQLiteConnection connection) + { + Storage = storage; + Connection = connection; + + try + { + Prepare(); + } + catch (Exception e) + { + Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database..."); + storage.DeleteDatabase(@"beatmaps"); + Reset(); + Prepare(); + } + } + + /// + /// Prepare this database for use. + /// + protected abstract void Prepare(); + + /// + /// Reset this database to a default state. Undo all changes to database and storage backings. + /// + public abstract void Reset(); + } +} \ No newline at end of file diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index 3b5c0575d5..240b4fa8e6 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -10,10 +10,11 @@ using osu.Game.IPC; using osu.Game.Modes; using osu.Game.Modes.Scoring; using SharpCompress.Compressors.LZMA; +using SQLite.Net; namespace osu.Game.Database { - public class ScoreDatabase + public class ScoreDatabase : Database { private readonly Storage storage; private readonly BeatmapDatabase beatmaps; @@ -23,7 +24,7 @@ namespace osu.Game.Database // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private ScoreIPCChannel ipc; - public ScoreDatabase(Storage storage, IIpcHost importHost = null, BeatmapDatabase beatmaps = null) + public ScoreDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null, BeatmapDatabase beatmaps = null) : base(storage, connection) { this.storage = storage; this.beatmaps = beatmaps; @@ -39,7 +40,7 @@ namespace osu.Game.Database using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) using (SerializationReader sr = new SerializationReader(s)) { - var ruleset = RulesetCollection.GetRuleset((int)sr.ReadByte()); + var ruleset = RulesetCollection.GetRuleset(sr.ReadByte()); score = ruleset.CreateScoreProcessor().CreateScore(); /* score.Pass = true;*/ @@ -107,5 +108,13 @@ namespace osu.Game.Database return score; } + + protected override void Prepare() + { + } + + public override void Reset() + { + } } } diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f95e8c3ac6..c37d2b83eb 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Processing; using osu.Game.Online.API; +using SQLite.Net; namespace osu.Game { @@ -80,8 +81,11 @@ namespace osu.Game { Dependencies.Cache(this); Dependencies.Cache(LocalConfig); - Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, Host)); - Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, Host, BeatmapDatabase)); + + SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); + + Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, Host)); + Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase)); Dependencies.Cache(new OsuColour()); //this completely overrides the framework default. will need to change once we make a proper FontStore. diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 866d3ddacb..a450125e48 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -78,6 +78,7 @@ + From a4e2f34ee73ecca2d19cd2b37d52faa631698b47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2017 17:43:48 +0900 Subject: [PATCH 10/22] Make a RulesetDatabase. --- osu.Desktop.Tests/VisualTests.cs | 10 -- osu.Desktop.VisualTests/Program.cs | 10 -- .../Tests/TestCaseModSelectOverlay.cs | 14 ++- .../Tests/TestCasePlaySongSelect.cs | 16 ++- .../Tests/TestCasePlayer.cs | 2 +- osu.Desktop/Program.cs | 10 -- osu.Game.Modes.Catch/CatchRuleset.cs | 2 + osu.Game.Modes.Mania/ManiaRuleset.cs | 2 + osu.Game.Modes.Osu/OsuRuleset.cs | 2 + osu.Game.Modes.Taiko/TaikoRuleset.cs | 2 + .../Beatmaps/Formats/OsuLegacyDecoderTest.cs | 4 +- .../Beatmaps/IO/ImportBeatmapTest.cs | 15 +-- .../Beatmaps/IO/OszArchiveReaderTest.cs | 3 - osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 2 +- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 +- osu.Game/Database/BeatmapDatabase.cs | 51 ++------- osu.Game/Database/BeatmapInfo.cs | 14 +-- osu.Game/Database/Database.cs | 43 ++++++- osu.Game/Database/RulesetDatabase.cs | 107 ++++++++++++++++++ osu.Game/Database/RulesetInfo.cs | 24 ++++ osu.Game/Database/ScoreDatabase.cs | 10 +- osu.Game/Modes/BeatmapStatistic.cs | 14 +++ osu.Game/Modes/Ruleset.cs | 12 +- osu.Game/Modes/RulesetCollection.cs | 42 ------- osu.Game/OsuGame.cs | 8 +- osu.Game/OsuGameBase.cs | 3 + osu.Game/Overlays/Mods/ModSelectOverlay.cs | 10 +- osu.Game/Overlays/Options/OptionsFooter.cs | 8 +- osu.Game/Overlays/Toolbar/Toolbar.cs | 6 +- .../Overlays/Toolbar/ToolbarModeButton.cs | 15 ++- .../Overlays/Toolbar/ToolbarModeSelector.cs | 15 ++- osu.Game/Screens/Play/Player.cs | 2 +- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 +- osu.Game/Screens/Select/FilterCriteria.cs | 4 +- osu.Game/Screens/Select/SongSelect.cs | 3 +- osu.Game/osu.Game.csproj | 4 +- 38 files changed, 298 insertions(+), 201 deletions(-) create mode 100644 osu.Game/Database/RulesetDatabase.cs create mode 100644 osu.Game/Database/RulesetInfo.cs create mode 100644 osu.Game/Modes/BeatmapStatistic.cs delete mode 100644 osu.Game/Modes/RulesetCollection.cs diff --git a/osu.Desktop.Tests/VisualTests.cs b/osu.Desktop.Tests/VisualTests.cs index 36dce18b05..6ef924e873 100644 --- a/osu.Desktop.Tests/VisualTests.cs +++ b/osu.Desktop.Tests/VisualTests.cs @@ -4,11 +4,6 @@ using NUnit.Framework; using osu.Desktop.VisualTests; 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 { @@ -20,11 +15,6 @@ namespace osu.Desktop.Tests { 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()); } } diff --git a/osu.Desktop.VisualTests/Program.cs b/osu.Desktop.VisualTests/Program.cs index 912034a927..03d1588b78 100644 --- a/osu.Desktop.VisualTests/Program.cs +++ b/osu.Desktop.VisualTests/Program.cs @@ -4,11 +4,6 @@ using System; using osu.Framework.Desktop; 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 { @@ -21,11 +16,6 @@ namespace osu.Desktop.VisualTests using (GameHost host = Host.GetSuitableHost(@"osu")) { - RulesetCollection.Register(typeof(OsuRuleset)); - RulesetCollection.Register(typeof(TaikoRuleset)); - RulesetCollection.Register(typeof(ManiaRuleset)); - RulesetCollection.Register(typeof(CatchRuleset)); - if (benchmark) host.Run(new AutomatedVisualTestGame()); else diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index c569f5f64a..d1c137191f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -1,10 +1,11 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays.Mods; using osu.Framework.Testing; -using osu.Game.Modes; +using osu.Game.Database; namespace osu.Desktop.VisualTests.Tests { @@ -13,6 +14,13 @@ namespace osu.Desktop.VisualTests.Tests public override string Description => @"Tests the mod select overlay"; private ModSelectOverlay modSelect; + private RulesetDatabase rulesets; + + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets) + { + this.rulesets = rulesets; + } public override void Reset() { @@ -27,8 +35,8 @@ namespace osu.Desktop.VisualTests.Tests AddStep("Toggle", modSelect.ToggleVisibility); - foreach (var ruleset in RulesetCollection.AllRulesets) - AddStep(ruleset.Description, () => modSelect.Ruleset.Value = ruleset); + foreach (var ruleset in rulesets.AllRulesets) + AddStep(ruleset.CreateInstance().Description, () => modSelect.Ruleset.Value = ruleset); } } } diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index dd17d62739..85ccebef77 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using osu.Desktop.VisualTests.Platform; +using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Database; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; -using osu.Game.Modes; namespace osu.Desktop.VisualTests.Tests { @@ -20,6 +20,14 @@ namespace osu.Desktop.VisualTests.Tests public override string Description => @"with fake data"; + private RulesetDatabase rulesets; + + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets) + { + this.rulesets = rulesets; + } + public override void Reset() { base.Reset(); @@ -72,7 +80,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1234 + i, - Ruleset = RulesetCollection.GetRuleset(0), + Ruleset = rulesets.Query().First(), Path = "normal.osu", Version = "Normal", Difficulty = new BeatmapDifficulty @@ -83,7 +91,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1235 + i, - Ruleset = RulesetCollection.GetRuleset(0), + Ruleset = rulesets.Query().First(), Path = "hard.osu", Version = "Hard", Difficulty = new BeatmapDifficulty @@ -94,7 +102,7 @@ namespace osu.Desktop.VisualTests.Tests new BeatmapInfo { OnlineBeatmapID = 1236 + i, - Ruleset = RulesetCollection.GetRuleset(0), + Ruleset = rulesets.Query().First(), Path = "insane.osu", Version = "Insane", Difficulty = new BeatmapDifficulty diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 2a9c31b2e9..924e753e2d 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -37,7 +37,7 @@ namespace osu.Desktop.VisualTests.Tests WorkingBeatmap beatmap = null; - var beatmapInfo = db.Query().FirstOrDefault(b => b.Ruleset is OsuRuleset); + var beatmapInfo = db.Query().FirstOrDefault(b => b.Ruleset.CreateInstance() is OsuRuleset); if (beatmapInfo != null) beatmap = db.GetWorkingBeatmap(beatmapInfo); diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index e9117cf533..210f780078 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -7,11 +7,6 @@ using osu.Desktop.Beatmaps.IO; using osu.Framework.Desktop; using osu.Framework.Desktop.Platform; 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 { @@ -41,11 +36,6 @@ namespace osu.Desktop } else { - RulesetCollection.Register(typeof(OsuRuleset)); - RulesetCollection.Register(typeof(TaikoRuleset)); - RulesetCollection.Register(typeof(ManiaRuleset)); - RulesetCollection.Register(typeof(CatchRuleset)); - host.Run(new OsuGameDesktop(args)); } return 0; diff --git a/osu.Game.Modes.Catch/CatchRuleset.cs b/osu.Game.Modes.Catch/CatchRuleset.cs index 02c170d0ac..6aafb2a3c6 100644 --- a/osu.Game.Modes.Catch/CatchRuleset.cs +++ b/osu.Game.Modes.Catch/CatchRuleset.cs @@ -90,5 +90,7 @@ namespace osu.Game.Modes.Catch public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); + + public override int LegacyID => 2; } } diff --git a/osu.Game.Modes.Mania/ManiaRuleset.cs b/osu.Game.Modes.Mania/ManiaRuleset.cs index 7d25ea93c9..030cea7344 100644 --- a/osu.Game.Modes.Mania/ManiaRuleset.cs +++ b/osu.Game.Modes.Mania/ManiaRuleset.cs @@ -105,5 +105,7 @@ namespace osu.Game.Modes.Mania public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); + + public override int LegacyID => 3; } } diff --git a/osu.Game.Modes.Osu/OsuRuleset.cs b/osu.Game.Modes.Osu/OsuRuleset.cs index 6ca19bb5bb..4de890ac5f 100644 --- a/osu.Game.Modes.Osu/OsuRuleset.cs +++ b/osu.Game.Modes.Osu/OsuRuleset.cs @@ -110,5 +110,7 @@ namespace osu.Game.Modes.Osu }; public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); + + public override int LegacyID => 0; } } diff --git a/osu.Game.Modes.Taiko/TaikoRuleset.cs b/osu.Game.Modes.Taiko/TaikoRuleset.cs index e88b50bb95..b93c25c55d 100644 --- a/osu.Game.Modes.Taiko/TaikoRuleset.cs +++ b/osu.Game.Modes.Taiko/TaikoRuleset.cs @@ -91,5 +91,7 @@ namespace osu.Game.Modes.Taiko public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap); public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); + + public override int LegacyID => 1; } } diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 9d783c7e91..91b673dc4c 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -6,7 +6,6 @@ using NUnit.Framework; using OpenTK; using OpenTK.Graphics; using osu.Game.Beatmaps.Formats; -using osu.Game.Modes; using osu.Game.Tests.Resources; using osu.Game.Modes.Osu; using osu.Game.Modes.Objects.Legacy; @@ -22,7 +21,6 @@ namespace osu.Game.Tests.Beatmaps.Formats public void SetUp() { OsuLegacyDecoder.Register(); - RulesetCollection.Register(typeof(OsuRuleset)); } [Test] @@ -58,7 +56,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(false, beatmapInfo.Countdown); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); 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.WidescreenStoryboard); } diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index e110da59b9..0d27a6a650 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -12,11 +12,7 @@ using osu.Framework.Desktop.Platform; 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; 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"; - [OneTimeSetUp] - public void SetUp() - { - RulesetCollection.Register(typeof(OsuRuleset)); - RulesetCollection.Register(typeof(TaikoRuleset)); - RulesetCollection.Register(typeof(ManiaRuleset)); - RulesetCollection.Register(typeof(CatchRuleset)); - } - [Test] public void TestImportWhenClosed() { @@ -166,7 +153,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.Ruleset is OsuRuleset))?.Beatmap; + var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.Ruleset.CreateInstance() is OsuRuleset))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); } diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs index add00d8f4d..03d09e24e0 100644 --- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs @@ -4,8 +4,6 @@ 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; using osu.Game.Beatmaps.Formats; using osu.Game.Database; @@ -19,7 +17,6 @@ namespace osu.Game.Tests.Beatmaps.IO public void SetUp() { OszArchiveReader.Register(); - RulesetCollection.Register(typeof(OsuRuleset)); } [Test] diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 6099b1e115..3b57d4e7fe 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -53,7 +53,7 @@ namespace osu.Game.Beatmaps /// Calculates the star difficulty for this Beatmap. /// /// The star difficulty. - public double CalculateStarDifficulty() => BeatmapInfo.Ruleset.CreateDifficultyCalculator(this).Calculate(); + public double CalculateStarDifficulty() => BeatmapInfo.Ruleset.CreateInstance().CreateDifficultyCalculator(this).Calculate(); /// /// Constructs a new beatmap. diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 02595df77a..8a9183819c 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, TextSize = Size.X, Colour = Color4.White, - Icon = beatmap.Ruleset.Icon + Icon = beatmap.Ruleset.CreateInstance().Icon } }; } diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 36f025d1ff..8ad5f8e7c0 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -83,7 +83,7 @@ namespace osu.Game.Beatmaps.Formats beatmap.BeatmapInfo.StackLeniency = float.Parse(val, NumberFormatInfo.InvariantInfo); break; case @"Mode": - beatmap.BeatmapInfo.Mode = int.Parse(val); + beatmap.BeatmapInfo.RulesetID = int.Parse(val); break; case @"LetterboxInBreaks": beatmap.BeatmapInfo.LetterboxInBreaks = int.Parse(val) == 1; diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index 9695ba8bd0..f3f58ce8b0 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Linq.Expressions; using osu.Framework.Extensions; using osu.Framework.Logging; using osu.Framework.Platform; @@ -77,6 +76,8 @@ namespace osu.Game.Database public override void Reset() { + Storage.DeleteDatabase(@"beatmaps"); + foreach (var setInfo in Query()) { if (Storage.Exists(setInfo.Path)) @@ -89,6 +90,13 @@ namespace osu.Game.Database Connection.DeleteAll(); } + protected override Type[] ValidTypes => new[] { + typeof(BeatmapSetInfo), + typeof(BeatmapInfo), + typeof(BeatmapMetadata), + typeof(BeatmapDifficulty), + }; + /// /// Import multiple from . /// @@ -275,47 +283,6 @@ namespace osu.Game.Database return working; } - public TableQuery Query() where T : class - { - return Connection.Table(); - } - - public T GetWithChildren(object id) where T : class - { - return Connection.GetWithChildren(id); - } - - public List GetAllWithChildren(Expression> filter = null, bool recursive = true) - where T : class - { - return Connection.GetAllWithChildren(filter, recursive); - } - - public T GetChildren(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 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); } } diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs index be4faebde2..5097622deb 100644 --- a/osu.Game/Database/BeatmapInfo.cs +++ b/osu.Game/Database/BeatmapInfo.cs @@ -3,7 +3,6 @@ using Newtonsoft.Json; using osu.Game.IO.Serialization; -using osu.Game.Modes; using SQLite.Net.Attributes; using SQLiteNetExtensions.Attributes; using System; @@ -55,15 +54,12 @@ namespace osu.Game.Database public float StackLeniency { 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 WidescreenStoryboard { get; set; } diff --git a/osu.Game/Database/Database.cs b/osu.Game/Database/Database.cs index 6f8e902663..19bd78b39c 100644 --- a/osu.Game/Database/Database.cs +++ b/osu.Game/Database/Database.cs @@ -2,9 +2,13 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; using osu.Framework.Logging; using osu.Framework.Platform; using SQLite.Net; +using SQLiteNetExtensions.Extensions; namespace osu.Game.Database { @@ -24,8 +28,7 @@ namespace osu.Game.Database } catch (Exception e) { - Logger.Error(e, @"Failed to initialise the beatmap database! Trying again with a clean database..."); - storage.DeleteDatabase(@"beatmaps"); + Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database..."); Reset(); Prepare(); } @@ -40,5 +43,41 @@ namespace osu.Game.Database /// Reset this database to a default state. Undo all changes to database and storage backings. /// public abstract void Reset(); + + public TableQuery Query() where T : class + { + return Connection.Table(); + } + + public T GetWithChildren(object id) where T : class + { + return Connection.GetWithChildren(id); + } + + public List GetAllWithChildren(Expression> filter = null, bool recursive = true) + where T : class + { + return Connection.GetAllWithChildren(filter, recursive); + } + + public T GetChildren(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 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); + } } } \ No newline at end of file diff --git a/osu.Game/Database/RulesetDatabase.cs b/osu.Game/Database/RulesetDatabase.cs new file mode 100644 index 0000000000..45db5df26f --- /dev/null +++ b/osu.Game/Database/RulesetDatabase.cs @@ -0,0 +1,107 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// 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 +{ + /// + /// Todo: All of this needs to be moved to a RulesetDatabase. + /// + public class RulesetDatabase : Database + { + public IEnumerable AllRulesets => Query().Where(r => r.Available); + + public RulesetDatabase(Storage storage, SQLiteConnection connection) + : base(storage, connection) + { + } + + protected override void Prepare() + { + Connection.CreateTable(); + + List instances = new List(); + + 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().FirstOrDefault(ri => ri.InstantiationInfo == us.InstantiationInfo); + + if (existing == null) + Connection.Insert(us); + } + + //perform a consistency check + foreach (var r in Query()) + { + 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(); + } + + protected override Type[] ValidTypes => new[] { typeof(RulesetInfo) }; + + public RulesetInfo GetRuleset(int id) => Query().First(r => r.ID == id); + } +} diff --git a/osu.Game/Database/RulesetInfo.cs b/osu.Game/Database/RulesetInfo.cs new file mode 100644 index 0000000000..6a0ee13e41 --- /dev/null +++ b/osu.Game/Database/RulesetInfo.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// 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)); + } +} \ No newline at end of file diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index 240b4fa8e6..91a52fba4a 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -7,7 +7,6 @@ using System.Linq; using osu.Framework.Platform; using osu.Game.IO.Legacy; using osu.Game.IPC; -using osu.Game.Modes; using osu.Game.Modes.Scoring; using SharpCompress.Compressors.LZMA; using SQLite.Net; @@ -17,17 +16,20 @@ namespace osu.Game.Database public class ScoreDatabase : Database { private readonly Storage storage; + private readonly BeatmapDatabase beatmaps; + private readonly RulesetDatabase rulesets; private const string replay_folder = @"replays"; // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) 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.beatmaps = beatmaps; + this.rulesets = rulesets; if (importHost != null) ipc = new ScoreIPCChannel(importHost, this); @@ -40,7 +42,7 @@ namespace osu.Game.Database using (Stream s = storage.GetStream(Path.Combine(replay_folder, replayFilename))) using (SerializationReader sr = new SerializationReader(s)) { - var ruleset = RulesetCollection.GetRuleset(sr.ReadByte()); + var ruleset = rulesets.GetRuleset(sr.ReadByte()).CreateInstance(); score = ruleset.CreateScoreProcessor().CreateScore(); /* score.Pass = true;*/ @@ -116,5 +118,7 @@ namespace osu.Game.Database public override void Reset() { } + + protected override Type[] ValidTypes => new[] { typeof(Score) }; } } diff --git a/osu.Game/Modes/BeatmapStatistic.cs b/osu.Game/Modes/BeatmapStatistic.cs new file mode 100644 index 0000000000..d598b81ff4 --- /dev/null +++ b/osu.Game/Modes/BeatmapStatistic.cs @@ -0,0 +1,14 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// 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; + } +} \ No newline at end of file diff --git a/osu.Game/Modes/Ruleset.cs b/osu.Game/Modes/Ruleset.cs index 284a71d518..cf0fbe5b6a 100644 --- a/osu.Game/Modes/Ruleset.cs +++ b/osu.Game/Modes/Ruleset.cs @@ -11,13 +11,6 @@ using osu.Game.Modes.Scoring; namespace osu.Game.Modes { - public class BeatmapStatistic - { - public FontAwesome Icon; - public string Content; - public string Name; - } - public abstract class Ruleset { public virtual IEnumerable GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { }; @@ -35,5 +28,10 @@ namespace osu.Game.Modes public abstract string Description { get; } public abstract IEnumerable CreateGameplayKeys(); + + /// + /// Do not override this unless you are a legacy mode. + /// + public virtual int LegacyID => -1; } } diff --git a/osu.Game/Modes/RulesetCollection.cs b/osu.Game/Modes/RulesetCollection.cs deleted file mode 100644 index 221fa6f5ba..0000000000 --- a/osu.Game/Modes/RulesetCollection.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// 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 -{ - /// - /// Todo: All of this needs to be moved to a RulesetDatabase. - /// - public static class RulesetCollection - { - private static readonly ConcurrentDictionary available_rulesets = new ConcurrentDictionary(); - - 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 AllRulesets => available_rulesets.Values; - } -} diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3379787d6d..6062f3fd59 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -15,7 +15,6 @@ using osu.Framework.Logging; using osu.Game.Graphics.UserInterface.Volume; using osu.Framework.Allocation; using osu.Framework.Timing; -using osu.Game.Modes; using osu.Game.Overlays.Toolbar; using osu.Game.Screens; using osu.Game.Screens.Menu; @@ -24,6 +23,7 @@ using System.Linq; using osu.Framework.Graphics.Primitives; using System.Threading.Tasks; using osu.Framework.Threading; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Modes.Scoring; using osu.Game.Overlays.Notifications; @@ -59,7 +59,7 @@ namespace osu.Game private VolumeControl volume; private Bindable configRuleset; - public Bindable Ruleset = new Bindable(); + public Bindable Ruleset = new Bindable(); private readonly string[] args; @@ -90,8 +90,8 @@ namespace osu.Game Dependencies.Cache(this); configRuleset = LocalConfig.GetBindable(OsuConfig.Ruleset); - Ruleset.Value = RulesetCollection.GetRuleset(configRuleset.Value); - Ruleset.ValueChanged += r => configRuleset.Value = RulesetCollection.GetId(r); + Ruleset.Value = RulesetDatabase.GetRuleset(configRuleset.Value); + Ruleset.ValueChanged += r => configRuleset.Value = r.ID; } private ScheduledDelegate scoreLoad; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index c37d2b83eb..c6a5cbef1b 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -28,6 +28,8 @@ namespace osu.Game protected BeatmapDatabase BeatmapDatabase; + protected RulesetDatabase RulesetDatabase; + protected ScoreDatabase ScoreDatabase; protected override string MainResourceFile => @"osu.Game.Resources.dll"; @@ -85,6 +87,7 @@ namespace osu.Game SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); 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(new OsuColour()); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 02df95ff8a..30ccb2d005 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -13,11 +13,11 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Sprites; -using osu.Game.Modes; using osu.Game.Modes.Mods; using System; using System.Collections.Generic; using System.Linq; +using osu.Game.Database; namespace osu.Game.Overlays.Mods { @@ -37,12 +37,14 @@ namespace osu.Game.Overlays.Mods public readonly Bindable> SelectedMods = new Bindable>(); - public readonly Bindable Ruleset = new Bindable(RulesetCollection.GetRuleset(0)); + public readonly Bindable Ruleset = new Bindable(); - private void rulesetChanged(Ruleset newRuleset) + private void rulesetChanged(RulesetInfo newRuleset) { + var instance = newRuleset.CreateInstance(); + 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(); } diff --git a/osu.Game/Overlays/Options/OptionsFooter.cs b/osu.Game/Overlays/Options/OptionsFooter.cs index ad184c8838..c785f2d0c0 100644 --- a/osu.Game/Overlays/Options/OptionsFooter.cs +++ b/osu.Game/Overlays/Options/OptionsFooter.cs @@ -6,9 +6,9 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; +using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Modes; using OpenTK; using OpenTK.Graphics; @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.Options public class OptionsFooter : FillFlowContainer { [BackgroundDependencyLoader] - private void load(OsuGameBase game, OsuColour colours) + private void load(OsuGameBase game, OsuColour colours, RulesetDatabase rulesets) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; @@ -26,11 +26,11 @@ namespace osu.Game.Overlays.Options var modes = new List(); - foreach (var ruleset in RulesetCollection.AllRulesets) + foreach (var ruleset in rulesets.AllRulesets) { modes.Add(new TextAwesome { - Icon = ruleset.Icon, + Icon = ruleset.CreateInstance().Icon, Colour = Color4.Gray, TextSize = 20 }); diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index ec76a37e6e..4632b55775 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -8,8 +8,8 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.Input; +using osu.Game.Database; using osu.Game.Graphics; -using osu.Game.Modes; using OpenTK; namespace osu.Game.Overlays.Toolbar @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Toolbar public const float TOOLTIP_HEIGHT = 30; public Action OnHome; - public Action OnRulesetChange; + public Action OnRulesetChange; private readonly ToolbarModeSelector modeSelector; 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() { diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs index 6ace90bcb4..dd70289f7d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs @@ -2,23 +2,26 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics.Containers; -using osu.Game.Modes; +using osu.Game.Database; using OpenTK.Graphics; namespace osu.Game.Overlays.Toolbar { public class ToolbarModeButton : ToolbarButton { - private Ruleset ruleset; - public Ruleset Ruleset + private RulesetInfo ruleset; + public RulesetInfo Ruleset { get { return ruleset; } set { ruleset = value; - TooltipMain = ruleset.Description; - TooltipSub = $"Play some {ruleset.Description}"; - Icon = ruleset.Icon; + + var rInstance = ruleset.CreateInstance(); + + TooltipMain = rInstance.Description; + TooltipSub = $"Play some {rInstance.Description}"; + Icon = rInstance.Icon; } } diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs index 0d673eb3fe..e4c9db7c5d 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs @@ -3,12 +3,13 @@ using System; using System.Linq; +using osu.Framework.Allocation; using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Sprites; -using osu.Game.Modes; +using osu.Game.Database; using OpenTK; using OpenTK.Graphics; @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Toolbar private readonly Drawable modeButtonLine; private ToolbarModeButton activeButton; - public Action OnRulesetChange; + public Action OnRulesetChange; 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 { @@ -84,11 +89,11 @@ namespace osu.Game.Overlays.Toolbar Size = new Vector2(modeButtons.DrawSize.X, 1); } - public void SetGameMode(Ruleset ruleset) + public void SetGameMode(RulesetInfo ruleset) { foreach (ToolbarModeButton m in modeButtons.Children.Cast()) { - bool isActive = m.Ruleset == ruleset; + bool isActive = m.Ruleset.ID == ruleset.ID; m.Active = isActive; if (isActive) activeButton = m; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b59b3bf0c1..b32548c31a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -102,7 +102,7 @@ namespace osu.Game.Screens.Play 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 // can actually convert the hit objects... Somehow... diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 775efd5a40..2d873d10ab 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -100,7 +100,7 @@ namespace osu.Game.Screens.Select })); //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; diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 1e2f074939..e0b197e9ca 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,7 +16,7 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Select.Filter; using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Input; -using osu.Game.Modes; +using osu.Game.Database; namespace osu.Game.Screens.Select { @@ -163,7 +163,7 @@ namespace osu.Game.Screens.Select searchTextBox.HoldFocus = true; } - private readonly Bindable ruleset = new Bindable(RulesetCollection.GetRuleset(0)); + private readonly Bindable ruleset = new Bindable(); [BackgroundDependencyLoader(permitNulls:true)] private void load(OsuColour colours, OsuGame osu) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 0b750ef8d3..1a32244deb 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps.Drawables; -using osu.Game.Modes; +using osu.Game.Database; using osu.Game.Screens.Select.Filter; namespace osu.Game.Screens.Select @@ -15,7 +15,7 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; public string SearchText; - public Ruleset Ruleset; + public RulesetInfo Ruleset; public void Filter(List groups) { diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 183eb7de32..182158fa5d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -20,7 +20,6 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Modes; using osu.Game.Overlays; using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Select.Options; @@ -29,7 +28,7 @@ namespace osu.Game.Screens.Select { public abstract class SongSelect : OsuScreen { - private readonly Bindable ruleset = new Bindable(RulesetCollection.GetRuleset(0)); + private readonly Bindable ruleset = new Bindable(); private BeatmapDatabase database; protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a450125e48..193c2c1179 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -79,6 +79,7 @@ + @@ -102,6 +103,7 @@ + @@ -133,7 +135,7 @@ - + From db6556a0f9459e71513e65b51b1113d0b0a556d7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2017 17:44:02 +0900 Subject: [PATCH 11/22] Index DeletePending for better performance. --- osu.Game/Database/BeatmapSetInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Database/BeatmapSetInfo.cs b/osu.Game/Database/BeatmapSetInfo.cs index 0ef0ba4c63..0875d3c01f 100644 --- a/osu.Game/Database/BeatmapSetInfo.cs +++ b/osu.Game/Database/BeatmapSetInfo.cs @@ -26,6 +26,7 @@ namespace osu.Game.Database public double MaxStarDifficulty => Beatmaps.Max(b => b.StarDifficulty); + [Indexed] public bool DeletePending { get; set; } public string Hash { get; set; } From af13f97435f94be809de44031fbe0faa9a033332 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2017 19:44:03 +0900 Subject: [PATCH 12/22] Fix regressions and test cases. --- .../Tests/TestCaseGamefield.cs | 10 +++++ .../Tests/TestCaseModSelectOverlay.cs | 1 + .../Tests/TestCasePlaySongSelect.cs | 12 +++--- .../Tests/TestCasePlayer.cs | 5 ++- .../Beatmaps/Formats/OsuLegacyDecoderTest.cs | 3 +- .../Beatmaps/IO/ImportBeatmapTest.cs | 6 +-- osu.Game/Beatmaps/Beatmap.cs | 6 --- osu.Game/Database/BeatmapDatabase.cs | 39 +++++++++++-------- osu.Game/Database/Database.cs | 7 ++-- osu.Game/Database/RulesetDatabase.cs | 16 +++----- osu.Game/Database/RulesetInfo.cs | 2 +- osu.Game/Database/ScoreDatabase.cs | 6 +-- osu.Game/OsuGame.cs | 2 +- osu.Game/OsuGameBase.cs | 2 +- osu.Game/Overlays/Mods/ModSelectOverlay.cs | 5 ++- 15 files changed, 63 insertions(+), 59 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs index 3129cade63..d1519d0404 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseGamefield.cs @@ -17,13 +17,22 @@ using osu.Game.Modes.Osu.UI; using osu.Game.Modes.Taiko.UI; using System.Collections.Generic; using osu.Desktop.VisualTests.Beatmaps; +using osu.Framework.Allocation; namespace osu.Desktop.VisualTests.Tests { internal class TestCaseGamefield : TestCase { + private RulesetDatabase rulesets; + public override string Description => @"Showing hitobjects and what not."; + [BackgroundDependencyLoader] + private void load(RulesetDatabase rulesets) + { + this.rulesets = rulesets; + } + public override void Reset() { base.Reset(); @@ -49,6 +58,7 @@ namespace osu.Desktop.VisualTests.Tests BeatmapInfo = new BeatmapInfo { Difficulty = new BeatmapDifficulty(), + Ruleset = rulesets.Query().First(), Metadata = new BeatmapMetadata { Artist = @"Unknown", diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index d1c137191f..a2d7b3ad99 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays.Mods; diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 85ccebef77..db21556cda 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -22,19 +22,17 @@ namespace osu.Desktop.VisualTests.Tests private RulesetDatabase rulesets; - [BackgroundDependencyLoader] - private void load(RulesetDatabase rulesets) - { - this.rulesets = rulesets; - } - public override void Reset() { base.Reset(); if (db == null) { storage = new TestStorage(@"TestCasePlaySongSelect"); - db = new BeatmapDatabase(storage, storage.GetDatabase(@"client")); + + var backingDatabase = storage.GetDatabase(@"client"); + + rulesets = new RulesetDatabase(storage, backingDatabase); + db = new BeatmapDatabase(storage, backingDatabase, rulesets); var sets = new List(); diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 924e753e2d..a21c09a9d0 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -22,12 +22,14 @@ namespace osu.Desktop.VisualTests.Tests { protected Player Player; private BeatmapDatabase db; + private RulesetDatabase rulesets; public override string Description => @"Showing everything to play the game."; [BackgroundDependencyLoader] - private void load(BeatmapDatabase db) + private void load(BeatmapDatabase db, RulesetDatabase rulesets) { + this.rulesets = rulesets; this.db = db; } @@ -65,6 +67,7 @@ namespace osu.Desktop.VisualTests.Tests BeatmapInfo = new BeatmapInfo { Difficulty = new BeatmapDifficulty(), + Ruleset = rulesets.Query().First(), Metadata = new BeatmapMetadata { Artist = @"Unknown", diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs index 91b673dc4c..5e94a4dd77 100644 --- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs @@ -7,7 +7,6 @@ using OpenTK; using OpenTK.Graphics; using osu.Game.Beatmaps.Formats; using osu.Game.Tests.Resources; -using osu.Game.Modes.Osu; using osu.Game.Modes.Objects.Legacy; using System.Linq; using osu.Game.Audio; @@ -56,7 +55,7 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.AreEqual(false, beatmapInfo.Countdown); Assert.AreEqual(0.7f, beatmapInfo.StackLeniency); Assert.AreEqual(false, beatmapInfo.SpecialStyle); - Assert.IsTrue(beatmapInfo.Ruleset.CreateInstance() is OsuRuleset); + Assert.IsTrue(beatmapInfo.RulesetID == 0); Assert.AreEqual(false, beatmapInfo.LetterboxInBreaks); Assert.AreEqual(false, beatmapInfo.WidescreenStoryboard); } diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 0d27a6a650..0e03a443cc 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -12,7 +12,6 @@ using osu.Framework.Desktop.Platform; using osu.Framework.Platform; using osu.Game.Database; using osu.Game.IPC; -using osu.Game.Modes.Osu; namespace osu.Game.Tests.Beatmaps.IO { @@ -106,6 +105,7 @@ namespace osu.Game.Tests.Beatmaps.IO Thread.Sleep(1); //reset beatmap database (sqlite and storage backing) + osu.Dependencies.Get().Reset(); osu.Dependencies.Get().Reset(); return osu; @@ -122,7 +122,7 @@ namespace osu.Game.Tests.Beatmaps.IO Thread.Sleep(50); }; - Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), + Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(999999999), @"BeatmapSet did not import to the database in allocated time."); //ensure we were stored to beatmap database backing... @@ -153,7 +153,7 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); - var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.Ruleset.CreateInstance() is OsuRuleset))?.Beatmap; + var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); } diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 3b57d4e7fe..e3a7a81d0d 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -49,12 +49,6 @@ namespace osu.Game.Beatmaps /// public class Beatmap : Beatmap { - /// - /// Calculates the star difficulty for this Beatmap. - /// - /// The star difficulty. - public double CalculateStarDifficulty() => BeatmapInfo.Ruleset.CreateInstance().CreateDifficultyCalculator(this).Calculate(); - /// /// Constructs a new beatmap. /// diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index f3f58ce8b0..7789096067 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -19,6 +19,7 @@ namespace osu.Game.Database { public class BeatmapDatabase : Database { + private readonly RulesetDatabase rulesets; public event Action BeatmapSetAdded; public event Action BeatmapSetRemoved; @@ -26,8 +27,9 @@ namespace osu.Game.Database // ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised) private BeatmapIPCChannel ipc; - public BeatmapDatabase(Storage storage, SQLiteConnection connection, IIpcHost importHost = null) : base(storage, connection) + public BeatmapDatabase(Storage storage, SQLiteConnection connection, RulesetDatabase rulesets, IIpcHost importHost = null) : base(storage, connection) { + this.rulesets = rulesets; if (importHost != null) ipc = new BeatmapIPCChannel(importHost, this); } @@ -64,30 +66,30 @@ namespace osu.Game.Database Connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); } - protected override void Prepare() + protected override void Prepare(bool reset = false) { Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); - deletePending(); - } - - public override void Reset() - { - Storage.DeleteDatabase(@"beatmaps"); - - foreach (var setInfo in Query()) + if (reset) { - if (Storage.Exists(setInfo.Path)) - Storage.Delete(setInfo.Path); + Storage.DeleteDatabase(@"beatmaps"); + + foreach (var setInfo in Query()) + { + if (Storage.Exists(setInfo.Path)) + Storage.Delete(setInfo.Path); + } + + Connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); + Connection.DeleteAll(); } - Connection.DeleteAll(); - Connection.DeleteAll(); - Connection.DeleteAll(); - Connection.DeleteAll(); + deletePending(); } protected override Type[] ValidTypes => new[] { @@ -216,7 +218,10 @@ namespace osu.Game.Database // TODO: Diff beatmap metadata with set metadata and leave it here if necessary beatmap.BeatmapInfo.Metadata = null; - beatmap.BeatmapInfo.StarDifficulty = beatmap.CalculateStarDifficulty(); + // TODO: this should be done in a better place once we actually need to dynamically update it. + beatmap.BeatmapInfo.StarDifficulty = rulesets.Query().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID)?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0; + + beatmap.BeatmapInfo.Ruleset = null; beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } diff --git a/osu.Game/Database/Database.cs b/osu.Game/Database/Database.cs index 19bd78b39c..23851b3b2e 100644 --- a/osu.Game/Database/Database.cs +++ b/osu.Game/Database/Database.cs @@ -29,20 +29,19 @@ namespace osu.Game.Database catch (Exception e) { Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database..."); - Reset(); - Prepare(); + Prepare(true); } } /// /// Prepare this database for use. /// - protected abstract void Prepare(); + protected abstract void Prepare(bool reset = false); /// /// Reset this database to a default state. Undo all changes to database and storage backings. /// - public abstract void Reset(); + public void Reset() => Prepare(true); public TableQuery Query() where T : class { diff --git a/osu.Game/Database/RulesetDatabase.cs b/osu.Game/Database/RulesetDatabase.cs index 45db5df26f..d19fe56345 100644 --- a/osu.Game/Database/RulesetDatabase.cs +++ b/osu.Game/Database/RulesetDatabase.cs @@ -24,10 +24,15 @@ namespace osu.Game.Database { } - protected override void Prepare() + protected override void Prepare(bool reset = false) { Connection.CreateTable(); + if (reset) + { + Connection.DeleteAll(); + } + List instances = new List(); foreach (string file in Directory.GetFiles(Environment.CurrentDirectory, @"osu.Game.Modes.*.dll")) @@ -40,8 +45,6 @@ namespace osu.Game.Database if (rulesets.Count() != 1) continue; - Assembly.LoadFile(file); - foreach (Type rulesetType in rulesets) instances.Add((Ruleset)Activator.CreateInstance(rulesetType)); } @@ -84,8 +87,6 @@ namespace osu.Game.Database } Connection.Commit(); - - } private RulesetInfo createRulesetInfo(Ruleset ruleset) => new RulesetInfo @@ -95,11 +96,6 @@ namespace osu.Game.Database ID = ruleset.LegacyID }; - public override void Reset() - { - Connection.DeleteAll(); - } - protected override Type[] ValidTypes => new[] { typeof(RulesetInfo) }; public RulesetInfo GetRuleset(int id) => Query().First(r => r.ID == id); diff --git a/osu.Game/Database/RulesetInfo.cs b/osu.Game/Database/RulesetInfo.cs index 6a0ee13e41..d7bab39b97 100644 --- a/osu.Game/Database/RulesetInfo.cs +++ b/osu.Game/Database/RulesetInfo.cs @@ -10,7 +10,7 @@ namespace osu.Game.Database public class RulesetInfo { [PrimaryKey, AutoIncrement] - public int ID { get; set; } + public int? ID { get; set; } public string Name { get; set; } diff --git a/osu.Game/Database/ScoreDatabase.cs b/osu.Game/Database/ScoreDatabase.cs index 91a52fba4a..a2fff7f795 100644 --- a/osu.Game/Database/ScoreDatabase.cs +++ b/osu.Game/Database/ScoreDatabase.cs @@ -111,11 +111,7 @@ namespace osu.Game.Database return score; } - protected override void Prepare() - { - } - - public override void Reset() + protected override void Prepare(bool reset = false) { } diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 6062f3fd59..1006008afc 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -91,7 +91,7 @@ namespace osu.Game configRuleset = LocalConfig.GetBindable(OsuConfig.Ruleset); Ruleset.Value = RulesetDatabase.GetRuleset(configRuleset.Value); - Ruleset.ValueChanged += r => configRuleset.Value = r.ID; + Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; } private ScheduledDelegate scoreLoad; diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index c6a5cbef1b..371699eab3 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -86,8 +86,8 @@ namespace osu.Game SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); - Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, Host)); Dependencies.Cache(RulesetDatabase = new RulesetDatabase(Host.Storage, connection)); + Dependencies.Cache(BeatmapDatabase = new BeatmapDatabase(Host.Storage, connection, RulesetDatabase, Host)); Dependencies.Cache(ScoreDatabase = new ScoreDatabase(Host.Storage, connection, Host, BeatmapDatabase)); Dependencies.Cache(new OsuColour()); diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs index 30ccb2d005..bf7117edf1 100644 --- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs +++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs @@ -49,13 +49,16 @@ namespace osu.Game.Overlays.Mods } [BackgroundDependencyLoader(permitNulls: true)] - private void load(OsuColour colours, OsuGame osu) + private void load(OsuColour colours, OsuGame osu, RulesetDatabase rulesets) { lowMultiplierColour = colours.Red; highMultiplierColour = colours.Green; if (osu != null) Ruleset.BindTo(osu.Ruleset); + else + Ruleset.Value = rulesets.AllRulesets.First(); + Ruleset.ValueChanged += rulesetChanged; Ruleset.TriggerChange(); } From fe0d18777e3c5e4db82908e87efc01ed14eaf31f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2017 19:52:07 +0900 Subject: [PATCH 13/22] Fix appveyor issues. --- osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs | 1 - osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs index a2d7b3ad99..d1c137191f 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseModSelectOverlay.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Overlays.Mods; diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index db21556cda..35eb6d0ff9 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using osu.Desktop.VisualTests.Platform; -using osu.Framework.Allocation; using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Database; From 4b6ba565f861b5ccef15916c70d0c372fd00ef3d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 17 Apr 2017 20:10:51 +0900 Subject: [PATCH 14/22] Fix forgotten revert. --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 0e03a443cc..0c64c47a63 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -122,7 +122,7 @@ namespace osu.Game.Tests.Beatmaps.IO Thread.Sleep(50); }; - Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(999999999), + Assert.IsTrue(waitAction.BeginInvoke(null, null).AsyncWaitHandle.WaitOne(timeout), @"BeatmapSet did not import to the database in allocated time."); //ensure we were stored to beatmap database backing... From 4393c2cb250d00233b1d6373d89e58a4e388883f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 09:46:14 +0900 Subject: [PATCH 15/22] Add unit tests to ensure all rulesets' beatmaps are added successfully. --- osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index 0c64c47a63..b35f5901be 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -154,7 +154,15 @@ namespace osu.Game.Tests.Beatmaps.IO Assert.IsTrue(set.Beatmaps.Count > 0); var beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 0))?.Beatmap; + Assert.IsTrue(beatmap?.HitObjects.Count > 0); + beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 1))?.Beatmap; + Assert.IsTrue(beatmap?.HitObjects.Count > 0); + + beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 2))?.Beatmap; + Assert.IsTrue(beatmap?.HitObjects.Count > 0); + + beatmap = osu.Dependencies.Get().GetWorkingBeatmap(set.Beatmaps.First(b => b.RulesetID == 3))?.Beatmap; Assert.IsTrue(beatmap?.HitObjects.Count > 0); } } From 2734983564a3fa132242fbe55a794dd124d582ed Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 09:47:16 +0900 Subject: [PATCH 16/22] Add unique constraints on RulesetInfo table to ensure things stay sane. --- osu.Game/Database/RulesetInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Database/RulesetInfo.cs b/osu.Game/Database/RulesetInfo.cs index d7bab39b97..c3c0d4343d 100644 --- a/osu.Game/Database/RulesetInfo.cs +++ b/osu.Game/Database/RulesetInfo.cs @@ -12,8 +12,10 @@ namespace osu.Game.Database [PrimaryKey, AutoIncrement] public int? ID { get; set; } + [Indexed(Unique = true)] public string Name { get; set; } + [Indexed(Unique = true)] public string InstantiationInfo { get; set; } [Indexed] From d3c1520a2d4f851d394b81f49613a25369cbcc53 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 09:47:29 +0900 Subject: [PATCH 17/22] Fix beatmaps not getting the correct ruleset on import. --- osu.Game/Database/BeatmapDatabase.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index 7789096067..e11ea797ca 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -219,10 +219,9 @@ namespace osu.Game.Database beatmap.BeatmapInfo.Metadata = null; // TODO: this should be done in a better place once we actually need to dynamically update it. + beatmap.BeatmapInfo.Ruleset = rulesets.Query().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.StarDifficulty = rulesets.Query().FirstOrDefault(r => r.ID == beatmap.BeatmapInfo.RulesetID)?.CreateInstance()?.CreateDifficultyCalculator(beatmap).Calculate() ?? 0; - beatmap.BeatmapInfo.Ruleset = null; - beatmapSet.Beatmaps.Add(beatmap.BeatmapInfo); } beatmapSet.StoryboardFile = archive.StoryboardFilename; @@ -239,7 +238,7 @@ namespace osu.Game.Database foreach (var s in beatmapSets) { - Connection.InsertWithChildren(s, true); + Connection.InsertOrReplaceWithChildren(s, true); BeatmapSetAdded?.Invoke(s); } From f2174054ea0810a1dccb4b88c4760b23d0edfcce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 10:04:32 +0900 Subject: [PATCH 18/22] Fix song select. --- osu.Game/Database/BeatmapDatabase.cs | 8 +++++--- osu.Game/Screens/Select/BeatmapCarousel.cs | 9 +++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index e11ea797ca..ab2a612176 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -271,12 +271,14 @@ namespace osu.Game.Database { var beatmapSetInfo = Query().FirstOrDefault(s => s.ID == beatmapInfo.BeatmapSetInfoID); - //we need metadata - GetChildren(beatmapSetInfo); - if (beatmapSetInfo == null) throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetInfoID} is not in the local database."); + //we need metadata + GetChildren(beatmapSetInfo); + foreach (var b in beatmapSetInfo.Beatmaps) + GetChildren(b); + if (beatmapInfo.Metadata == null) beatmapInfo.Metadata = beatmapSetInfo.Metadata; diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index f104bf9a37..06aaea041a 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -145,7 +145,7 @@ namespace osu.Game.Screens.Select } } - int startIndex = groups.IndexOf(selectedGroup); + int startIndex = Math.Max(0, groups.IndexOf(selectedGroup)); int index = startIndex; do @@ -221,7 +221,12 @@ namespace osu.Game.Screens.Select private BeatmapGroup createGroup(BeatmapSetInfo beatmapSet) { database.GetChildren(beatmapSet); - beatmapSet.Beatmaps.ForEach(b => { if (b.Metadata == null) b.Metadata = beatmapSet.Metadata; }); + beatmapSet.Beatmaps.ForEach(b => + { + database.GetChildren(b); + if (b.Metadata == null) + b.Metadata = beatmapSet.Metadata; + }); return new BeatmapGroup(beatmapSet, database) { From 6b6690caf7989e566318ad949b22dadf83fc6b2f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 10:04:41 +0900 Subject: [PATCH 19/22] Fix filtering by ruleset. --- osu.Game/Screens/Select/FilterCriteria.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 1a32244deb..11aea3eb4c 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Select { var set = g.BeatmapSet; - bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Ruleset == Ruleset); + bool hasCurrentMode = set.Beatmaps.Any(bm => bm.RulesetID == Ruleset.ID); bool match = hasCurrentMode; From 5939ba9143cf410e32ce2d9b1cd9b3b4d59b34a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 10:55:33 +0900 Subject: [PATCH 20/22] Fix ruleset not always being initialised correctly. --- osu.Desktop.VisualTests/Tests/TestCasePlayer.cs | 2 +- osu.Game/Database/BeatmapDatabase.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index a21c09a9d0..8c3ac526f6 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -39,7 +39,7 @@ namespace osu.Desktop.VisualTests.Tests WorkingBeatmap beatmap = null; - var beatmapInfo = db.Query().FirstOrDefault(b => b.Ruleset.CreateInstance() is OsuRuleset); + var beatmapInfo = db.Query().FirstOrDefault(b => b.RulesetID == 0); if (beatmapInfo != null) beatmap = db.GetWorkingBeatmap(beatmapInfo); diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs index ab2a612176..0e814dea82 100644 --- a/osu.Game/Database/BeatmapDatabase.cs +++ b/osu.Game/Database/BeatmapDatabase.cs @@ -276,8 +276,8 @@ namespace osu.Game.Database //we need metadata GetChildren(beatmapSetInfo); - foreach (var b in beatmapSetInfo.Beatmaps) - GetChildren(b); + //we also need a ruleset + GetChildren(beatmapInfo); if (beatmapInfo.Metadata == null) beatmapInfo.Metadata = beatmapSetInfo.Metadata; From 8ef675d9b3dab2730535eed3124b2737e9d1aac3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 10:55:45 +0900 Subject: [PATCH 21/22] Add fallback to allow FilterCriteria to run without a ruleset being set. --- osu.Game/Screens/Select/FilterCriteria.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 11aea3eb4c..d49c7296ba 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -23,7 +23,7 @@ namespace osu.Game.Screens.Select { var set = g.BeatmapSet; - bool hasCurrentMode = set.Beatmaps.Any(bm => bm.RulesetID == Ruleset.ID); + bool hasCurrentMode = set.Beatmaps.Any(bm => bm.RulesetID == (Ruleset?.ID ?? 0)); bool match = hasCurrentMode; From 7d3a1c5658393f3ec8b50a9ee581752174b659df Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Apr 2017 10:59:50 +0900 Subject: [PATCH 22/22] Remove using. --- osu.Desktop.VisualTests/Tests/TestCasePlayer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs index 8c3ac526f6..8e19419dbb 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs @@ -14,7 +14,6 @@ using osu.Game.Modes.Osu.Objects; using osu.Game.Screens.Play; using OpenTK.Graphics; using osu.Desktop.VisualTests.Beatmaps; -using osu.Game.Modes.Osu; namespace osu.Desktop.VisualTests.Tests {