diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2139572601..68f8ef51ef 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -38,7 +38,7 @@ jobs:
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
- name: Test
- run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --blame-crash --blame-hang --blame-hang-timeout 5m --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
+ run: dotnet test $pwd/*.Tests/bin/Debug/*/*.Tests.dll --logger "trx;LogFileName=TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx"
shell: pwsh
# Attempt to upload results even if test fails.
@@ -48,7 +48,7 @@ jobs:
if: ${{ always() }}
with:
name: osu-test-results-${{matrix.os.prettyname}}-${{matrix.threadingMode}}
- path: ${{github.workspace}}/TestResults/**/*
+ path: ${{github.workspace}}/TestResults/TestResults-${{matrix.os.prettyname}}-${{matrix.threadingMode}}.trx
build-only-android:
name: Build only (Android)
diff --git a/osu.Android.props b/osu.Android.props
index d80fb858e9..d893792285 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs
index e1e7e6ad18..3642f70a56 100644
--- a/osu.Desktop/DiscordRichPresence.cs
+++ b/osu.Desktop/DiscordRichPresence.cs
@@ -108,7 +108,10 @@ namespace osu.Desktop
presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty);
// update ruleset
- presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_custom";
+ int onlineID = ruleset.Value.OnlineID;
+ bool isLegacyRuleset = onlineID >= 0 && onlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID;
+
+ presence.Assets.SmallImageKey = isLegacyRuleset ? $"mode_{onlineID}" : "mode_custom";
presence.Assets.SmallImageText = ruleset.Value.Name;
client.SetPresence(presence);
diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs
index 9c71466489..6e5a546e87 100644
--- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs
@@ -30,7 +30,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
{
var score = decoder.Parse(resourceStream);
- Assert.AreEqual(3, score.ScoreInfo.Ruleset.ID);
+ Assert.AreEqual(3, score.ScoreInfo.Ruleset.OnlineID);
Assert.AreEqual(2, score.ScoreInfo.Statistics[HitResult.Great]);
Assert.AreEqual(1, score.ScoreInfo.Statistics[HitResult.Good]);
diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
index 836cbfa6c5..a404a54ee4 100644
--- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
+++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
@@ -584,7 +584,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{
OnlineID = 1,
Metadata = metadata,
- Beatmaps = new List
+ Beatmaps =
{
new BeatmapInfo
{
diff --git a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs
index f84dbca0be..2a60a7b96d 100644
--- a/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs
+++ b/osu.Game.Tests/Beatmaps/TestSceneBeatmapDifficultyCache.cs
@@ -100,8 +100,8 @@ namespace osu.Game.Tests.Beatmaps
[Test]
public void TestKeyEqualsWithDifferentModInstances()
{
- var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() });
- var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() });
+ var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() });
+ var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() });
Assert.That(key1, Is.EqualTo(key2));
Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode()));
@@ -110,8 +110,8 @@ namespace osu.Game.Tests.Beatmaps
[Test]
public void TestKeyEqualsWithDifferentModOrder()
{
- var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() });
- var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModHidden(), new OsuModHardRock() });
+ var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHardRock(), new OsuModHidden() });
+ var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModHidden(), new OsuModHardRock() });
Assert.That(key1, Is.EqualTo(key2));
Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode()));
@@ -120,8 +120,8 @@ namespace osu.Game.Tests.Beatmaps
[Test]
public void TestKeyDoesntEqualWithDifferentModSettings()
{
- var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } });
- var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } });
+ var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.1 } } });
+ var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.9 } } });
Assert.That(key1, Is.Not.EqualTo(key2));
Assert.That(key1.GetHashCode(), Is.Not.EqualTo(key2.GetHashCode()));
@@ -130,8 +130,8 @@ namespace osu.Game.Tests.Beatmaps
[Test]
public void TestKeyEqualWithMatchingModSettings()
{
- var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
- var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { ID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
+ var key1 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
+ var key2 = new BeatmapDifficultyCache.DifficultyCacheLookup(new BeatmapInfo { ID = 1234 }, new RulesetInfo { OnlineID = 0 }, new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 1.25 } } });
Assert.That(key1, Is.EqualTo(key2));
Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode()));
diff --git a/osu.Game.Tests/Models/DisplayStringTest.cs b/osu.Game.Tests/Models/DisplayStringTest.cs
index 95af21eb5f..2d0bda88e4 100644
--- a/osu.Game.Tests/Models/DisplayStringTest.cs
+++ b/osu.Game.Tests/Models/DisplayStringTest.cs
@@ -29,9 +29,9 @@ namespace osu.Game.Tests.Models
{
var mock = new Mock();
- mock.Setup(m => m.Metadata!.Artist).Returns("artist");
- mock.Setup(m => m.Metadata!.Title).Returns("title");
- mock.Setup(m => m.Metadata!.Author.Username).Returns("author");
+ mock.Setup(m => m.Metadata.Artist).Returns("artist");
+ mock.Setup(m => m.Metadata.Title).Returns("title");
+ mock.Setup(m => m.Metadata.Author.Username).Returns("author");
Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title (author)"));
}
@@ -41,9 +41,9 @@ namespace osu.Game.Tests.Models
{
var mock = new Mock();
- mock.Setup(m => m.Metadata!.Artist).Returns("artist");
- mock.Setup(m => m.Metadata!.Title).Returns("title");
- mock.Setup(m => m.Metadata!.Author.Username).Returns(string.Empty);
+ mock.Setup(m => m.Metadata.Artist).Returns("artist");
+ mock.Setup(m => m.Metadata.Title).Returns("title");
+ mock.Setup(m => m.Metadata.Author.Username).Returns(string.Empty);
Assert.That(mock.Object.GetDisplayString(), Is.EqualTo("artist - title"));
}
diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs
index ee1feeca8d..e49b0d3a67 100644
--- a/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs
+++ b/osu.Game.Tests/NonVisual/Filtering/FilterMatchingTest.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
{
private BeatmapInfo getExampleBeatmap() => new BeatmapInfo
{
- Ruleset = new RulesetInfo { ID = 5 },
+ Ruleset = new RulesetInfo { OnlineID = 5 },
StarRating = 4.0d,
BaseDifficulty = new BeatmapDifficulty
{
@@ -57,7 +57,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
var exampleBeatmapInfo = getExampleBeatmap();
var criteria = new FilterCriteria
{
- Ruleset = new RulesetInfo { ID = 6 }
+ Ruleset = new RulesetInfo { OnlineID = 6 }
};
var carouselItem = new CarouselBeatmap(exampleBeatmapInfo);
carouselItem.Filter(criteria);
@@ -70,7 +70,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
var exampleBeatmapInfo = getExampleBeatmap();
var criteria = new FilterCriteria
{
- Ruleset = new RulesetInfo { ID = 6 },
+ Ruleset = new RulesetInfo { OnlineID = 6 },
AllowConvertedBeatmaps = true
};
var carouselItem = new CarouselBeatmap(exampleBeatmapInfo);
@@ -86,7 +86,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
var exampleBeatmapInfo = getExampleBeatmap();
var criteria = new FilterCriteria
{
- Ruleset = new RulesetInfo { ID = 6 },
+ Ruleset = new RulesetInfo { OnlineID = 6 },
AllowConvertedBeatmaps = true,
ApproachRate = new FilterCriteria.OptionalRange
{
@@ -107,7 +107,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
var exampleBeatmapInfo = getExampleBeatmap();
var criteria = new FilterCriteria
{
- Ruleset = new RulesetInfo { ID = 6 },
+ Ruleset = new RulesetInfo { OnlineID = 6 },
AllowConvertedBeatmaps = true,
BPM = new FilterCriteria.OptionalRange
{
@@ -132,7 +132,7 @@ namespace osu.Game.Tests.NonVisual.Filtering
var exampleBeatmapInfo = getExampleBeatmap();
var criteria = new FilterCriteria
{
- Ruleset = new RulesetInfo { ID = 6 },
+ Ruleset = new RulesetInfo { OnlineID = 6 },
AllowConvertedBeatmaps = true,
SearchText = terms
};
diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
index b66da028f1..a4c69075be 100644
--- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
+++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
@@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -143,7 +143,10 @@ namespace osu.Game.Tests.Online
var beatmap = decoder.Decode(reader);
info = beatmap.BeatmapInfo;
- info.BeatmapSet.Beatmaps = new List { info };
+
+ Debug.Assert(info.BeatmapSet != null);
+
+ info.BeatmapSet.Beatmaps.Add(info);
info.BeatmapSet.Metadata = info.Metadata;
info.MD5Hash = stream.ComputeMD5Hash();
info.Hash = stream.ComputeSHA2Hash();
diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs
index be7803734e..0dee0f89ea 100644
--- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs
+++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs
@@ -142,7 +142,7 @@ namespace osu.Game.Tests.Scores.IO
var scoreManager = osu.Dependencies.Get();
beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.BeatmapInfo.ID)));
- Assert.That(scoreManager.Query(s => s.ID == imported.ID).DeletePending, Is.EqualTo(true));
+ Assert.That(scoreManager.Query(s => s.Equals(imported)).DeletePending, Is.EqualTo(true));
var secondImport = await LoadScoreIntoOsu(osu, imported);
Assert.That(secondImport, Is.Null);
diff --git a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs
index bb9b705c7e..330d3dd2ae 100644
--- a/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs
+++ b/osu.Game.Tests/Testing/TestSceneRulesetDependencies.cs
@@ -70,7 +70,7 @@ namespace osu.Game.Tests.Testing
{
// temporary ID to let RulesetConfigCache pass our
// config manager to the ruleset dependencies.
- RulesetInfo.ID = -1;
+ RulesetInfo.OnlineID = -1;
}
public override IResourceStore CreateResourceStore() => new NamespacedResourceStore(TestResources.GetStore(), @"Resources");
diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs
index cb5058779c..324a132120 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs
@@ -233,7 +233,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
prepareTokenResponse(true);
- createPlayerTest(false, createRuleset: () => new OsuRuleset { RulesetInfo = { ID = rulesetId } });
+ createPlayerTest(false, createRuleset: () => new OsuRuleset { RulesetInfo = { OnlineID = rulesetId ?? -1 } });
AddUntilStep("wait for token request", () => Player.TokenCreationRequested);
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs
index 2a82c65c7c..409cec4cf6 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectatorHost.cs
@@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public void TestClientSendsCorrectRuleset()
{
AddUntilStep("spectator client sending frames", () => spectatorClient.PlayingUserStates.ContainsKey(dummy_user_id));
- AddAssert("spectator client sent correct ruleset", () => spectatorClient.PlayingUserStates[dummy_user_id].RulesetID == Ruleset.Value.ID);
+ AddAssert("spectator client sent correct ruleset", () => spectatorClient.PlayingUserStates[dummy_user_id].RulesetID == Ruleset.Value.OnlineID);
}
public override void TearDownSteps()
diff --git a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs
index 6dda8df6f0..f429b5b2a8 100644
--- a/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs
+++ b/osu.Game.Tests/Visual/Menus/TestSceneMusicActionHandling.cs
@@ -36,7 +36,7 @@ namespace osu.Game.Tests.Visual.Menus
// ensure we have at least two beatmaps available to identify the direction the music controller navigated to.
AddRepeatStep("import beatmap", () => Game.BeatmapManager.Import(new BeatmapSetInfo
{
- Beatmaps = new List
+ Beatmaps =
{
new BeatmapInfo
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs
index aef1fb31d6..6b67a979e5 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSongSelect.cs
@@ -47,6 +47,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
beatmaps = new List();
+ var metadata = new BeatmapMetadata
+ {
+ Artist = "Some Artist",
+ Title = "Some Beatmap",
+ AuthorString = "Some Author"
+ };
+
+ var beatmapSetInfo = new BeatmapSetInfo
+ {
+ OnlineID = 10,
+ Hash = Guid.NewGuid().ToString().ComputeMD5Hash(),
+ Metadata = metadata,
+ DateAdded = DateTimeOffset.UtcNow
+ };
+
for (int i = 0; i < 8; ++i)
{
int beatmapId = 10 * 10 + i;
@@ -54,29 +69,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
int length = RNG.Next(30000, 200000);
double bpm = RNG.NextSingle(80, 200);
- beatmaps.Add(new BeatmapInfo
+ var beatmap = new BeatmapInfo
{
Ruleset = rulesets.GetRuleset(i % 4),
OnlineID = beatmapId,
Length = length,
BPM = bpm,
+ Metadata = metadata,
BaseDifficulty = new BeatmapDifficulty()
- });
+ };
+
+ beatmaps.Add(beatmap);
+ beatmapSetInfo.Beatmaps.Add(beatmap);
}
- manager.Import(new BeatmapSetInfo
- {
- OnlineID = 10,
- Hash = Guid.NewGuid().ToString().ComputeMD5Hash(),
- Metadata = new BeatmapMetadata
- {
- Artist = "Some Artist",
- Title = "Some Beatmap",
- AuthorString = "Some Author"
- },
- Beatmaps = beatmaps,
- DateAdded = DateTimeOffset.UtcNow
- }).Wait();
+ manager.Import(beatmapSetInfo).Wait();
}
public override void SetUpSteps()
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
index c0b21c4421..80f807e7d3 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
@@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
PlaylistItem playlistItem = new PlaylistItem
{
- BeatmapID = beatmapInfo.ID,
+ BeatmapID = beatmapInfo.OnlineID ?? -1,
};
Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem));
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
index d391c39c89..da1fa226e1 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
@@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
PlaylistItem playlistItem = new PlaylistItem
{
- BeatmapID = beatmapInfo.ID,
+ BeatmapID = beatmapInfo.OnlineID ?? -1,
};
SortedDictionary teamScores = new SortedDictionary
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs
index 05f9a94cf7..3e24b7a1d0 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsSongSelect.cs
@@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
@@ -42,7 +41,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
- var beatmaps = new List();
+ var metadata = new BeatmapMetadata
+ {
+ // Create random metadata, then we can check if sorting works based on these
+ Artist = "Some Artist " + RNG.Next(0, 9),
+ Title = "Some Song (set id 10)",
+ AuthorString = "Some Guy " + RNG.Next(0, 9),
+ };
+
+ var beatmapSet = new BeatmapSetInfo
+ {
+ OnlineID = 10,
+ Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
+ Metadata = metadata,
+ DateAdded = DateTimeOffset.UtcNow,
+ };
for (int i = 0; i < 6; i++)
{
@@ -51,12 +64,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
int length = RNG.Next(30000, 200000);
double bpm = RNG.NextSingle(80, 200);
- beatmaps.Add(new BeatmapInfo
+ beatmapSet.Beatmaps.Add(new BeatmapInfo
{
Ruleset = new OsuRuleset().RulesetInfo,
OnlineID = beatmapId,
DifficultyName = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})",
Length = length,
+ Metadata = metadata,
BPM = bpm,
BaseDifficulty = new BeatmapDifficulty
{
@@ -65,20 +79,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
});
}
- manager.Import(new BeatmapSetInfo
- {
- OnlineID = 10,
- Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
- Metadata = new BeatmapMetadata
- {
- // Create random metadata, then we can check if sorting works based on these
- Artist = "Some Artist " + RNG.Next(0, 9),
- Title = $"Some Song (set id 10), max bpm {beatmaps.Max(b => b.BPM):0.#})",
- AuthorString = "Some Guy " + RNG.Next(0, 9),
- },
- Beatmaps = beatmaps,
- DateAdded = DateTimeOffset.UtcNow,
- }).Wait();
+ manager.Import(beatmapSet).Wait();
}
public override void SetUpSteps()
diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs
index d1ee984682..0d0931f871 100644
--- a/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentBeatmap.cs
@@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Screens;
@@ -110,7 +109,7 @@ namespace osu.Game.Tests.Visual.Navigation
Hash = Guid.NewGuid().ToString(),
OnlineID = i,
Metadata = metadata,
- Beatmaps = new List
+ Beatmaps =
{
new BeatmapInfo
{
@@ -141,7 +140,7 @@ namespace osu.Game.Tests.Visual.Navigation
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapSetInfo.MatchesOnlineID(getImport()));
- AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID);
+ AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Beatmaps.First().Ruleset));
}
private void presentSecondDifficultyAndConfirm(Func getImport, int importedID)
@@ -151,7 +150,7 @@ namespace osu.Game.Tests.Visual.Navigation
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect);
AddUntilStep("correct beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.OnlineID == importedID * 2048);
- AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Beatmaps.First().Ruleset.ID);
+ AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Beatmaps.First().Ruleset));
}
}
}
diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs
index 72f160c9a9..c9dec25ad3 100644
--- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs
@@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Screens;
@@ -41,7 +40,7 @@ namespace osu.Game.Tests.Visual.Navigation
Hash = Guid.NewGuid().ToString(),
OnlineID = 1,
Metadata = metadata,
- Beatmaps = new List
+ Beatmaps =
{
new BeatmapInfo
{
@@ -155,15 +154,15 @@ namespace osu.Game.Tests.Visual.Navigation
case ScorePresentType.Results:
AddUntilStep("wait for results", () => lastWaitedScreen != Game.ScreenStack.CurrentScreen && Game.ScreenStack.CurrentScreen is ResultsScreen);
AddStep("store last waited screen", () => lastWaitedScreen = Game.ScreenStack.CurrentScreen);
- AddUntilStep("correct score displayed", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score.ID == getImport().ID);
- AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Ruleset.ID);
+ AddUntilStep("correct score displayed", () => ((ResultsScreen)Game.ScreenStack.CurrentScreen).Score.Equals(getImport()));
+ AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Ruleset));
break;
case ScorePresentType.Gameplay:
AddUntilStep("wait for player loader", () => lastWaitedScreen != Game.ScreenStack.CurrentScreen && Game.ScreenStack.CurrentScreen is ReplayPlayerLoader);
AddStep("store last waited screen", () => lastWaitedScreen = Game.ScreenStack.CurrentScreen);
- AddUntilStep("correct score displayed", () => ((ReplayPlayerLoader)Game.ScreenStack.CurrentScreen).Score.ID == getImport().ID);
- AddAssert("correct ruleset selected", () => Game.Ruleset.Value.ID == getImport().Ruleset.ID);
+ AddUntilStep("correct score displayed", () => ((ReplayPlayerLoader)Game.ScreenStack.CurrentScreen).Score.Equals(getImport()));
+ AddAssert("correct ruleset selected", () => Game.Ruleset.Value.Equals(getImport().Ruleset));
break;
}
}
diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
index ef71c54e03..497c68cf2e 100644
--- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
@@ -257,7 +257,7 @@ namespace osu.Game.Tests.Visual.Navigation
InputManager.ReleaseKey(Key.ControlLeft);
});
- AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.ID == 1);
+ AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.OnlineID == 1);
AddAssert("Mods overlay still visible", () => songSelect.ModSelectOverlay.State.Value == Visibility.Visible);
}
@@ -278,7 +278,7 @@ namespace osu.Game.Tests.Visual.Navigation
InputManager.ReleaseKey(Key.ControlLeft);
});
- AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.ID == 1);
+ AddAssert("Ruleset changed to osu!taiko", () => Game.Toolbar.ChildrenOfType().Single().Current.Value.OnlineID == 1);
AddAssert("Options overlay still visible", () => songSelect.BeatmapOptionsOverlay.State.Value == Visibility.Visible);
}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs
index 86863c0b5d..3314e291e8 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs
@@ -200,7 +200,7 @@ namespace osu.Game.Tests.Visual.Online
{
OnlineID = i * 10,
DifficultyName = $"Test #{i}",
- RulesetID = Ruleset.Value.ID ?? -1,
+ RulesetID = Ruleset.Value.OnlineID,
StarRating = 2 + i * 0.1,
OverallDifficulty = 3.5f,
FailTimes = new APIFailTimes
diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs
index 01dde97d38..510b9e8483 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs
@@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.Online
{
new APIBeatmap
{
- RulesetID = Ruleset.Value.ID ?? 0,
+ RulesetID = Ruleset.Value.OnlineID,
DifficultyName = "Test",
StarRating = 6.42,
}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs
index 7a5ee84eb4..b689b85490 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneNowPlayingCommand.cs
@@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online
AddStep("Set beatmap", () => Beatmap.Value = new DummyWorkingBeatmap(Audio, null)
{
- BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : (int?)null }
+ BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : -1 }
});
AddStep("Run command", () => Add(new NowPlayingCommand()));
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs
index 5c40a3dd94..1808f98c23 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs
@@ -836,23 +836,29 @@ namespace osu.Game.Tests.Visual.SongSelect
private BeatmapSetInfo createTestBeatmapSet(int id, bool randomDifficultyCount = false)
{
- return new BeatmapSetInfo
+ var metadata = new BeatmapMetadata
+ {
+ // Create random metadata, then we can check if sorting works based on these
+ Artist = $"peppy{id.ToString().PadLeft(6, '0')}",
+ Title = $"test set #{id}!",
+ AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5))
+ };
+
+ var beatmapSet = new BeatmapSetInfo
{
ID = id,
OnlineID = id,
Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
- Metadata = new BeatmapMetadata
- {
- // Create random metadata, then we can check if sorting works based on these
- Artist = $"peppy{id.ToString().PadLeft(6, '0')}",
- Title = $"test set #{id}!",
- AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5))
- },
- Beatmaps = getBeatmaps(randomDifficultyCount ? RNG.Next(1, 20) : 3).ToList()
+ Metadata = metadata,
};
+
+ foreach (var b in getBeatmaps(randomDifficultyCount ? RNG.Next(1, 20) : 3, metadata))
+ beatmapSet.Beatmaps.Add(b);
+
+ return beatmapSet;
}
- private IEnumerable getBeatmaps(int count)
+ private IEnumerable getBeatmaps(int count, BeatmapMetadata metadata)
{
int id = 0;
@@ -872,6 +878,7 @@ namespace osu.Game.Tests.Visual.SongSelect
DifficultyName = version,
StarRating = diff,
Ruleset = new OsuRuleset().RulesetInfo,
+ Metadata = metadata,
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = diff,
@@ -882,19 +889,19 @@ namespace osu.Game.Tests.Visual.SongSelect
private BeatmapSetInfo createTestBeatmapSetWithManyDifficulties(int id)
{
+ var metadata = new BeatmapMetadata
+ {
+ // Create random metadata, then we can check if sorting works based on these
+ Artist = $"peppy{id.ToString().PadLeft(6, '0')}",
+ Title = $"test set #{id}!",
+ AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5))
+ };
+
var toReturn = new BeatmapSetInfo
{
- ID = id,
OnlineID = id,
Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
- Metadata = new BeatmapMetadata
- {
- // Create random metadata, then we can check if sorting works based on these
- Artist = $"peppy{id.ToString().PadLeft(6, '0')}",
- Title = $"test set #{id}!",
- AuthorString = string.Concat(Enumerable.Repeat((char)('z' - Math.Min(25, id - 1)), 5))
- },
- Beatmaps = new List(),
+ Metadata = metadata,
};
for (int b = 1; b < 101; b++)
@@ -902,10 +909,10 @@ namespace osu.Game.Tests.Visual.SongSelect
toReturn.Beatmaps.Add(new BeatmapInfo
{
OnlineID = b * 10,
- Path = $"extra{b}.osu",
DifficultyName = $"Extra {b}",
Ruleset = rulesets.GetRuleset((b - 1) % 4),
StarRating = 2,
+ Metadata = metadata,
BaseDifficulty = new BeatmapDifficulty
{
OverallDifficulty = 3.5f,
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs
index c9ec53cfd5..60b6fd81a2 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapRecommendations.cs
@@ -32,7 +32,7 @@ namespace osu.Game.Tests.Visual.SongSelect
switch (req)
{
case GetUserRequest userRequest:
- userRequest.TriggerSuccess(getUser(userRequest.Ruleset.ID));
+ userRequest.TriggerSuccess(getUser(userRequest.Ruleset.OnlineID));
return true;
}
@@ -183,17 +183,18 @@ namespace osu.Game.Tests.Visual.SongSelect
Hash = Guid.NewGuid().ToString(),
OnlineID = importID,
Metadata = metadata,
- Beatmaps = difficultyRulesets.Select((ruleset, difficultyIndex) => new BeatmapInfo
- {
- OnlineID = importID * 1024 + difficultyIndex,
- Metadata = metadata,
- BaseDifficulty = new BeatmapDifficulty(),
- Ruleset = ruleset,
- StarRating = difficultyIndex + 1,
- DifficultyName = $"SR{difficultyIndex + 1}"
- }).ToList()
};
+ beatmapSet.Beatmaps.AddRange(difficultyRulesets.Select((ruleset, difficultyIndex) => new BeatmapInfo
+ {
+ OnlineID = importID * 1024 + difficultyIndex,
+ Metadata = metadata,
+ BaseDifficulty = new BeatmapDifficulty(),
+ Ruleset = ruleset,
+ StarRating = difficultyIndex + 1,
+ DifficultyName = $"SR{difficultyIndex + 1}"
+ }));
+
return Game.BeatmapManager.Import(beatmapSet).Result.Value;
}
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index f09dc38378..5a9a377605 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -258,7 +258,7 @@ namespace osu.Game.Tests.Visual.SongSelect
{
AddStep("import multi-ruleset map", () =>
{
- var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
+ var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
});
}
@@ -354,7 +354,7 @@ namespace osu.Game.Tests.Visual.SongSelect
target = manager.GetAllUsableBeatmapSets()
.Last(b => b.Beatmaps.Any(bi => bi.RulesetID == 0)).Beatmaps.Last();
- Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == 0);
+ Ruleset.Value = rulesets.AvailableRulesets.First(r => r.OnlineID == 0);
Beatmap.Value = manager.GetWorkingBeatmap(target);
});
@@ -385,12 +385,12 @@ namespace osu.Game.Tests.Visual.SongSelect
.Last(b => b.Beatmaps.Any(bi => bi.RulesetID == 0)).Beatmaps.Last();
Beatmap.Value = manager.GetWorkingBeatmap(target);
- Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == 0);
+ Ruleset.Value = rulesets.AvailableRulesets.First(r => r.OnlineID == 0);
});
AddUntilStep("has selection", () => songSelect.Carousel.SelectedBeatmapInfo.Equals(target));
- AddUntilStep("has correct ruleset", () => Ruleset.Value.ID == 0);
+ AddUntilStep("has correct ruleset", () => Ruleset.Value.OnlineID == 0);
// this is an important check, to make sure updateComponentFromBeatmap() was actually run
AddUntilStep("selection shown on wedge", () => songSelect.CurrentBeatmapDetailsBeatmap.BeatmapInfo.MatchesOnlineID(target));
@@ -505,7 +505,7 @@ namespace osu.Game.Tests.Visual.SongSelect
// special case for converts checked here.
return selectedPanel.ChildrenOfType().All(i =>
- i.IsFiltered || i.Item.BeatmapInfo.Ruleset.ID == targetRuleset || i.Item.BeatmapInfo.Ruleset.ID == 0);
+ i.IsFiltered || i.Item.BeatmapInfo.Ruleset.OnlineID == targetRuleset || i.Item.BeatmapInfo.Ruleset.OnlineID == 0);
});
AddUntilStep("carousel has correct", () => songSelect.Carousel.SelectedBeatmapInfo?.MatchesOnlineID(target) == true);
@@ -665,7 +665,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import multi-ruleset map", () =>
{
- var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
+ var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
});
@@ -676,11 +676,11 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("record set ID", () => previousSetID = ((IBeatmapSetInfo)Beatmap.Value.BeatmapSetInfo).OnlineID);
AddAssert("selection changed once", () => changeCount == 1);
- AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
+ AddAssert("Check ruleset is osu!", () => Ruleset.Value.OnlineID == 0);
changeRuleset(3);
- AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
+ AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.OnlineID == 3);
AddUntilStep("selection changed", () => changeCount > 1);
@@ -705,7 +705,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import multi-ruleset map", () =>
{
- var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
+ var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
});
@@ -720,11 +720,11 @@ namespace osu.Game.Tests.Visual.SongSelect
AddUntilStep("Find an icon for different ruleset", () =>
{
difficultyIcon = set.ChildrenOfType()
- .FirstOrDefault(icon => icon.Item.BeatmapInfo.Ruleset.ID == 3);
+ .FirstOrDefault(icon => icon.Item.BeatmapInfo.Ruleset.OnlineID == 3);
return difficultyIcon != null;
});
- AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
+ AddAssert("Check ruleset is osu!", () => Ruleset.Value.OnlineID == 0);
int previousSetID = 0;
@@ -737,7 +737,7 @@ namespace osu.Game.Tests.Visual.SongSelect
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
+ AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.OnlineID == 3);
AddAssert("Selected beatmap still same set", () => songSelect.Carousel.SelectedBeatmapInfo.BeatmapSet.OnlineID == previousSetID);
AddAssert("Selected beatmap is mania", () => Beatmap.Value.BeatmapInfo.Ruleset.OnlineID == 3);
@@ -754,7 +754,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("import huge difficulty count map", () =>
{
- var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
+ var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
imported = manager.Import(createTestBeatmapSet(usableRulesets, 50)).Result.Value;
});
@@ -771,10 +771,10 @@ namespace osu.Game.Tests.Visual.SongSelect
AddUntilStep("Find group icon for different ruleset", () =>
{
return (groupIcon = set.ChildrenOfType()
- .FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.ID == 3)) != null;
+ .FirstOrDefault(icon => icon.Items.First().BeatmapInfo.Ruleset.OnlineID == 3)) != null;
});
- AddAssert("Check ruleset is osu!", () => Ruleset.Value.ID == 0);
+ AddAssert("Check ruleset is osu!", () => Ruleset.Value.OnlineID == 0);
AddStep("Click on group", () =>
{
@@ -783,7 +783,7 @@ namespace osu.Game.Tests.Visual.SongSelect
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.ID == 3);
+ AddUntilStep("Check ruleset changed to mania", () => Ruleset.Value.OnlineID == 3);
AddAssert("Check first item in group selected", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(groupIcon.Items.First().BeatmapInfo));
}
@@ -817,7 +817,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap()));
- AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
+ AddAssert("check ruleset is correct for score", () => Ruleset.Value.OnlineID == 0);
}
[Test]
@@ -849,7 +849,7 @@ namespace osu.Game.Tests.Visual.SongSelect
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
AddAssert("check beatmap is correct for score", () => Beatmap.Value.BeatmapInfo.MatchesOnlineID(getPresentBeatmap()));
- AddAssert("check ruleset is correct for score", () => Ruleset.Value.ID == 0);
+ AddAssert("check ruleset is correct for score", () => Ruleset.Value.OnlineID == 0);
}
private void waitForInitialSelection()
@@ -869,7 +869,7 @@ namespace osu.Game.Tests.Visual.SongSelect
private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id));
- private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait();
+ private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(rulesets.AvailableRulesets.Where(r => r.OnlineID == id).ToArray())).Wait();
private static int importId;
@@ -880,7 +880,7 @@ namespace osu.Game.Tests.Visual.SongSelect
private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => SelectedMods.Value = mods);
- private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));
+ private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.OnlineID == id));
private void createSongSelect()
{
@@ -893,7 +893,7 @@ namespace osu.Game.Tests.Visual.SongSelect
{
AddStep("import test maps", () =>
{
- var usableRulesets = rulesets.AvailableRulesets.Where(r => r.ID != 2).ToArray();
+ var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(usableRulesets)).Wait();
@@ -907,7 +907,21 @@ namespace osu.Game.Tests.Visual.SongSelect
int setId = getImportId();
- var beatmaps = new List();
+ var metadata = new BeatmapMetadata
+ {
+ // Create random metadata, then we can check if sorting works based on these
+ Artist = "Some Artist " + RNG.Next(0, 9),
+ Title = $"Some Song (set id {setId})",
+ AuthorString = "Some Guy " + RNG.Next(0, 9),
+ };
+
+ var beatmapSet = new BeatmapSetInfo
+ {
+ OnlineID = setId,
+ Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
+ DateAdded = DateTimeOffset.UtcNow,
+ Metadata = metadata
+ };
for (int i = 0; i < countPerRuleset; i++)
{
@@ -916,12 +930,13 @@ namespace osu.Game.Tests.Visual.SongSelect
int length = RNG.Next(30000, 200000);
double bpm = RNG.NextSingle(80, 200);
- beatmaps.Add(new BeatmapInfo
+ beatmapSet.Beatmaps.Add(new BeatmapInfo
{
Ruleset = getRuleset(),
OnlineID = beatmapId,
DifficultyName = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})",
Length = length,
+ Metadata = metadata,
BPM = bpm,
BaseDifficulty = new BeatmapDifficulty
{
@@ -930,20 +945,7 @@ namespace osu.Game.Tests.Visual.SongSelect
});
}
- return new BeatmapSetInfo
- {
- OnlineID = setId,
- Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(),
- Metadata = new BeatmapMetadata
- {
- // Create random metadata, then we can check if sorting works based on these
- Artist = "Some Artist " + RNG.Next(0, 9),
- Title = $"Some Song (set id {setId}, max bpm {beatmaps.Max(b => b.BPM):0.#})",
- AuthorString = "Some Guy " + RNG.Next(0, 9),
- },
- Beatmaps = beatmaps,
- DateAdded = DateTimeOffset.UtcNow,
- };
+ return beatmapSet;
}
protected override void Dispose(bool isDisposing)
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs
index 4f7aec3b67..f196bbd76e 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs
@@ -378,9 +378,9 @@ namespace osu.Game.Tests.Visual.UserInterface
});
}
- private void changeRuleset(int? id)
+ private void changeRuleset(int? onlineId)
{
- AddStep($"change ruleset to {(id?.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); });
+ AddStep($"change ruleset to {(onlineId?.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.OnlineID == onlineId); });
waitForLoad();
}
diff --git a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs
index 3c22bdca03..3cd13df0d3 100644
--- a/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs
+++ b/osu.Game.Tournament.Tests/Components/TestSceneTournamentModDisplay.cs
@@ -42,7 +42,12 @@ namespace osu.Game.Tournament.Tests.Components
private void success(APIBeatmap beatmap)
{
- var mods = rulesets.GetRuleset(Ladder.Ruleset.Value.ID ?? 0).CreateInstance().AllMods;
+ var ruleset = rulesets.GetRuleset(Ladder.Ruleset.Value.OnlineID);
+
+ if (ruleset == null)
+ return;
+
+ var mods = ruleset.CreateInstance().AllMods;
foreach (var mod in mods)
{
diff --git a/osu.Game.Tournament/Components/SongBar.cs b/osu.Game.Tournament/Components/SongBar.cs
index a74b88c592..a7f0d58145 100644
--- a/osu.Game.Tournament/Components/SongBar.cs
+++ b/osu.Game.Tournament/Components/SongBar.cs
@@ -127,7 +127,7 @@ namespace osu.Game.Tournament.Components
(string heading, string content)[] stats;
- switch (ruleset.Value.ID)
+ switch (ruleset.Value.OnlineID)
{
default:
stats = new (string heading, string content)[]
diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs
index f444b597c9..61717c18d5 100644
--- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs
+++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs
@@ -340,8 +340,8 @@ namespace osu.Game.Beatmaps
}
public bool Equals(DifficultyCacheLookup other)
- => BeatmapInfo.ID == other.BeatmapInfo.ID
- && Ruleset.ID == other.Ruleset.ID
+ => BeatmapInfo.Equals(other.BeatmapInfo)
+ && Ruleset.Equals(other.Ruleset)
&& OrderedMods.SequenceEqual(other.OrderedMods);
public override int GetHashCode()
@@ -349,7 +349,7 @@ namespace osu.Game.Beatmaps
var hashCode = new HashCode();
hashCode.Add(BeatmapInfo.ID);
- hashCode.Add(Ruleset.ID);
+ hashCode.Add(Ruleset.ShortName);
foreach (var mod in OrderedMods)
hashCode.Add(mod);
diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs
index d2b322a843..782944c28e 100644
--- a/osu.Game/Beatmaps/BeatmapInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapInfo.cs
@@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
-using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Database;
@@ -104,28 +103,6 @@ namespace osu.Game.Beatmaps
///
public int CountdownOffset { get; set; }
- // Editor
- // This bookmarks stuff is necessary because DB doesn't know how to store int[]
- [JsonIgnore]
- public string StoredBookmarks
- {
- get => string.Join(',', Bookmarks);
- set
- {
- if (string.IsNullOrEmpty(value))
- {
- Bookmarks = Array.Empty();
- return;
- }
-
- Bookmarks = value.Split(',').Select(v =>
- {
- bool result = int.TryParse(v, out int val);
- return new { result, val };
- }).Where(p => p.result).Select(p => p.val).ToArray();
- }
- }
-
[NotMapped]
public int[] Bookmarks { get; set; } = Array.Empty();
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index c2a2e93caf..0594cd1316 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -10,7 +10,6 @@ using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework.Audio;
-using osu.Framework.Audio.Mixing;
using osu.Framework.Audio.Track;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
@@ -40,7 +39,7 @@ namespace osu.Game.Beatmaps
private readonly WorkingBeatmapCache workingBeatmapCache;
private readonly BeatmapOnlineLookupQueue onlineBeatmapLookupQueue;
- public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore gameResources, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false, AudioMixer mainTrackMixer = null)
+ public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore gameResources, GameHost host = null, WorkingBeatmap defaultBeatmap = null, bool performOnlineLookups = false)
{
var userResources = new FileStore(contextFactory, storage).Store;
@@ -86,7 +85,7 @@ namespace osu.Game.Beatmaps
var set = new BeatmapSetInfo
{
Metadata = metadata,
- Beatmaps = new List
+ Beatmaps =
{
new BeatmapInfo
{
diff --git a/osu.Game/Beatmaps/BeatmapModelManager.cs b/osu.Game/Beatmaps/BeatmapModelManager.cs
index 8f55232031..ae395c6da6 100644
--- a/osu.Game/Beatmaps/BeatmapModelManager.cs
+++ b/osu.Game/Beatmaps/BeatmapModelManager.cs
@@ -82,7 +82,7 @@ namespace osu.Game.Beatmaps
protected override async Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default)
{
if (archive != null)
- beatmapSet.Beatmaps = createBeatmapDifficulties(beatmapSet.Files);
+ beatmapSet.Beatmaps.AddRange(createBeatmapDifficulties(beatmapSet.Files));
foreach (BeatmapInfo b in beatmapSet.Beatmaps)
{
@@ -208,7 +208,7 @@ namespace osu.Game.Beatmaps
using (ContextFactory.GetForWrite())
{
- beatmapInfo = setInfo.Beatmaps.Single(b => b.ID == beatmapInfo.ID);
+ beatmapInfo = setInfo.Beatmaps.Single(b => b.Equals(beatmapInfo));
var metadata = beatmapInfo.Metadata ?? setInfo.Metadata;
@@ -370,7 +370,6 @@ namespace osu.Game.Beatmaps
return new BeatmapSetInfo
{
OnlineID = beatmap.BeatmapInfo.BeatmapSet?.OnlineID,
- Beatmaps = new List(),
Metadata = beatmap.Metadata,
DateAdded = DateTimeOffset.UtcNow
};
diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs
index 1806c2b491..9a954f94cd 100644
--- a/osu.Game/Beatmaps/BeatmapSetInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs
@@ -5,6 +5,8 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
+using JetBrains.Annotations;
+using Newtonsoft.Json;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Extensions;
@@ -29,7 +31,8 @@ namespace osu.Game.Beatmaps
public BeatmapMetadata Metadata { get; set; }
- public List Beatmaps { get; set; }
+ [NotNull]
+ public List Beatmaps { get; } = new List();
public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None;
@@ -38,17 +41,20 @@ namespace osu.Game.Beatmaps
///
/// The maximum star difficulty of all beatmaps in this set.
///
- public double MaxStarDifficulty => Beatmaps?.Max(b => b.StarRating) ?? 0;
+ [JsonIgnore]
+ public double MaxStarDifficulty => Beatmaps.Count == 0 ? 0 : Beatmaps.Max(b => b.StarRating);
///
/// The maximum playable length in milliseconds of all beatmaps in this set.
///
- public double MaxLength => Beatmaps?.Max(b => b.Length) ?? 0;
+ [JsonIgnore]
+ public double MaxLength => Beatmaps.Count == 0 ? 0 : Beatmaps.Max(b => b.Length);
///
/// The maximum BPM of all beatmaps in this set.
///
- public double MaxBPM => Beatmaps?.Max(b => b.BPM) ?? 0;
+ [JsonIgnore]
+ public double MaxBPM => Beatmaps.Count == 0 ? 0 : Beatmaps.Max(b => b.BPM);
[NotMapped]
public bool DeletePending { get; set; }
@@ -87,7 +93,7 @@ namespace osu.Game.Beatmaps
#region Implementation of IBeatmapSetInfo
- IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => Metadata;
+ IBeatmapMetadataInfo IBeatmapSetInfo.Metadata => Metadata ?? Beatmaps.FirstOrDefault()?.Metadata ?? new BeatmapMetadata();
IEnumerable IBeatmapSetInfo.Beatmaps => Beatmaps;
IEnumerable IBeatmapSetInfo.Files => Files;
diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs
index a2bd7c6ce9..8b00d0f7f2 100644
--- a/osu.Game/Beatmaps/DifficultyRecommender.cs
+++ b/osu.Game/Beatmaps/DifficultyRecommender.cs
@@ -83,7 +83,7 @@ namespace osu.Game.Beatmaps
requestedUserId = api.LocalUser.Value.Id;
// only query API for built-in rulesets
- rulesets.AvailableRulesets.Where(ruleset => ruleset.ID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID).ForEach(rulesetInfo =>
+ rulesets.AvailableRulesets.Where(ruleset => ruleset.OnlineID >= 0 && ruleset.OnlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID).ForEach(rulesetInfo =>
{
var req = new GetUserRequest(api.LocalUser.Value.Id, rulesetInfo);
diff --git a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs
index 1feaa88350..f4501f0633 100644
--- a/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs
+++ b/osu.Game/Beatmaps/Drawables/DifficultySpectrumDisplay.cs
@@ -117,7 +117,7 @@ namespace osu.Game.Beatmaps.Drawables
Spacing = new Vector2(1, 0);
Direction = FillDirection.Horizontal;
- var icon = rulesets.GetRuleset(rulesetId)?.CreateInstance()?.CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle };
+ var icon = rulesets.GetRuleset(rulesetId)?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle };
Add(icon.With(i =>
{
i.Size = new Vector2(14);
diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
index 65d050e608..e5db9d045a 100644
--- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs
@@ -201,7 +201,11 @@ namespace osu.Game.Beatmaps.Formats
switch (pair.Key)
{
case @"Bookmarks":
- beatmap.BeatmapInfo.StoredBookmarks = pair.Value;
+ beatmap.BeatmapInfo.Bookmarks = pair.Value.Split(',').Select(v =>
+ {
+ bool result = int.TryParse(v, out int val);
+ return new { result, val };
+ }).Where(p => p.result).Select(p => p.val).ToArray();
break;
case @"DistanceSpacing":
diff --git a/osu.Game/Beatmaps/IBeatmapSetInfo.cs b/osu.Game/Beatmaps/IBeatmapSetInfo.cs
index 67f38397d4..aa114c8472 100644
--- a/osu.Game/Beatmaps/IBeatmapSetInfo.cs
+++ b/osu.Game/Beatmaps/IBeatmapSetInfo.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Beatmaps
///
/// The best-effort metadata representing this set. In the case metadata differs between contained beatmaps, one is arbitrarily chosen.
///
- IBeatmapMetadataInfo? Metadata { get; }
+ IBeatmapMetadataInfo Metadata { get; }
///
/// All beatmaps contained in this set.
diff --git a/osu.Game/Beatmaps/WorkingBeatmapCache.cs b/osu.Game/Beatmaps/WorkingBeatmapCache.cs
index 0af28902a0..559685d3c4 100644
--- a/osu.Game/Beatmaps/WorkingBeatmapCache.cs
+++ b/osu.Game/Beatmaps/WorkingBeatmapCache.cs
@@ -55,8 +55,6 @@ namespace osu.Game.Beatmaps
public void Invalidate(BeatmapSetInfo info)
{
- if (info.Beatmaps == null) return;
-
foreach (var b in info.Beatmaps)
Invalidate(b);
}
@@ -65,7 +63,7 @@ namespace osu.Game.Beatmaps
{
lock (workingCache)
{
- var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == info.ID);
+ var working = workingCache.FirstOrDefault(w => info.Equals(w.BeatmapInfo));
if (working != null)
{
@@ -89,7 +87,7 @@ namespace osu.Game.Beatmaps
lock (workingCache)
{
- var working = workingCache.FirstOrDefault(w => w.BeatmapInfo?.ID == beatmapInfo.ID);
+ var working = workingCache.FirstOrDefault(w => beatmapInfo.Equals(w.BeatmapInfo));
if (working != null)
return working;
diff --git a/osu.Game/Database/RealmContextFactory.cs b/osu.Game/Database/RealmContextFactory.cs
index 0e602da190..d0ca2f0fd4 100644
--- a/osu.Game/Database/RealmContextFactory.cs
+++ b/osu.Game/Database/RealmContextFactory.cs
@@ -41,8 +41,9 @@ namespace osu.Game.Database
/// 8 2021-10-29 Rebind scroll adjust keys to not have control modifier.
/// 9 2021-11-04 Converted BeatmapMetadata.Author from string to RealmUser.
/// 10 2021-11-22 Use ShortName instead of RulesetID for ruleset settings.
+ /// 11 2021-11-22 Use ShortName instead of RulesetID for ruleset key bindings.
///
- private const int schema_version = 10;
+ private const int schema_version = 11;
///
/// Lock object which is held during sections, blocking context creation during blocking periods.
@@ -94,7 +95,12 @@ namespace osu.Game.Database
if (!Filename.EndsWith(realm_extension, StringComparison.Ordinal))
Filename += realm_extension;
+ // This method triggers the first `CreateContext` call, which will implicitly run realm migrations and bring the schema up-to-date.
cleanupPendingDeletions();
+
+ // Data migration is handled separately from schema migrations.
+ // This is required as the user may be initialising realm for the first time ever, which would result in no schema migrations running.
+ migrateDataFromEF();
}
private void cleanupPendingDeletions()
@@ -162,6 +168,53 @@ namespace osu.Game.Database
};
}
+ private void migrateDataFromEF()
+ {
+ if (efContextFactory == null)
+ return;
+
+ using (var db = efContextFactory.GetForWrite())
+ {
+ // migrate ruleset settings. can be removed 20220315.
+ var existingSettings = db.Context.DatabasedSetting;
+
+ // previous entries in EF are removed post migration.
+ if (!existingSettings.Any())
+ return;
+
+ using (var realm = CreateContext())
+ using (var transaction = realm.BeginWrite())
+ {
+ // only migrate data if the realm database is empty.
+ if (!realm.All().Any())
+ {
+ foreach (var dkb in existingSettings)
+ {
+ if (dkb.RulesetID == null)
+ continue;
+
+ string? shortName = getRulesetShortNameFromLegacyID(dkb.RulesetID.Value);
+
+ if (string.IsNullOrEmpty(shortName))
+ continue;
+
+ realm.Add(new RealmRulesetSetting
+ {
+ Key = dkb.Key,
+ Value = dkb.StringValue,
+ RulesetName = shortName,
+ Variant = dkb.Variant ?? 0,
+ });
+ }
+ }
+
+ db.Context.RemoveRange(existingSettings);
+
+ transaction.Commit();
+ }
+ }
+ }
+
private void onMigration(Migration migration, ulong lastSchemaVersion)
{
for (ulong i = lastSchemaVersion + 1; i <= schema_version; i++)
@@ -265,6 +318,31 @@ namespace osu.Game.Database
newItem.RulesetName = rulesetName;
}
+ break;
+
+ case 11:
+ string keyBindingClassName = getMappedOrOriginalName(typeof(RealmKeyBinding));
+
+ var oldKeyBindings = migration.OldRealm.DynamicApi.All(keyBindingClassName);
+ var newKeyBindings = migration.NewRealm.All().ToList();
+
+ for (int i = 0; i < newKeyBindings.Count; i++)
+ {
+ dynamic? oldItem = oldKeyBindings.ElementAt(i);
+ var newItem = newKeyBindings.ElementAt(i);
+
+ if (oldItem.RulesetID == null)
+ continue;
+
+ long rulesetId = oldItem.RulesetID;
+ string? rulesetName = getRulesetShortNameFromLegacyID(rulesetId);
+
+ if (string.IsNullOrEmpty(rulesetName))
+ migration.NewRealm.Remove(newItem);
+ else
+ newItem.RulesetName = rulesetName;
+ }
+
break;
}
}
diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs
index aaf87385c8..9f00d21383 100644
--- a/osu.Game/Extensions/ModelExtensions.cs
+++ b/osu.Game/Extensions/ModelExtensions.cs
@@ -42,7 +42,7 @@ namespace osu.Game.Extensions
switch (model)
{
case IBeatmapSetInfo beatmapSetInfo:
- result = beatmapSetInfo.Metadata?.GetDisplayTitle();
+ result = beatmapSetInfo.Metadata.GetDisplayTitle();
break;
case IBeatmapInfo beatmapInfo:
diff --git a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
index 5dced23614..baa5b9ff9c 100644
--- a/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
+++ b/osu.Game/Input/Bindings/DatabasedKeyBindingContainer.cs
@@ -50,23 +50,20 @@ namespace osu.Game.Input.Bindings
protected override void LoadComplete()
{
- if (ruleset == null || ruleset.ID.HasValue)
- {
- int? rulesetId = ruleset?.ID;
+ string rulesetName = ruleset?.ShortName;
- realmKeyBindings = realmFactory.Context.All()
- .Where(b => b.RulesetID == rulesetId && b.Variant == variant);
+ realmKeyBindings = realmFactory.Context.All()
+ .Where(b => b.RulesetName == rulesetName && b.Variant == variant);
- realmSubscription = realmKeyBindings
- .SubscribeForNotifications((sender, changes, error) =>
- {
- // first subscription ignored as we are handling this in LoadComplete.
- if (changes == null)
- return;
+ realmSubscription = realmKeyBindings
+ .SubscribeForNotifications((sender, changes, error) =>
+ {
+ // first subscription ignored as we are handling this in LoadComplete.
+ if (changes == null)
+ return;
- ReloadMappings();
- });
- }
+ ReloadMappings();
+ });
base.LoadComplete();
}
diff --git a/osu.Game/Input/Bindings/RealmKeyBinding.cs b/osu.Game/Input/Bindings/RealmKeyBinding.cs
index 334d2da427..6a408847fe 100644
--- a/osu.Game/Input/Bindings/RealmKeyBinding.cs
+++ b/osu.Game/Input/Bindings/RealmKeyBinding.cs
@@ -6,6 +6,8 @@ using osu.Framework.Input.Bindings;
using osu.Game.Database;
using Realms;
+#nullable enable
+
namespace osu.Game.Input.Bindings
{
[MapTo(nameof(KeyBinding))]
@@ -14,7 +16,7 @@ namespace osu.Game.Input.Bindings
[PrimaryKey]
public Guid ID { get; set; } = Guid.NewGuid();
- public int? RulesetID { get; set; }
+ public string? RulesetName { get; set; }
public int? Variant { get; set; }
@@ -34,6 +36,6 @@ namespace osu.Game.Input.Bindings
public int ActionInt { get; set; }
[MapTo(nameof(KeyCombination))]
- public string KeyCombinationString { get; set; }
+ public string KeyCombinationString { get; set; } = string.Empty;
}
}
diff --git a/osu.Game/Input/RealmKeyBindingStore.cs b/osu.Game/Input/RealmKeyBindingStore.cs
index 046969579c..3bdb0a180d 100644
--- a/osu.Game/Input/RealmKeyBindingStore.cs
+++ b/osu.Game/Input/RealmKeyBindingStore.cs
@@ -36,7 +36,7 @@ namespace osu.Game.Input
using (var context = realmFactory.CreateContext())
{
- foreach (var action in context.All().Where(b => b.RulesetID == null && (GlobalAction)b.ActionInt == globalAction))
+ foreach (var action in context.All().Where(b => string.IsNullOrEmpty(b.RulesetName) && (GlobalAction)b.ActionInt == globalAction))
{
string str = keyCombinationProvider.GetReadableString(action.KeyCombination);
@@ -69,20 +69,20 @@ namespace osu.Game.Input
{
var instance = ruleset.CreateInstance();
foreach (int variant in instance.AvailableVariants)
- insertDefaults(realm, existingBindings, instance.GetDefaultKeyBindings(variant), ruleset.ID, variant);
+ insertDefaults(realm, existingBindings, instance.GetDefaultKeyBindings(variant), ruleset.ShortName, variant);
}
transaction.Commit();
}
}
- private void insertDefaults(Realm realm, List existingBindings, IEnumerable defaults, int? rulesetId = null, int? variant = null)
+ private void insertDefaults(Realm realm, List existingBindings, IEnumerable defaults, string? rulesetName = null, int? variant = null)
{
// compare counts in database vs defaults for each action type.
foreach (var defaultsForAction in defaults.GroupBy(k => k.Action))
{
// avoid performing redundant queries when the database is empty and needs to be re-filled.
- int existingCount = existingBindings.Count(k => k.RulesetID == rulesetId && k.Variant == variant && k.ActionInt == (int)defaultsForAction.Key);
+ int existingCount = existingBindings.Count(k => k.RulesetName == rulesetName && k.Variant == variant && k.ActionInt == (int)defaultsForAction.Key);
if (defaultsForAction.Count() <= existingCount)
continue;
@@ -92,7 +92,7 @@ namespace osu.Game.Input
{
KeyCombinationString = k.KeyCombination.ToString(),
ActionInt = (int)k.Action,
- RulesetID = rulesetId,
+ RulesetName = rulesetName,
Variant = variant
}));
}
diff --git a/osu.Game/Models/RealmBeatmapSet.cs b/osu.Game/Models/RealmBeatmapSet.cs
index da75978977..ff39bcf13e 100644
--- a/osu.Game/Models/RealmBeatmapSet.cs
+++ b/osu.Game/Models/RealmBeatmapSet.cs
@@ -26,7 +26,7 @@ namespace osu.Game.Models
public DateTimeOffset DateAdded { get; set; }
- public IBeatmapMetadataInfo? Metadata => Beatmaps.FirstOrDefault()?.Metadata;
+ public IBeatmapMetadataInfo Metadata => Beatmaps.FirstOrDefault()?.Metadata ?? new RealmBeatmapMetadata();
public IList Beatmaps { get; } = null!;
@@ -62,7 +62,7 @@ namespace osu.Game.Models
return ID == other.ID;
}
- public override string ToString() => Metadata?.GetDisplayString() ?? base.ToString();
+ public override string ToString() => Metadata.GetDisplayString();
public bool Equals(IBeatmapSetInfo? other) => other is RealmBeatmapSet b && Equals(b);
diff --git a/osu.Game/Models/RealmRuleset.cs b/osu.Game/Models/RealmRuleset.cs
index 5d70324713..9a7488fda2 100644
--- a/osu.Game/Models/RealmRuleset.cs
+++ b/osu.Game/Models/RealmRuleset.cs
@@ -25,12 +25,12 @@ namespace osu.Game.Models
public string InstantiationInfo { get; set; } = string.Empty;
- public RealmRuleset(string shortName, string name, string instantiationInfo, int? onlineID = null)
+ public RealmRuleset(string shortName, string name, string instantiationInfo, int onlineID)
{
ShortName = shortName;
Name = name;
InstantiationInfo = instantiationInfo;
- OnlineID = onlineID ?? -1;
+ OnlineID = onlineID;
}
[UsedImplicitly]
@@ -60,5 +60,27 @@ namespace osu.Game.Models
InstantiationInfo = InstantiationInfo,
Available = Available
};
+
+ public Ruleset CreateInstance()
+ {
+ if (!Available)
+ throw new RulesetLoadException(@"Ruleset not available");
+
+ var type = Type.GetType(InstantiationInfo);
+
+ if (type == null)
+ throw new RulesetLoadException(@"Type lookup failure");
+
+ var ruleset = Activator.CreateInstance(type) as Ruleset;
+
+ if (ruleset == null)
+ throw new RulesetLoadException(@"Instantiation failure");
+
+ // overwrite the pre-populated RulesetInfo with a potentially database attached copy.
+ // TODO: figure if we still want/need this after switching to realm.
+ // ruleset.RulesetInfo = this;
+
+ return ruleset;
+ }
}
}
diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs
index 3fb9335629..243c39ab53 100644
--- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs
@@ -98,7 +98,7 @@ namespace osu.Game.Online.API.Requests.Responses
public string MD5Hash => Checksum;
- public IRulesetInfo Ruleset => new RulesetInfo { ID = RulesetID };
+ public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID };
[JsonIgnore]
public string Hash => throw new NotImplementedException();
diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs
index d0677eacab..0a2d6ca7b0 100644
--- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs
@@ -146,7 +146,7 @@ namespace osu.Game.Online.API.Requests.Responses
return scoreInfo;
}
- public IRulesetInfo Ruleset => new RulesetInfo { ID = RulesetID };
+ public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID };
IBeatmapInfo IScoreInfo.Beatmap => Beatmap;
}
diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs
index ae082ca82e..736024b08b 100644
--- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs
+++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs
@@ -86,8 +86,8 @@ namespace osu.Game.Online.API.Requests
if (General != null && General.Any())
req.AddParameter("c", string.Join('.', General.Select(e => e.ToString().Underscore())));
- if (ruleset.ID.HasValue)
- req.AddParameter("m", ruleset.ID.Value.ToString());
+ if (ruleset.OnlineID >= 0)
+ req.AddParameter("m", ruleset.OnlineID.ToString());
req.AddParameter("s", SearchCategory.ToString().ToLowerInvariant());
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 1890fd7d24..dd4ae590c7 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -214,7 +214,7 @@ namespace osu.Game
SkinManager.ItemRemoved += item => Schedule(() =>
{
// check the removed skin is not the current user choice. if it is, switch back to default.
- if (item.ID == SkinManager.CurrentSkinInfo.Value.ID)
+ if (item.Equals(SkinManager.CurrentSkinInfo.Value))
SkinManager.CurrentSkinInfo.Value = SkinInfo.Default;
});
@@ -262,8 +262,6 @@ namespace osu.Game
dependencies.Cache(scorePerformanceManager);
AddInternal(scorePerformanceManager);
- migrateDataToRealm();
-
dependencies.Cache(rulesetConfigCache = new RulesetConfigCache(realmFactory, RulesetStore));
var powerStatus = CreateBatteryInfo();
@@ -439,35 +437,6 @@ namespace osu.Game
private void migrateDataToRealm()
{
- using (var db = contextFactory.GetForWrite())
- using (var realm = realmFactory.CreateContext())
- using (var transaction = realm.BeginWrite())
- {
- // migrate ruleset settings. can be removed 20220315.
- var existingSettings = db.Context.DatabasedSetting;
-
- // only migrate data if the realm database is empty.
- if (!realm.All().Any())
- {
- foreach (var dkb in existingSettings)
- {
- if (dkb.RulesetID == null) continue;
-
- realm.Add(new RealmRulesetSetting
- {
- Key = dkb.Key,
- Value = dkb.StringValue,
- // important: this RulesetStore must be the EF one.
- RulesetName = RulesetStore.GetRuleset(dkb.RulesetID.Value).ShortName,
- Variant = dkb.Variant ?? 0,
- });
- }
- }
-
- db.Context.RemoveRange(existingSettings);
-
- transaction.Commit();
- }
}
private void onRulesetChanged(ValueChangedEvent r)
diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs
index b8d04eab4e..78b2d58dae 100644
--- a/osu.Game/Overlays/Music/PlaylistOverlay.cs
+++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs
@@ -77,7 +77,7 @@ namespace osu.Game.Overlays.Music
filter.Search.OnCommit += (sender, newText) =>
{
- BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
+ BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps.FirstOrDefault();
if (toSelect != null)
{
@@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Music
private void itemSelected(BeatmapSetInfo set)
{
- if (set.ID == (beatmap.Value?.BeatmapSetInfo?.ID ?? -1))
+ if (set.Equals((beatmap.Value?.BeatmapSetInfo)))
{
beatmap.Value?.Track.Seek(0);
return;
diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs
index 829ff5be25..76358fca3f 100644
--- a/osu.Game/Overlays/MusicController.cs
+++ b/osu.Game/Overlays/MusicController.cs
@@ -111,7 +111,7 @@ namespace osu.Game.Overlays
beatmapSets.Add(set);
});
- private void beatmapRemoved(BeatmapSetInfo set) => Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID));
+ private void beatmapRemoved(BeatmapSetInfo set) => Schedule(() => beatmapSets.RemoveAll(s => s.Equals(set)));
private ScheduledDelegate seekDelegate;
@@ -228,7 +228,7 @@ namespace osu.Game.Overlays
queuedDirection = TrackChangeDirection.Prev;
- var playable = BeatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? BeatmapSets.LastOrDefault();
+ var playable = BeatmapSets.TakeWhile(i => !i.Equals(current.BeatmapSetInfo)).LastOrDefault() ?? BeatmapSets.LastOrDefault();
if (playable != null)
{
@@ -259,7 +259,7 @@ namespace osu.Game.Overlays
queuedDirection = TrackChangeDirection.Next;
- var playable = BeatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).ElementAtOrDefault(1) ?? BeatmapSets.FirstOrDefault();
+ var playable = BeatmapSets.SkipWhile(i => !i.Equals(current.BeatmapSetInfo)).ElementAtOrDefault(1) ?? BeatmapSets.FirstOrDefault();
if (playable != null)
{
@@ -309,8 +309,8 @@ namespace osu.Game.Overlays
else
{
// figure out the best direction based on order in playlist.
- int last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count();
- int next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != newWorking.BeatmapSetInfo?.ID).Count();
+ int last = BeatmapSets.TakeWhile(b => !b.Equals(current.BeatmapSetInfo)).Count();
+ int next = newWorking == null ? -1 : BeatmapSets.TakeWhile(b => !b.Equals(newWorking.BeatmapSetInfo)).Count();
direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next;
}
diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs
index eaa9703834..4d2290266c 100644
--- a/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs
+++ b/osu.Game/Overlays/Profile/Header/Components/ProfileRulesetSelector.cs
@@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Profile.Header.Components
public void SetDefaultRuleset(RulesetInfo ruleset)
{
foreach (var tabItem in TabContainer)
- ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.ID == ruleset.ID;
+ ((ProfileRulesetTabItem)tabItem).IsDefault = ((ProfileRulesetTabItem)tabItem).Value.Equals(ruleset);
}
protected override TabItem CreateTabItem(RulesetInfo value) => new ProfileRulesetTabItem(value);
diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs
index 96a685a9c5..e0a1a82326 100644
--- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs
+++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingRow.cs
@@ -524,7 +524,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
public void UpdateKeyCombination(KeyCombination newCombination)
{
- if (KeyBinding.RulesetID != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
+ if (KeyBinding.RulesetName != null && !RealmKeyBindingStore.CheckValidForGameplay(newCombination))
return;
KeyBinding.KeyCombination = newCombination;
diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs
index be0830a7c2..115a7bdc79 100644
--- a/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs
+++ b/osu.Game/Overlays/Settings/Sections/Input/KeyBindingsSubsection.cs
@@ -32,12 +32,12 @@ namespace osu.Game.Overlays.Settings.Sections.Input
[BackgroundDependencyLoader]
private void load(RealmContextFactory realmFactory)
{
- int? rulesetId = Ruleset?.ID;
+ string rulesetName = Ruleset?.ShortName;
List bindings;
using (var realm = realmFactory.CreateContext())
- bindings = realm.All().Where(b => b.RulesetID == rulesetId && b.Variant == variant).Detach();
+ bindings = realm.All().Where(b => b.RulesetName == rulesetName && b.Variant == variant).Detach();
foreach (var defaultGroup in Defaults.GroupBy(d => d.Action))
{
diff --git a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs
index 48cbe1b59e..b5d26d4887 100644
--- a/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs
+++ b/osu.Game/Overlays/Settings/Sections/Input/RulesetBindingsSection.cs
@@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{
public class RulesetBindingsSection : SettingsSection
{
- public override Drawable CreateIcon() => ruleset?.CreateInstance()?.CreateIcon() ?? new SpriteIcon
+ public override Drawable CreateIcon() => ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon
{
Icon = OsuIcon.Hot
};
diff --git a/osu.Game/Overlays/Settings/Sections/SkinSection.cs b/osu.Game/Overlays/Settings/Sections/SkinSection.cs
index 0714b28b47..e7a7abed59 100644
--- a/osu.Game/Overlays/Settings/Sections/SkinSection.cs
+++ b/osu.Game/Overlays/Settings/Sections/SkinSection.cs
@@ -132,7 +132,7 @@ namespace osu.Game.Overlays.Settings.Sections
skinDropdown.Items = newDropdownItems;
}
- private void itemRemoved(SkinInfo item) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != item.ID).ToArray());
+ private void itemRemoved(SkinInfo item) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => !i.Equals(item)).ToArray());
private void sortUserSkins(List skinsList)
{
diff --git a/osu.Game/Overlays/Toolbar/ToolbarButton.cs b/osu.Game/Overlays/Toolbar/ToolbarButton.cs
index b2252a5575..75bebfa763 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarButton.cs
@@ -207,7 +207,7 @@ namespace osu.Game.Overlays.Toolbar
{
if (Hotkey == null) return;
- var realmKeyBinding = realmFactory.Context.All().FirstOrDefault(rkb => rkb.RulesetID == null && rkb.ActionInt == (int)Hotkey.Value);
+ var realmKeyBinding = realmFactory.Context.All().FirstOrDefault(rkb => rkb.RulesetName == null && rkb.ActionInt == (int)Hotkey.Value);
if (realmKeyBinding != null)
{
diff --git a/osu.Game/Rulesets/IRulesetInfo.cs b/osu.Game/Rulesets/IRulesetInfo.cs
index c3bc6c1995..4e529a73fb 100644
--- a/osu.Game/Rulesets/IRulesetInfo.cs
+++ b/osu.Game/Rulesets/IRulesetInfo.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System;
using osu.Game.Database;
#nullable enable
@@ -28,20 +27,6 @@ namespace osu.Game.Rulesets
///
string InstantiationInfo { get; }
- Ruleset? CreateInstance()
- {
- var type = Type.GetType(InstantiationInfo);
-
- if (type == null)
- return null;
-
- var ruleset = Activator.CreateInstance(type) as Ruleset;
-
- // overwrite the pre-populated RulesetInfo with a potentially database attached copy.
- // TODO: figure if we still want/need this after switching to realm.
- // ruleset.RulesetInfo = this;
-
- return ruleset;
- }
+ Ruleset CreateInstance();
}
}
diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs
index 31ebcfd600..d279f6d6ee 100644
--- a/osu.Game/Rulesets/Ruleset.cs
+++ b/osu.Game/Rulesets/Ruleset.cs
@@ -183,7 +183,7 @@ namespace osu.Game.Rulesets
{
Name = Description,
ShortName = ShortName,
- ID = (this as ILegacyRuleset)?.LegacyID,
+ OnlineID = (this as ILegacyRuleset)?.LegacyID ?? -1,
InstantiationInfo = GetType().GetInvariantInstantiationInfo(),
Available = true,
};
diff --git a/osu.Game/Rulesets/RulesetConfigCache.cs b/osu.Game/Rulesets/RulesetConfigCache.cs
index aeac052673..262340b4ee 100644
--- a/osu.Game/Rulesets/RulesetConfigCache.cs
+++ b/osu.Game/Rulesets/RulesetConfigCache.cs
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets
private readonly RealmContextFactory realmFactory;
private readonly RulesetStore rulesets;
- private readonly Dictionary configCache = new Dictionary();
+ private readonly Dictionary configCache = new Dictionary();
public RulesetConfigCache(RealmContextFactory realmFactory, RulesetStore rulesets)
{
@@ -36,10 +36,10 @@ namespace osu.Game.Rulesets
// let's keep things simple for now and just retrieve all the required configs at startup..
foreach (var ruleset in rulesets.AvailableRulesets)
{
- if (ruleset.ID == null)
+ if (string.IsNullOrEmpty(ruleset.ShortName))
continue;
- configCache[ruleset.ID.Value] = ruleset.CreateInstance().CreateConfig(settingsStore);
+ configCache[ruleset.ShortName] = ruleset.CreateInstance().CreateConfig(settingsStore);
}
}
@@ -51,10 +51,7 @@ namespace osu.Game.Rulesets
/// If doesn't have a valid .
public IRulesetConfigManager GetConfigFor(Ruleset ruleset)
{
- if (ruleset.RulesetInfo.ID == null)
- return null;
-
- if (!configCache.TryGetValue(ruleset.RulesetInfo.ID.Value, out var config))
+ if (!configCache.TryGetValue(ruleset.RulesetInfo.ShortName, out var config))
// any ruleset request which wasn't initialised on startup should not be stored to realm.
// this should only be used by tests.
return ruleset.CreateConfig(null);
diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs
index ccb614fe91..4a146c05bf 100644
--- a/osu.Game/Rulesets/RulesetInfo.cs
+++ b/osu.Game/Rulesets/RulesetInfo.cs
@@ -2,9 +2,9 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
-using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Testing;
namespace osu.Game.Rulesets
@@ -26,9 +26,18 @@ namespace osu.Game.Rulesets
// TODO: this should probably be moved to RulesetStore.
public Ruleset CreateInstance()
{
- if (!Available) return null;
+ if (!Available)
+ throw new RulesetLoadException(@"Ruleset not available");
- var ruleset = (Ruleset)Activator.CreateInstance(Type.GetType(InstantiationInfo).AsNonNull());
+ var type = Type.GetType(InstantiationInfo);
+
+ if (type == null)
+ throw new RulesetLoadException(@"Type lookup failure");
+
+ var ruleset = Activator.CreateInstance(type) as Ruleset;
+
+ if (ruleset == null)
+ throw new RulesetLoadException(@"Instantiation failure");
// overwrite the pre-populated RulesetInfo with a potentially database attached copy.
ruleset.RulesetInfo = this;
@@ -57,7 +66,12 @@ namespace osu.Game.Rulesets
#region Implementation of IHasOnlineID
- public int OnlineID => ID ?? -1;
+ [NotMapped]
+ public int OnlineID
+ {
+ get => ID ?? -1;
+ set => ID = value >= 0 ? value : (int?)null;
+ }
#endregion
}
diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs
index 7ac4f90c07..f943422389 100644
--- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs
+++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs
@@ -140,7 +140,7 @@ namespace osu.Game.Scoring.Legacy
int countGeki = score.GetCountGeki() ?? 0;
int countKatu = score.GetCountKatu() ?? 0;
- switch (score.Ruleset.ID)
+ switch (score.Ruleset.OnlineID)
{
case 0:
{
diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs
index 5769406948..7b8cacb35b 100644
--- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs
+++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs
@@ -42,7 +42,7 @@ namespace osu.Game.Scoring.Legacy
{
using (SerializationWriter sw = new SerializationWriter(stream))
{
- sw.Write((byte)(score.ScoreInfo.Ruleset.ID ?? 0));
+ sw.Write((byte)(score.ScoreInfo.Ruleset.OnlineID));
sw.Write(LATEST_VERSION);
sw.Write(score.ScoreInfo.BeatmapInfo.MD5Hash);
sw.Write(score.ScoreInfo.UserString);
diff --git a/osu.Game/Screens/Edit/Setup/SetupScreen.cs b/osu.Game/Screens/Edit/Setup/SetupScreen.cs
index 04767f1786..8d726f7752 100644
--- a/osu.Game/Screens/Edit/Setup/SetupScreen.cs
+++ b/osu.Game/Screens/Edit/Setup/SetupScreen.cs
@@ -33,7 +33,7 @@ namespace osu.Game.Screens.Edit.Setup
new DesignSection(),
};
- var rulesetSpecificSection = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateEditorSetupSection();
+ var rulesetSpecificSection = beatmap.BeatmapInfo.Ruleset?.CreateInstance().CreateEditorSetupSection();
if (rulesetSpecificSection != null)
sectionsEnumerable.Add(rulesetSpecificSection);
diff --git a/osu.Game/Screens/Edit/Verify/IssueList.cs b/osu.Game/Screens/Edit/Verify/IssueList.cs
index 0b1f988447..fd238feeac 100644
--- a/osu.Game/Screens/Edit/Verify/IssueList.cs
+++ b/osu.Game/Screens/Edit/Verify/IssueList.cs
@@ -43,7 +43,7 @@ namespace osu.Game.Screens.Edit.Verify
private void load(OverlayColourProvider colours)
{
generalVerifier = new BeatmapVerifier();
- rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance()?.CreateBeatmapVerifier();
+ rulesetVerifier = beatmap.BeatmapInfo.Ruleset?.CreateInstance().CreateBeatmapVerifier();
context = new BeatmapVerifierContext(beatmap, workingBeatmap.Value, verify.InterpretedDifficulty.Value);
verify.InterpretedDifficulty.BindValueChanged(difficulty => context.InterpretedDifficulty = difficulty.NewValue);
diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs
index 6cea75af0a..c8d831ebe6 100644
--- a/osu.Game/Screens/Play/SoloPlayer.cs
+++ b/osu.Game/Screens/Play/SoloPlayer.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Rooms;
using osu.Game.Online.Solo;
@@ -25,10 +26,13 @@ namespace osu.Game.Screens.Play
protected override APIRequest CreateTokenRequest()
{
- if (!(Beatmap.Value.BeatmapInfo.OnlineID is int beatmapId))
+ int beatmapId = Beatmap.Value.BeatmapInfo.OnlineID ?? -1;
+ int rulesetId = Ruleset.Value.OnlineID;
+
+ if (beatmapId <= 0)
return null;
- if (!(Ruleset.Value.ID is int rulesetId) || Ruleset.Value.ID > ILegacyRuleset.MAX_LEGACY_RULESET_ID)
+ if (rulesetId < 0 || rulesetId > ILegacyRuleset.MAX_LEGACY_RULESET_ID)
return null;
return new CreateSoloScoreRequest(beatmapId, rulesetId, Game.VersionHash);
@@ -38,13 +42,11 @@ namespace osu.Game.Screens.Play
protected override APIRequest CreateSubmissionRequest(Score score, long token)
{
- var beatmap = score.ScoreInfo.BeatmapInfo;
+ IBeatmapInfo beatmap = score.ScoreInfo.BeatmapInfo;
- Debug.Assert(beatmap.OnlineID != null);
+ Debug.Assert(beatmap.OnlineID > 0);
- int beatmapId = beatmap.OnlineID.Value;
-
- return new SubmitSoloScoreRequest(beatmapId, token, score.ScoreInfo);
+ return new SubmitSoloScoreRequest(beatmap.OnlineID, token, score.ScoreInfo);
}
}
}
diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs
index 0fc7a99c96..b0d0821ee9 100644
--- a/osu.Game/Screens/Select/BeatmapCarousel.cs
+++ b/osu.Game/Screens/Select/BeatmapCarousel.cs
@@ -186,7 +186,7 @@ namespace osu.Game.Screens.Select
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
- var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
+ var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.Equals(beatmapSet));
if (existingSet == null)
return;
@@ -198,7 +198,7 @@ namespace osu.Game.Screens.Select
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
{
int? previouslySelectedID = null;
- CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
+ CarouselBeatmapSet existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.Equals(beatmapSet));
// If the selected beatmap is about to be removed, store its ID so it can be re-selected if required
if (existingSet?.State?.Value == CarouselItemState.Selected)
diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs
index 1f07042ede..ca56366927 100644
--- a/osu.Game/Screens/Spectate/SpectatorScreen.cs
+++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs
@@ -146,7 +146,7 @@ namespace osu.Game.Screens.Spectate
var user = userMap[userId];
var spectatorState = playingUserStates[userId];
- var resolvedRuleset = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == spectatorState.RulesetID)?.CreateInstance();
+ var resolvedRuleset = rulesets.AvailableRulesets.FirstOrDefault(r => r.OnlineID == spectatorState.RulesetID)?.CreateInstance();
if (resolvedRuleset == null)
return;
diff --git a/osu.Game/Stores/BeatmapImporter.cs b/osu.Game/Stores/BeatmapImporter.cs
index 32f0cd3d7a..8ab6941885 100644
--- a/osu.Game/Stores/BeatmapImporter.cs
+++ b/osu.Game/Stores/BeatmapImporter.cs
@@ -282,9 +282,6 @@ namespace osu.Game.Stores
{
var rulesetInstance = ((IRulesetInfo)beatmap.Ruleset).CreateInstance();
- if (rulesetInstance == null)
- return;
-
decoded.BeatmapInfo.Ruleset = rulesetInstance.RulesetInfo;
// TODO: this should be done in a better place once we actually need to dynamically update it.
diff --git a/osu.Game/Stores/RealmRulesetStore.cs b/osu.Game/Stores/RealmRulesetStore.cs
index cf9ffd112c..0119aec9a4 100644
--- a/osu.Game/Stores/RealmRulesetStore.cs
+++ b/osu.Game/Stores/RealmRulesetStore.cs
@@ -117,8 +117,8 @@ namespace osu.Game.Stores
// add all legacy rulesets first to ensure they have exclusive choice of primary key.
foreach (var r in instances.Where(r => r is ILegacyRuleset))
{
- if (realm.All().FirstOrDefault(rr => rr.OnlineID == r.RulesetInfo.ID) == null)
- realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.ID));
+ if (realm.All().FirstOrDefault(rr => rr.OnlineID == r.RulesetInfo.OnlineID) == null)
+ realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.OnlineID));
}
// add any other rulesets which have assemblies present but are not yet in the database.
@@ -136,7 +136,7 @@ namespace osu.Game.Stores
existingSameShortName.InstantiationInfo = r.RulesetInfo.InstantiationInfo;
}
else
- realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.ID));
+ realm.Add(new RealmRuleset(r.RulesetInfo.ShortName, r.RulesetInfo.Name, r.RulesetInfo.InstantiationInfo, r.RulesetInfo.OnlineID));
}
}
diff --git a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs
index 127c853a8e..9d92f5c5fc 100644
--- a/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs
+++ b/osu.Game/Tests/Beatmaps/HitObjectSampleTest.cs
@@ -15,7 +15,6 @@ using osu.Framework.Timing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Formats;
using osu.Game.IO;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Ranking;
@@ -39,10 +38,7 @@ namespace osu.Game.Tests.Beatmaps
private readonly BeatmapInfo beatmapInfo = new BeatmapInfo
{
BeatmapSet = new BeatmapSetInfo(),
- Metadata = new BeatmapMetadata
- {
- Author = APIUser.SYSTEM_USER
- }
+ Metadata = new BeatmapMetadata(),
};
private readonly TestResourceStore userSkinResourceStore = new TestResourceStore();
diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs
index 32a9b0b9d1..99944bcf6d 100644
--- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs
+++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs
@@ -2,7 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
@@ -33,12 +33,15 @@ namespace osu.Game.Tests.Beatmaps
BeatmapInfo.Ruleset = ruleset;
BeatmapInfo.RulesetID = ruleset.ID ?? 0;
- BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata;
- BeatmapInfo.BeatmapSet.Beatmaps = new List { BeatmapInfo };
- BeatmapInfo.BeatmapSet.OnlineID = Interlocked.Increment(ref onlineSetID);
BeatmapInfo.Length = 75000;
BeatmapInfo.OnlineInfo = new APIBeatmap();
BeatmapInfo.OnlineID = Interlocked.Increment(ref onlineBeatmapID);
+
+ Debug.Assert(BeatmapInfo.BeatmapSet != null);
+
+ BeatmapInfo.BeatmapSet.Metadata = BeatmapInfo.Metadata;
+ BeatmapInfo.BeatmapSet.Beatmaps.Add(BeatmapInfo);
+ BeatmapInfo.BeatmapSet.OnlineID = Interlocked.Increment(ref onlineSetID);
}
protected virtual Beatmap CreateBeatmap() => createTestBeatmap();
diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs
index eedf266bbe..d774514dda 100644
--- a/osu.Game/Tests/Visual/OsuTestScene.cs
+++ b/osu.Game/Tests/Visual/OsuTestScene.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -220,6 +221,8 @@ namespace osu.Game.Tests.Visual
{
var beatmap = CreateBeatmap(ruleset ?? Ruleset.Value).BeatmapInfo;
+ Debug.Assert(beatmap.BeatmapSet != null);
+
return new APIBeatmapSet
{
OnlineID = ((IBeatmapSetInfo)beatmap.BeatmapSet).OnlineID,
@@ -230,13 +233,17 @@ namespace osu.Game.Tests.Visual
Card = "https://assets.ppy.sh/beatmaps/163112/covers/card.jpg",
List = "https://assets.ppy.sh/beatmaps/163112/covers/list.jpg"
},
- Title = beatmap.BeatmapSet.Metadata.Title,
- TitleUnicode = beatmap.BeatmapSet.Metadata.TitleUnicode,
- Artist = beatmap.BeatmapSet.Metadata.Artist,
- ArtistUnicode = beatmap.BeatmapSet.Metadata.ArtistUnicode,
- Author = beatmap.BeatmapSet.Metadata.Author,
- Source = beatmap.BeatmapSet.Metadata.Source,
- Tags = beatmap.BeatmapSet.Metadata.Tags,
+ Title = beatmap.Metadata.Title,
+ TitleUnicode = beatmap.Metadata.TitleUnicode,
+ Artist = beatmap.Metadata.Artist,
+ ArtistUnicode = beatmap.Metadata.ArtistUnicode,
+ Author = new APIUser
+ {
+ Username = beatmap.Metadata.Author.Username,
+ Id = beatmap.Metadata.Author.OnlineID
+ },
+ Source = beatmap.Metadata.Source,
+ Tags = beatmap.Metadata.Tags,
Beatmaps = new[]
{
new APIBeatmap
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 2f26e45ba8..f9c8d9743d 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -36,7 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 4554469c19..47f8fbb43a 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -60,7 +60,7 @@
-
+
@@ -83,7 +83,7 @@
-
+
diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings
index 3fac94b243..a96f64cdc3 100644
--- a/osu.sln.DotSettings
+++ b/osu.sln.DotSettings
@@ -311,6 +311,7 @@
AABB
API
BPM
+ EF
FPS
GC
GL