diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 6444127594..985fc09df3 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -27,10 +27,10 @@
]
},
"ppy.localisationanalyser.tools": {
- "version": "2021.725.0",
+ "version": "2021.1210.0",
"commands": [
"localisation"
]
}
}
-}
\ No newline at end of file
+}
diff --git a/osu.Android.props b/osu.Android.props
index 0c922c09ac..5cf59decec 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs
index 645ea66654..b234207848 100644
--- a/osu.Desktop/OsuGameDesktop.cs
+++ b/osu.Desktop/OsuGameDesktop.cs
@@ -70,7 +70,9 @@ namespace osu.Desktop
if (!string.IsNullOrEmpty(stableInstallPath) && checkExists(stableInstallPath))
return stableInstallPath;
}
- catch { }
+ catch
+ {
+ }
}
stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
@@ -113,7 +115,7 @@ namespace osu.Desktop
base.LoadComplete();
if (!noVersionOverlay)
- LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, Add);
+ LoadComponentAsync(versionManager = new VersionManager { Depth = int.MinValue }, ScreenContainer.Add);
LoadComponentAsync(new DiscordRichPresence(), Add);
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index d00d89a577..06d1ef7346 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -55,73 +55,75 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
bool firstDeltaSwitch = false;
- for (int i = Previous.Count - 2; i > 0; i--)
+ int rhythmStart = 0;
+
+ while (rhythmStart < Previous.Count - 2 && current.StartTime - Previous[rhythmStart].StartTime < history_time_max)
+ rhythmStart++;
+
+ for (int i = rhythmStart; i > 0; i--)
{
OsuDifficultyHitObject currObj = (OsuDifficultyHitObject)Previous[i - 1];
OsuDifficultyHitObject prevObj = (OsuDifficultyHitObject)Previous[i];
OsuDifficultyHitObject lastObj = (OsuDifficultyHitObject)Previous[i + 1];
- double currHistoricalDecay = Math.Max(0, (history_time_max - (current.StartTime - currObj.StartTime))) / history_time_max; // scales note 0 to 1 from history to now
+ double currHistoricalDecay = (history_time_max - (current.StartTime - currObj.StartTime)) / history_time_max; // scales note 0 to 1 from history to now
- if (currHistoricalDecay != 0)
+ currHistoricalDecay = Math.Min((double)(Previous.Count - i) / Previous.Count, currHistoricalDecay); // either we're limited by time or limited by object count.
+
+ double currDelta = currObj.StrainTime;
+ double prevDelta = prevObj.StrainTime;
+ double lastDelta = lastObj.StrainTime;
+ double currRatio = 1.0 + 6.0 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses.
+
+ double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - greatWindow * 0.6) / (greatWindow * 0.6));
+
+ windowPenalty = Math.Min(1, windowPenalty);
+
+ double effectiveRatio = windowPenalty * currRatio;
+
+ if (firstDeltaSwitch)
{
- currHistoricalDecay = Math.Min((double)(Previous.Count - i) / Previous.Count, currHistoricalDecay); // either we're limited by time or limited by object count.
-
- double currDelta = currObj.StrainTime;
- double prevDelta = prevObj.StrainTime;
- double lastDelta = lastObj.StrainTime;
- double currRatio = 1.0 + 6.0 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses.
-
- double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - greatWindow * 0.6) / (greatWindow * 0.6));
-
- windowPenalty = Math.Min(1, windowPenalty);
-
- double effectiveRatio = windowPenalty * currRatio;
-
- if (firstDeltaSwitch)
+ if (!(prevDelta > 1.25 * currDelta || prevDelta * 1.25 < currDelta))
{
- if (!(prevDelta > 1.25 * currDelta || prevDelta * 1.25 < currDelta))
- {
- if (islandSize < 7)
- islandSize++; // island is still progressing, count size.
- }
- else
- {
- if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window
- effectiveRatio *= 0.125;
-
- if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle
- effectiveRatio *= 0.25;
-
- if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet)
- effectiveRatio *= 0.25;
-
- if (previousIslandSize % 2 == islandSize % 2) // repeated island polartiy (2 -> 4, 3 -> 5)
- effectiveRatio *= 0.50;
-
- if (lastDelta > prevDelta + 10 && prevDelta > currDelta + 10) // previous increase happened a note ago, 1/1->1/2-1/4, dont want to buff this.
- effectiveRatio *= 0.125;
-
- rhythmComplexitySum += Math.Sqrt(effectiveRatio * startRatio) * currHistoricalDecay * Math.Sqrt(4 + islandSize) / 2 * Math.Sqrt(4 + previousIslandSize) / 2;
-
- startRatio = effectiveRatio;
-
- previousIslandSize = islandSize; // log the last island size.
-
- if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting
- firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size.
-
- islandSize = 1;
- }
+ if (islandSize < 7)
+ islandSize++; // island is still progressing, count size.
}
- else if (prevDelta > 1.25 * currDelta) // we want to be speeding up.
+ else
{
- // Begin counting island until we change speed again.
- firstDeltaSwitch = true;
+ if (Previous[i - 1].BaseObject is Slider) // bpm change is into slider, this is easy acc window
+ effectiveRatio *= 0.125;
+
+ if (Previous[i].BaseObject is Slider) // bpm change was from a slider, this is easier typically than circle -> circle
+ effectiveRatio *= 0.25;
+
+ if (previousIslandSize == islandSize) // repeated island size (ex: triplet -> triplet)
+ effectiveRatio *= 0.25;
+
+ if (previousIslandSize % 2 == islandSize % 2) // repeated island polartiy (2 -> 4, 3 -> 5)
+ effectiveRatio *= 0.50;
+
+ if (lastDelta > prevDelta + 10 && prevDelta > currDelta + 10) // previous increase happened a note ago, 1/1->1/2-1/4, dont want to buff this.
+ effectiveRatio *= 0.125;
+
+ rhythmComplexitySum += Math.Sqrt(effectiveRatio * startRatio) * currHistoricalDecay * Math.Sqrt(4 + islandSize) / 2 * Math.Sqrt(4 + previousIslandSize) / 2;
+
startRatio = effectiveRatio;
+
+ previousIslandSize = islandSize; // log the last island size.
+
+ if (prevDelta * 1.25 < currDelta) // we're slowing down, stop counting
+ firstDeltaSwitch = false; // if we're speeding up, this stays true and we keep counting island size.
+
islandSize = 1;
}
}
+ else if (prevDelta > 1.25 * currDelta) // we want to be speeding up.
+ {
+ // Begin counting island until we change speed again.
+ firstDeltaSwitch = true;
+ startRatio = effectiveRatio;
+ islandSize = 1;
+ }
}
return Math.Sqrt(4 + rhythmComplexitySum * rhythm_multiplier) / 2; //produces multiplier that can be applied to strain. range [1, infinity) (not really though)
diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs
index a73ae9dcdb..81d89359e0 100644
--- a/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/LegacyScoreDecoderTest.cs
@@ -62,7 +62,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
public void TestCultureInvariance()
{
var ruleset = new OsuRuleset().RulesetInfo;
- var scoreInfo = new TestScoreInfo(ruleset);
+ var scoreInfo = TestResources.CreateTestScoreInfo(ruleset);
var beatmap = new TestBeatmap(ruleset);
var score = new Score
{
diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
index 6e2b9d20a8..6d0d5702e9 100644
--- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
+++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
@@ -1022,7 +1022,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{
return ImportScoreTest.LoadScoreIntoOsu(osu, new ScoreInfo
{
- OnlineScoreID = 2,
+ OnlineID = 2,
BeatmapInfo = beatmapInfo,
BeatmapInfoID = beatmapInfo.ID
}, new ImportScoreTest.TestArchiveReader());
diff --git a/osu.Game.Tests/Database/BeatmapImporterTests.cs b/osu.Game.Tests/Database/BeatmapImporterTests.cs
index a6edd6cb5f..e47e24021f 100644
--- a/osu.Game.Tests/Database/BeatmapImporterTests.cs
+++ b/osu.Game.Tests/Database/BeatmapImporterTests.cs
@@ -809,7 +809,7 @@ namespace osu.Game.Tests.Database
// TODO: reimplement when we have score support in realm.
// return ImportScoreTest.LoadScoreIntoOsu(osu, new ScoreInfo
// {
- // OnlineScoreID = 2,
+ // OnlineID = 2,
// Beatmap = beatmap,
// BeatmapInfoID = beatmap.ID
// }, new ImportScoreTest.TestArchiveReader());
diff --git a/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs b/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs
index 860828ae81..f05d9ab3dc 100644
--- a/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs
+++ b/osu.Game.Tests/Database/TestRealmKeyBindingStore.cs
@@ -52,6 +52,45 @@ namespace osu.Game.Tests.Database
Assert.That(queryCount(GlobalAction.Select), Is.EqualTo(2));
}
+ [Test]
+ public void TestDefaultsPopulationRemovesExcess()
+ {
+ Assert.That(queryCount(), Is.EqualTo(0));
+
+ KeyBindingContainer testContainer = new TestKeyBindingContainer();
+
+ // Add some excess bindings for an action which only supports 1.
+ using (var realm = realmContextFactory.CreateContext())
+ using (var transaction = realm.BeginWrite())
+ {
+ realm.Add(new RealmKeyBinding
+ {
+ Action = GlobalAction.Back,
+ KeyCombination = new KeyCombination(InputKey.A)
+ });
+
+ realm.Add(new RealmKeyBinding
+ {
+ Action = GlobalAction.Back,
+ KeyCombination = new KeyCombination(InputKey.S)
+ });
+
+ realm.Add(new RealmKeyBinding
+ {
+ Action = GlobalAction.Back,
+ KeyCombination = new KeyCombination(InputKey.D)
+ });
+
+ transaction.Commit();
+ }
+
+ Assert.That(queryCount(GlobalAction.Back), Is.EqualTo(3));
+
+ keyBindingStore.Register(testContainer, Enumerable.Empty());
+
+ Assert.That(queryCount(GlobalAction.Back), Is.EqualTo(1));
+ }
+
private int queryCount(GlobalAction? match = null)
{
using (var realm = realmContextFactory.CreateContext())
diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs
index 42305ccd81..bc0041e2c2 100644
--- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs
+++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs
@@ -45,8 +45,6 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
AddRepeatStep("add some users", () => Client.AddUser(new APIUser { Id = id++ }), 5);
checkPlayingUserCount(0);
- AddAssert("playlist item is available", () => Client.CurrentMatchPlayingItem.Value != null);
-
changeState(3, MultiplayerUserState.WaitingForLoad);
checkPlayingUserCount(3);
@@ -64,8 +62,6 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
AddStep("leave room", () => Client.LeaveRoom());
checkPlayingUserCount(0);
-
- AddAssert("playlist item is null", () => Client.CurrentMatchPlayingItem.Value == null);
}
[Test]
diff --git a/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs
new file mode 100644
index 0000000000..2ec5b778d1
--- /dev/null
+++ b/osu.Game.Tests/Online/Chat/MessageNotifierTest.cs
@@ -0,0 +1,90 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Game.Online.Chat;
+
+namespace osu.Game.Tests.Online.Chat
+{
+ [TestFixture]
+ public class MessageNotifierTest
+ {
+ [Test]
+ public void TestContainsUsernameMidlinePositive()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("This is a test message", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameStartOfLinePositive()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("Test message", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameEndOfLinePositive()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("This is a test", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameMidlineNegative()
+ {
+ Assert.IsFalse(MessageNotifier.CheckContainsUsername("This is a testmessage for notifications", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameStartOfLineNegative()
+ {
+ Assert.IsFalse(MessageNotifier.CheckContainsUsername("Testmessage", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameEndOfLineNegative()
+ {
+ Assert.IsFalse(MessageNotifier.CheckContainsUsername("This is a notificationtest", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameBetweenInterpunction()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("Hello 'test'-message", "Test"));
+ }
+
+ [Test]
+ public void TestContainsUsernameUnicode()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("Test \u0460\u0460 message", "\u0460\u0460"));
+ }
+
+ [Test]
+ public void TestContainsUsernameUnicodeNegative()
+ {
+ Assert.IsFalse(MessageNotifier.CheckContainsUsername("Test ha\u0460\u0460o message", "\u0460\u0460"));
+ }
+
+ [Test]
+ public void TestContainsUsernameSpecialCharactersPositive()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("Test [#^-^#] message", "[#^-^#]"));
+ }
+
+ [Test]
+ public void TestContainsUsernameSpecialCharactersNegative()
+ {
+ Assert.IsFalse(MessageNotifier.CheckContainsUsername("Test pad[#^-^#]oru message", "[#^-^#]"));
+ }
+
+ [Test]
+ public void TestContainsUsernameAtSign()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("@username hi", "username"));
+ }
+
+ [Test]
+ public void TestContainsUsernameColon()
+ {
+ Assert.IsTrue(MessageNotifier.CheckContainsUsername("username: hi", "username"));
+ }
+ }
+}
diff --git a/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs b/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs
index 8378b33b3d..4b160e1d67 100644
--- a/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs
+++ b/osu.Game.Tests/Online/TestAPIModJsonSerialization.cs
@@ -13,7 +13,6 @@ using osu.Game.Online.Solo;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods;
-using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
@@ -94,7 +93,7 @@ namespace osu.Game.Tests.Online
[Test]
public void TestDeserialiseSubmittableScoreWithEmptyMods()
{
- var score = new SubmittableScore(new ScoreInfo { Ruleset = new OsuRuleset().RulesetInfo });
+ var score = new SubmittableScore(new ScoreInfo());
var deserialised = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(score));
@@ -106,7 +105,6 @@ namespace osu.Game.Tests.Online
{
var score = new SubmittableScore(new ScoreInfo
{
- Ruleset = new OsuRuleset().RulesetInfo,
Mods = new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 2 } } }
});
diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
index 24824b1e23..239c787349 100644
--- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
+++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
@@ -114,18 +114,23 @@ namespace osu.Game.Tests.Online
public void TestTrackerRespectsChecksum()
{
AddStep("allow importing", () => beatmaps.AllowImport.SetResult(true));
+ AddStep("import beatmap", () => beatmaps.Import(testBeatmapFile).Wait());
+ addAvailabilityCheckStep("initially locally available", BeatmapAvailability.LocallyAvailable);
AddStep("import altered beatmap", () =>
{
beatmaps.Import(TestResources.GetTestBeatmapForImport(true)).Wait();
});
- addAvailabilityCheckStep("state still not downloaded", BeatmapAvailability.NotDownloaded);
+ addAvailabilityCheckStep("state not downloaded", BeatmapAvailability.NotDownloaded);
AddStep("recreate tracker", () => Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
{
SelectedItem = { BindTarget = selectedItem }
});
addAvailabilityCheckStep("state not downloaded as well", BeatmapAvailability.NotDownloaded);
+
+ AddStep("reimport original beatmap", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait());
+ addAvailabilityCheckStep("locally available after re-import", BeatmapAvailability.LocallyAvailable);
}
private void addAvailabilityCheckStep(string description, Func expected)
diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs
index 440d5e701f..445394fc77 100644
--- a/osu.Game.Tests/Resources/TestResources.cs
+++ b/osu.Game.Tests/Resources/TestResources.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
using NUnit.Framework;
@@ -12,8 +13,12 @@ using osu.Framework.IO.Stores;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
+using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
+using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
+using osu.Game.Rulesets.Scoring;
+using osu.Game.Scoring;
namespace osu.Game.Tests.Resources
{
@@ -137,5 +142,63 @@ namespace osu.Game.Tests.Resources
}
}
}
+
+ ///
+ /// Create a test score model.
+ ///
+ /// The ruleset for which the score was set against.
+ ///
+ public static ScoreInfo CreateTestScoreInfo(RulesetInfo ruleset = null) =>
+ CreateTestScoreInfo(CreateTestBeatmapSetInfo(1, new[] { ruleset ?? new OsuRuleset().RulesetInfo }).Beatmaps.First());
+
+ ///
+ /// Create a test score model.
+ ///
+ /// The beatmap for which the score was set against.
+ ///
+ public static ScoreInfo CreateTestScoreInfo(BeatmapInfo beatmap) => new ScoreInfo
+ {
+ User = new APIUser
+ {
+ Id = 2,
+ Username = "peppy",
+ CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
+ },
+ BeatmapInfo = beatmap,
+ Ruleset = beatmap.Ruleset,
+ RulesetID = beatmap.Ruleset.ID ?? 0,
+ Mods = new Mod[] { new TestModHardRock(), new TestModDoubleTime() },
+ TotalScore = 2845370,
+ Accuracy = 0.95,
+ MaxCombo = 999,
+ Position = 1,
+ Rank = ScoreRank.S,
+ Date = DateTimeOffset.Now,
+ Statistics = new Dictionary
+ {
+ [HitResult.Miss] = 1,
+ [HitResult.Meh] = 50,
+ [HitResult.Ok] = 100,
+ [HitResult.Good] = 200,
+ [HitResult.Great] = 300,
+ [HitResult.Perfect] = 320,
+ [HitResult.SmallTickHit] = 50,
+ [HitResult.SmallTickMiss] = 25,
+ [HitResult.LargeTickHit] = 100,
+ [HitResult.LargeTickMiss] = 50,
+ [HitResult.SmallBonus] = 10,
+ [HitResult.SmallBonus] = 50
+ },
+ };
+
+ private class TestModHardRock : ModHardRock
+ {
+ public override double ScoreMultiplier => 1;
+ }
+
+ private class TestModDoubleTime : ModDoubleTime
+ {
+ public override double ScoreMultiplier => 1;
+ }
}
}
diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs
index 0dee0f89ea..bbc92b7817 100644
--- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs
+++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs
@@ -40,7 +40,7 @@ namespace osu.Game.Tests.Scores.IO
Combo = 250,
User = new APIUser { Username = "Test user" },
Date = DateTimeOffset.Now,
- OnlineScoreID = 12345,
+ OnlineID = 12345,
};
var imported = await LoadScoreIntoOsu(osu, toImport);
@@ -52,7 +52,7 @@ namespace osu.Game.Tests.Scores.IO
Assert.AreEqual(toImport.Combo, imported.Combo);
Assert.AreEqual(toImport.User.Username, imported.User.Username);
Assert.AreEqual(toImport.Date, imported.Date);
- Assert.AreEqual(toImport.OnlineScoreID, imported.OnlineScoreID);
+ Assert.AreEqual(toImport.OnlineID, imported.OnlineID);
}
finally
{
@@ -163,12 +163,12 @@ namespace osu.Game.Tests.Scores.IO
{
var osu = LoadOsuIntoHost(host, true);
- await LoadScoreIntoOsu(osu, new ScoreInfo { OnlineScoreID = 2 }, new TestArchiveReader());
+ await LoadScoreIntoOsu(osu, new ScoreInfo { OnlineID = 2 }, new TestArchiveReader());
var scoreManager = osu.Dependencies.Get();
// Note: A new score reference is used here since the import process mutates the original object to set an ID
- Assert.That(scoreManager.IsAvailableLocally(new ScoreInfo { OnlineScoreID = 2 }));
+ Assert.That(scoreManager.IsAvailableLocally(new ScoreInfo { OnlineID = 2 }));
}
finally
{
diff --git a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs
index d1374eb6e5..42fcb3acab 100644
--- a/osu.Game.Tests/Scores/IO/TestScoreEquality.cs
+++ b/osu.Game.Tests/Scores/IO/TestScoreEquality.cs
@@ -44,24 +44,6 @@ namespace osu.Game.Tests.Scores.IO
Assert.That(score1, Is.EqualTo(score2));
}
- [Test]
- public void TestNonMatchingByHash()
- {
- ScoreInfo score1 = new ScoreInfo { Hash = "a" };
- ScoreInfo score2 = new ScoreInfo { Hash = "b" };
-
- Assert.That(score1, Is.Not.EqualTo(score2));
- }
-
- [Test]
- public void TestMatchingByHash()
- {
- ScoreInfo score1 = new ScoreInfo { Hash = "a" };
- ScoreInfo score2 = new ScoreInfo { Hash = "a" };
-
- Assert.That(score1, Is.EqualTo(score2));
- }
-
[Test]
public void TestNonMatchingByNull()
{
diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
index bdd1b92c8d..1d3dd35e1d 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
@@ -5,8 +5,11 @@ using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
+using osu.Framework.Audio;
+using osu.Framework.Graphics.Textures;
using osu.Framework.Screens;
using osu.Framework.Testing;
+using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Graphics.Backgrounds;
@@ -15,6 +18,7 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Screens;
using osu.Game.Screens.Backgrounds;
using osu.Game.Skinning;
+using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual.Background
{
@@ -22,8 +26,7 @@ namespace osu.Game.Tests.Visual.Background
public class TestSceneBackgroundScreenDefault : OsuTestScene
{
private BackgroundScreenStack stack;
- private BackgroundScreenDefault screen;
-
+ private TestBackgroundScreenDefault screen;
private Graphics.Backgrounds.Background getCurrentBackground() => screen.ChildrenOfType().FirstOrDefault();
[Resolved]
@@ -36,10 +39,95 @@ namespace osu.Game.Tests.Visual.Background
public void SetUpSteps()
{
AddStep("create background stack", () => Child = stack = new BackgroundScreenStack());
- AddStep("push default screen", () => stack.Push(screen = new BackgroundScreenDefault(false)));
+ AddStep("push default screen", () => stack.Push(screen = new TestBackgroundScreenDefault()));
AddUntilStep("wait for screen to load", () => screen.IsCurrentScreen());
}
+ [Test]
+ public void TestBeatmapBackgroundTracksBeatmap()
+ {
+ setSupporter(true);
+ setSourceMode(BackgroundSource.Beatmap);
+
+ AddStep("change beatmap", () => Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+ AddAssert("background changed", () => screen.CheckLastLoadChange() == true);
+
+ Graphics.Backgrounds.Background last = null;
+
+ AddUntilStep("wait for beatmap background to be loaded", () => getCurrentBackground()?.GetType() == typeof(BeatmapBackground));
+ AddStep("store background", () => last = getCurrentBackground());
+
+ AddStep("change beatmap", () => Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+
+ AddUntilStep("wait for beatmap background to change", () => screen.CheckLastLoadChange() == true);
+
+ AddUntilStep("background is new beatmap background", () => last != getCurrentBackground());
+ AddStep("store background", () => last = getCurrentBackground());
+
+ AddStep("change beatmap", () => Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+
+ AddUntilStep("wait for beatmap background to change", () => screen.CheckLastLoadChange() == true);
+ AddUntilStep("background is new beatmap background", () => last != getCurrentBackground());
+ }
+
+ [Test]
+ public void TestBeatmapBackgroundTracksBeatmapWhenSuspended()
+ {
+ setSupporter(true);
+ setSourceMode(BackgroundSource.Beatmap);
+
+ AddStep("change beatmap", () => Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+ AddAssert("background changed", () => screen.CheckLastLoadChange() == true);
+ AddUntilStep("wait for beatmap background to be loaded", () => getCurrentBackground()?.GetType() == typeof(BeatmapBackground));
+
+ BackgroundScreenBeatmap nestedScreen = null;
+
+ // of note, this needs to be a type that doesn't match BackgroundScreenDefault else it is silently not pushed by the background stack.
+ AddStep("push new background to stack", () => stack.Push(nestedScreen = new BackgroundScreenBeatmap(Beatmap.Value)));
+ AddUntilStep("wait for screen to load", () => nestedScreen.IsLoaded && nestedScreen.IsCurrentScreen());
+
+ AddAssert("top level background hasn't changed yet", () => screen.CheckLastLoadChange() == null);
+
+ AddStep("change beatmap", () => Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+
+ AddAssert("top level background hasn't changed yet", () => screen.CheckLastLoadChange() == null);
+
+ AddStep("pop screen back to top level", () => screen.MakeCurrent());
+
+ AddAssert("top level background changed", () => screen.CheckLastLoadChange() == true);
+ }
+
+ [Test]
+ public void TestBeatmapBackgroundIgnoresNoChangeWhenSuspended()
+ {
+ BackgroundScreenBeatmap nestedScreen = null;
+ WorkingBeatmap originalWorking = null;
+
+ setSupporter(true);
+ setSourceMode(BackgroundSource.Beatmap);
+
+ AddStep("change beatmap", () => originalWorking = Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+ AddAssert("background changed", () => screen.CheckLastLoadChange() == true);
+ AddUntilStep("wait for beatmap background to be loaded", () => getCurrentBackground()?.GetType() == typeof(BeatmapBackground));
+
+ // of note, this needs to be a type that doesn't match BackgroundScreenDefault else it is silently not pushed by the background stack.
+ AddStep("push new background to stack", () => stack.Push(nestedScreen = new BackgroundScreenBeatmap(Beatmap.Value)));
+ AddUntilStep("wait for screen to load", () => nestedScreen.IsLoaded && nestedScreen.IsCurrentScreen());
+
+ // we're testing a case where scheduling may be used to avoid issues, so ensure the scheduler is no longer running.
+ AddUntilStep("wait for top level not alive", () => !screen.IsAlive);
+
+ AddStep("change beatmap", () => Beatmap.Value = createTestWorkingBeatmapWithUniqueBackground());
+ AddStep("change beatmap back", () => Beatmap.Value = originalWorking);
+
+ AddAssert("top level background hasn't changed yet", () => screen.CheckLastLoadChange() == null);
+
+ AddStep("pop screen back to top level", () => screen.MakeCurrent());
+
+ AddStep("top level screen is current", () => screen.IsCurrentScreen());
+ AddAssert("top level background reused existing", () => screen.CheckLastLoadChange() == false);
+ }
+
[Test]
public void TestBackgroundTypeSwitch()
{
@@ -78,36 +166,24 @@ namespace osu.Game.Tests.Visual.Background
[TestCase(BackgroundSource.Skin, typeof(SkinBackground))]
public void TestBackgroundDoesntReloadOnNoChange(BackgroundSource source, Type backgroundType)
{
- Graphics.Backgrounds.Background last = null;
-
setSourceMode(source);
setSupporter(true);
if (source == BackgroundSource.Skin)
setCustomSkin();
- AddUntilStep("wait for beatmap background to be loaded", () => (last = getCurrentBackground())?.GetType() == backgroundType);
+ AddUntilStep("wait for beatmap background to be loaded", () => (getCurrentBackground())?.GetType() == backgroundType);
AddAssert("next doesn't load new background", () => screen.Next() == false);
-
- // doesn't really need to be checked but might as well.
- AddWaitStep("wait a bit", 5);
- AddUntilStep("ensure same background instance", () => last == getCurrentBackground());
}
[Test]
public void TestBackgroundCyclingOnDefaultSkin([Values] bool supporter)
{
- Graphics.Backgrounds.Background last = null;
-
setSourceMode(BackgroundSource.Skin);
setSupporter(supporter);
setDefaultSkin();
- AddUntilStep("wait for beatmap background to be loaded", () => (last = getCurrentBackground())?.GetType() == typeof(Graphics.Backgrounds.Background));
+ AddUntilStep("wait for beatmap background to be loaded", () => (getCurrentBackground())?.GetType() == typeof(Graphics.Backgrounds.Background));
AddAssert("next cycles background", () => screen.Next());
-
- // doesn't really need to be checked but might as well.
- AddWaitStep("wait a bit", 5);
- AddUntilStep("ensure different background instance", () => last != getCurrentBackground());
}
private void setSourceMode(BackgroundSource source) =>
@@ -120,6 +196,42 @@ namespace osu.Game.Tests.Visual.Background
Id = API.LocalUser.Value.Id + 1,
});
+ private WorkingBeatmap createTestWorkingBeatmapWithUniqueBackground() => new UniqueBackgroundTestWorkingBeatmap(Audio);
+
+ private class TestBackgroundScreenDefault : BackgroundScreenDefault
+ {
+ private bool? lastLoadTriggerCausedChange;
+
+ public TestBackgroundScreenDefault()
+ : base(false)
+ {
+ }
+
+ public override bool Next()
+ {
+ bool didChange = base.Next();
+ lastLoadTriggerCausedChange = didChange;
+ return didChange;
+ }
+
+ public bool? CheckLastLoadChange()
+ {
+ bool? lastChange = lastLoadTriggerCausedChange;
+ lastLoadTriggerCausedChange = null;
+ return lastChange;
+ }
+ }
+
+ private class UniqueBackgroundTestWorkingBeatmap : TestWorkingBeatmap
+ {
+ public UniqueBackgroundTestWorkingBeatmap(AudioManager audioManager)
+ : base(new Beatmap(), null, audioManager)
+ {
+ }
+
+ protected override Texture GetBackground() => new Texture(1, 1);
+ }
+
private void setCustomSkin()
{
// feign a skin switch. this doesn't do anything except force CurrentSkin to become a LegacySkin.
diff --git a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs
index 194341d1ab..33b1d9a67d 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimBackgrounds.cs
@@ -18,7 +18,6 @@ using osu.Game.Configuration;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Scoring;
@@ -28,7 +27,6 @@ using osu.Game.Screens.Play;
using osu.Game.Screens.Play.PlayerSettings;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Select;
-using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Resources;
using osuTK;
using osuTK.Graphics;
@@ -229,12 +227,7 @@ namespace osu.Game.Tests.Visual.Background
FadeAccessibleResults results = null;
- AddStep("Transition to Results", () => player.Push(results = new FadeAccessibleResults(new ScoreInfo
- {
- User = new APIUser { Username = "osu!" },
- BeatmapInfo = new TestBeatmap(Ruleset.Value).BeatmapInfo,
- Ruleset = Ruleset.Value,
- })));
+ AddStep("Transition to Results", () => player.Push(results = new FadeAccessibleResults(TestResources.CreateTestScoreInfo())));
AddUntilStep("Wait for results is current", () => results.IsCurrentScreen());
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs
index 160af47a6d..50794f15ed 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorTestGameplay.cs
@@ -9,6 +9,7 @@ using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
+using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Backgrounds;
using osu.Game.Screens.Edit;
@@ -44,6 +45,7 @@ namespace osu.Game.Tests.Visual.Editing
protected override void LoadEditor()
{
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedBeatmapSet.Beatmaps.First(b => b.RulesetID == 0));
+ SelectedMods.Value = new[] { new ModCinema() };
base.LoadEditor();
}
@@ -67,6 +69,7 @@ namespace osu.Game.Tests.Visual.Editing
var background = this.ChildrenOfType().Single();
return background.Colour == Color4.DarkGray && background.BlurAmount.Value == 0;
});
+ AddAssert("no mods selected", () => SelectedMods.Value.Count == 0);
}
[Test]
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs
index 745932315c..fa27e1abdd 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs
@@ -26,6 +26,7 @@ namespace osu.Game.Tests.Visual.Gameplay
AddAssert("total number of results == 1", () =>
{
var score = new ScoreInfo();
+
((FailPlayer)Player).ScoreProcessor.PopulateScore(score);
return score.Statistics.Values.Sum() == 1;
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs
index f5f17a0bc1..e03c8d7561 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneLeadIn.cs
@@ -85,11 +85,12 @@ namespace osu.Game.Tests.Visual.Gameplay
loopGroup.Scale.Add(Easing.None, -20000, -18000, 0, 1);
var target = addEventToLoop ? loopGroup : sprite.TimelineGroup;
- target.Alpha.Add(Easing.None, firstStoryboardEvent, firstStoryboardEvent + 500, 0, 1);
+ double targetTime = addEventToLoop ? 20000 : 0;
+ target.Alpha.Add(Easing.None, targetTime + firstStoryboardEvent, targetTime + firstStoryboardEvent + 500, 0, 1);
// these should be ignored due to being in the future.
sprite.TimelineGroup.Alpha.Add(Easing.None, 18000, 20000, 0, 1);
- loopGroup.Alpha.Add(Easing.None, 18000, 20000, 0, 1);
+ loopGroup.Alpha.Add(Easing.None, 38000, 40000, 0, 1);
storyboard.GetLayer("Background").Add(sprite);
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs
index f47fae33ca..42c4f89e9d 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs
@@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private ScoreInfo getScoreInfo(bool replayAvailable)
{
- return new APIScoreInfo
+ return new APIScore
{
OnlineID = 2553163309,
RulesetID = 0,
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs
index 8373979308..a5744f9986 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs
@@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestFirstItemSelectedByDefault()
{
- AddAssert("first item selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[0].ID);
+ AddAssert("first item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
}
[Test]
@@ -27,13 +27,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
addItem(() => OtherBeatmap);
AddAssert("playlist has 2 items", () => Client.APIRoom?.Playlist.Count == 2);
- AddAssert("last playlist item is different", () => Client.APIRoom?.Playlist[1].Beatmap.Value.OnlineID == OtherBeatmap.OnlineID);
addItem(() => InitialBeatmap);
AddAssert("playlist has 3 items", () => Client.APIRoom?.Playlist.Count == 3);
- AddAssert("last playlist item is different", () => Client.APIRoom?.Playlist[2].Beatmap.Value.OnlineID == InitialBeatmap.OnlineID);
- AddAssert("first item still selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[0].ID);
+ AddAssert("first item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
}
[Test]
@@ -43,7 +41,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("playlist has only one item", () => Client.APIRoom?.Playlist.Count == 1);
AddAssert("playlist item is expired", () => Client.APIRoom?.Playlist[0].Expired == true);
- AddAssert("last item selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[0].ID);
+ AddAssert("last item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
}
[Test]
@@ -55,12 +53,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
RunGameplay();
AddAssert("first item expired", () => Client.APIRoom?.Playlist[0].Expired == true);
- AddAssert("next item selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[1].ID);
+ AddAssert("next item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[1].ID);
RunGameplay();
AddAssert("second item expired", () => Client.APIRoom?.Playlist[1].Expired == true);
- AddAssert("next item selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[2].ID);
+ AddAssert("next item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[2].ID);
}
[Test]
@@ -74,15 +72,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("change queue mode", () => Client.ChangeSettings(queueMode: QueueMode.HostOnly));
AddAssert("playlist has 3 items", () => Client.APIRoom?.Playlist.Count == 3);
- AddAssert("playlist item is the other beatmap", () => Client.CurrentMatchPlayingItem.Value?.BeatmapID == OtherBeatmap.OnlineID);
- AddAssert("playlist item is not expired", () => Client.APIRoom?.Playlist[1].Expired == false);
+ AddAssert("item 2 is not expired", () => Client.APIRoom?.Playlist[1].Expired == false);
+ AddAssert("current item is the other beatmap", () => Client.Room?.Settings.PlaylistItemId == 2);
}
[Test]
public void TestCorrectItemSelectedAfterNewItemAdded()
{
addItem(() => OtherBeatmap);
- AddAssert("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
+ AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID);
}
private void addItem(Func beatmap)
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs
index ccac3de304..c7eeff81fe 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs
@@ -9,6 +9,7 @@ using osu.Game.Beatmaps;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Multiplayer;
+using osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Multiplayer
@@ -20,7 +21,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestFirstItemSelectedByDefault()
{
- AddAssert("first item selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[0].ID);
+ AddAssert("first item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
}
[Test]
@@ -28,7 +29,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
selectNewItem(() => InitialBeatmap);
- AddAssert("playlist item still selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[0].ID);
+ AddAssert("playlist item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
}
[Test]
@@ -36,7 +37,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
selectNewItem(() => OtherBeatmap);
- AddAssert("playlist item still selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[0].ID);
+ AddAssert("playlist item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID);
}
[Test]
@@ -47,7 +48,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("playlist contains two items", () => Client.APIRoom?.Playlist.Count == 2);
AddAssert("first playlist item expired", () => Client.APIRoom?.Playlist[0].Expired == true);
AddAssert("second playlist item not expired", () => Client.APIRoom?.Playlist[1].Expired == false);
- AddAssert("second playlist item selected", () => Client.CurrentMatchPlayingItem.Value?.ID == Client.APIRoom?.Playlist[1].ID);
+ AddAssert("second playlist item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[1].ID);
}
[Test]
@@ -85,6 +86,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void selectNewItem(Func beatmap)
{
+ AddUntilStep("wait for playlist panels to load", () =>
+ {
+ var queueList = this.ChildrenOfType().Single();
+ return queueList.ChildrenOfType().Count() == queueList.Items.Count;
+ });
+
AddStep("click edit button", () =>
{
InputManager.MoveMouseTo(this.ChildrenOfType().First());
@@ -97,7 +104,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("select other beatmap", () => ((Screens.Select.SongSelect)CurrentSubScreen).FinaliseSelection(otherBeatmap = beatmap()));
AddUntilStep("wait for return to match", () => CurrentSubScreen is MultiplayerMatchSubScreen);
- AddUntilStep("selected item is new beatmap", () => Client.CurrentMatchPlayingItem.Value?.Beatmap.Value?.OnlineID == otherBeatmap.OnlineID);
+ AddUntilStep("selected item is new beatmap", () => (CurrentSubScreen as MultiplayerMatchSubScreen)?.SelectedItem.Value?.BeatmapID == otherBeatmap.OnlineID);
}
private void addItem(Func beatmap)
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index 5eb0abc830..bc2902480d 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -391,9 +391,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
}
});
- AddStep("set user ready", () => client.ChangeState(MultiplayerUserState.Ready));
- AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
+ pressReadyButton();
+ AddStep("delete beatmap", () => beatmaps.Delete(importedSet));
AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
}
@@ -413,10 +413,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
}
});
+ pressReadyButton();
+
AddStep("Enter song select", () =>
{
var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerScreenStack.CurrentScreen).CurrentSubScreen;
- ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.CurrentMatchPlayingItem.Value);
+ ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId);
});
AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true);
@@ -592,19 +594,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
}
});
- AddUntilStep("wait for ready button to be enabled", () => readyButton.ChildrenOfType().Single().Enabled.Value);
-
- AddStep("click ready button", () =>
- {
- InputManager.MoveMouseTo(readyButton);
- InputManager.Click(MouseButton.Left);
- });
-
- AddUntilStep("wait for player to be ready", () => client.Room?.Users[0].State == MultiplayerUserState.Ready);
- AddUntilStep("wait for ready button to be enabled", () => readyButton.ChildrenOfType().Single().Enabled.Value);
-
- AddStep("click start button", () => InputManager.Click(MouseButton.Left));
-
+ pressReadyButton();
+ pressReadyButton();
AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player);
// Gameplay runs in real-time, so we need to incrementally check if gameplay has finished in order to not time out.
@@ -665,7 +656,24 @@ namespace osu.Game.Tests.Visual.Multiplayer
});
}
- private MultiplayerReadyButton readyButton => this.ChildrenOfType().Single();
+ private ReadyButton readyButton => this.ChildrenOfType().Single();
+
+ private void pressReadyButton()
+ {
+ AddUntilStep("wait for ready button to be enabled", () => readyButton.Enabled.Value);
+
+ MultiplayerUserState lastState = MultiplayerUserState.Idle;
+
+ AddStep("click ready button", () =>
+ {
+ lastState = client.LocalUser?.State ?? MultiplayerUserState.Idle;
+
+ InputManager.MoveMouseTo(readyButton);
+ InputManager.Click(MouseButton.Left);
+ });
+
+ AddUntilStep("wait for state change", () => client.LocalUser?.State != lastState);
+ }
private void createRoom(Func room)
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
index 5708b2f789..73f2ed5b39 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
@@ -6,6 +6,7 @@ using NUnit.Framework;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Online.Multiplayer;
+using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Multiplayer;
@@ -27,7 +28,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("initialise gameplay", () =>
{
- Stack.Push(player = new MultiplayerPlayer(Client.APIRoom, Client.CurrentMatchPlayingItem.Value, Client.Room?.Users.ToArray()));
+ Stack.Push(player = new MultiplayerPlayer(Client.APIRoom, new PlaylistItem
+ {
+ Beatmap = { Value = Beatmap.Value.BeatmapInfo },
+ Ruleset = { Value = Beatmap.Value.BeatmapInfo.Ruleset }
+ }, Client.Room?.Users.ToArray()));
});
AddUntilStep("wait for player to be current", () => player.IsCurrentScreen() && player.IsLoaded);
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs
index a2b2da0aec..61a92c32a4 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs
@@ -6,6 +6,7 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
+using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Platform;
@@ -27,11 +28,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiplayerQueueList : MultiplayerTestScene
{
- private MultiplayerQueueList playlist;
+ private readonly Bindable selectedItem = new Bindable();
[Cached(typeof(UserLookupCache))]
private readonly TestUserLookupCache userLookupCache = new TestUserLookupCache();
+ private MultiplayerQueueList playlist;
private BeatmapManager beatmaps;
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
@@ -50,12 +52,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create playlist", () =>
{
+ selectedItem.Value = null;
+
Child = playlist = new MultiplayerQueueList
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(500, 300),
- SelectedItem = { BindTarget = Client.CurrentMatchPlayingItem },
+ SelectedItem = { BindTarget = selectedItem },
Items = { BindTarget = Client.APIRoom!.Playlist }
};
});
@@ -107,22 +111,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
- assertDeleteButtonVisibility(0, false);
-
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
+
+ AddStep("select item 0", () => selectedItem.Value = playlist.ChildrenOfType>().ElementAt(0).Model);
assertDeleteButtonVisibility(0, false);
assertDeleteButtonVisibility(1, true);
- // Run through gameplay.
- AddStep("set state to ready", () => Client.ChangeUserState(API.LocalUser.Value.Id, MultiplayerUserState.Ready));
- AddUntilStep("local state is ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
- AddStep("start match", () => Client.StartMatch());
- AddUntilStep("match started", () => Client.LocalUser?.State == MultiplayerUserState.WaitingForLoad);
- AddStep("set state to loaded", () => Client.ChangeUserState(API.LocalUser.Value.Id, MultiplayerUserState.Loaded));
- AddUntilStep("local state is playing", () => Client.LocalUser?.State == MultiplayerUserState.Playing);
- AddStep("set state to finished play", () => Client.ChangeUserState(API.LocalUser.Value.Id, MultiplayerUserState.FinishedPlay));
- AddUntilStep("local state is results", () => Client.LocalUser?.State == MultiplayerUserState.Results);
-
+ AddStep("select item 1", () => selectedItem.Value = playlist.ChildrenOfType>().ElementAt(1).Model);
+ assertDeleteButtonVisibility(0, true);
assertDeleteButtonVisibility(1, false);
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
index 80f807e7d3..4674601f28 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
@@ -1,13 +1,11 @@
// 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 NUnit.Framework;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
-using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Multiplayer;
+using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.Multiplayer
{
@@ -22,20 +20,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
var rulesetInfo = new OsuRuleset().RulesetInfo;
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
-
- var score = new ScoreInfo
- {
- Rank = ScoreRank.B,
- TotalScore = 987654,
- Accuracy = 0.8,
- MaxCombo = 500,
- Combo = 250,
- BeatmapInfo = beatmapInfo,
- User = new APIUser { Username = "Test user" },
- Date = DateTimeOffset.Now,
- OnlineScoreID = 12345,
- Ruleset = rulesetInfo,
- };
+ var score = TestResources.CreateTestScoreInfo(beatmapInfo);
PlaylistItem playlistItem = new PlaylistItem
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
index da1fa226e1..f5df8d7507 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
@@ -1,15 +1,13 @@
// 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 System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Bindables;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
-using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Multiplayer;
+using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.Multiplayer
{
@@ -26,20 +24,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
var rulesetInfo = new OsuRuleset().RulesetInfo;
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
-
- var score = new ScoreInfo
- {
- Rank = ScoreRank.B,
- TotalScore = 987654,
- Accuracy = 0.8,
- MaxCombo = 500,
- Combo = 250,
- BeatmapInfo = beatmapInfo,
- User = new APIUser { Username = "Test user" },
- Date = DateTimeOffset.Now,
- OnlineScoreID = 12345,
- Ruleset = rulesetInfo,
- };
+ var score = TestResources.CreateTestScoreInfo(beatmapInfo);
PlaylistItem playlistItem = new PlaylistItem
{
diff --git a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs
index c9dec25ad3..1653247570 100644
--- a/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestScenePresentScore.cs
@@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.Navigation
imported = Game.ScoreManager.Import(new ScoreInfo
{
Hash = Guid.NewGuid().ToString(),
- OnlineScoreID = i,
+ OnlineID = i,
BeatmapInfo = beatmap.Beatmaps.First(),
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo
}).Result.Value;
diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs
index 50969aad9b..be2db9a8a0 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs
@@ -47,9 +47,9 @@ namespace osu.Game.Tests.Visual.Online
var allScores = new APIScoresCollection
{
- Scores = new List
+ Scores = new List
{
- new APIScoreInfo
+ new APIScore
{
User = new APIUser
{
@@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 1234567890,
Accuracy = 1,
},
- new APIScoreInfo
+ new APIScore
{
User = new APIUser
{
@@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 1234789,
Accuracy = 0.9997,
},
- new APIScoreInfo
+ new APIScore
{
User = new APIUser
{
@@ -121,7 +121,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 12345678,
Accuracy = 0.9854,
},
- new APIScoreInfo
+ new APIScore
{
User = new APIUser
{
@@ -143,7 +143,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 1234567,
Accuracy = 0.8765,
},
- new APIScoreInfo
+ new APIScore
{
User = new APIUser
{
@@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.Online
var myBestScore = new APIScoreWithPosition
{
- Score = new APIScoreInfo
+ Score = new APIScore
{
User = new APIUser
{
@@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Online
var myBestScoreWithNullPosition = new APIScoreWithPosition
{
- Score = new APIScoreInfo
+ Score = new APIScore
{
User = new APIUser
{
@@ -212,9 +212,9 @@ namespace osu.Game.Tests.Visual.Online
var oneScore = new APIScoresCollection
{
- Scores = new List
+ Scores = new List
{
- new APIScoreInfo
+ new APIScore
{
User = new APIUser
{
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs
index 9c2cc13416..7dfdca8276 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileScores.cs
@@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online
{
public TestSceneUserProfileScores()
{
- var firstScore = new APIScoreInfo
+ var firstScore = new APIScore
{
PP = 1047.21,
Rank = ScoreRank.SH,
@@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online
Accuracy = 0.9813
};
- var secondScore = new APIScoreInfo
+ var secondScore = new APIScore
{
PP = 134.32,
Rank = ScoreRank.A,
@@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online
Accuracy = 0.998546
};
- var thirdScore = new APIScoreInfo
+ var thirdScore = new APIScore
{
PP = 96.83,
Rank = ScoreRank.S,
@@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Online
Accuracy = 0.9726
};
- var noPPScore = new APIScoreInfo
+ var noPPScore = new APIScore
{
Rank = ScoreRank.B,
Beatmap = new APIBeatmap
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
index 4284bc6358..25ca1299ef 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
@@ -22,14 +22,17 @@ using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Screens.Ranking;
using osu.Game.Tests.Beatmaps;
+using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.Playlists
{
public class TestScenePlaylistsResultsScreen : ScreenTestScene
{
private const int scores_per_result = 10;
+ private const int real_user_position = 200;
private TestResultsScreen resultsScreen;
+
private int currentScoreId;
private bool requestComplete;
private int totalCount;
@@ -37,7 +40,7 @@ namespace osu.Game.Tests.Visual.Playlists
[SetUp]
public void Setup() => Schedule(() =>
{
- currentScoreId = 0;
+ currentScoreId = 1;
requestComplete = false;
totalCount = 0;
bindHandler();
@@ -50,13 +53,17 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("bind user score info handler", () =>
{
- userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineScoreID = currentScoreId++ };
+ userScore = TestResources.CreateTestScoreInfo();
+ userScore.OnlineID = currentScoreId++;
+
bindHandler(userScore: userScore);
});
createResults(() => userScore);
- AddAssert("user score selected", () => this.ChildrenOfType().Single(p => p.Score.OnlineScoreID == userScore.OnlineScoreID).State == PanelState.Expanded);
+ AddAssert("user score selected", () => this.ChildrenOfType().Single(p => p.Score.OnlineID == userScore.OnlineID).State == PanelState.Expanded);
+ AddAssert($"score panel position is {real_user_position}",
+ () => this.ChildrenOfType().Single(p => p.Score.OnlineID == userScore.OnlineID).ScorePosition.Value == real_user_position);
}
[Test]
@@ -74,14 +81,16 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("bind user score info handler", () =>
{
- userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineScoreID = currentScoreId++ };
+ userScore = TestResources.CreateTestScoreInfo();
+ userScore.OnlineID = currentScoreId++;
+
bindHandler(true, userScore);
});
createResults(() => userScore);
AddAssert("more than 1 panel displayed", () => this.ChildrenOfType().Count() > 1);
- AddAssert("user score selected", () => this.ChildrenOfType().Single(p => p.Score.OnlineScoreID == userScore.OnlineScoreID).State == PanelState.Expanded);
+ AddAssert("user score selected", () => this.ChildrenOfType().Single(p => p.Score.OnlineID == userScore.OnlineID).State == PanelState.Expanded);
}
[Test]
@@ -123,7 +132,9 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("bind user score info handler", () =>
{
- userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineScoreID = currentScoreId++ };
+ userScore = TestResources.CreateTestScoreInfo();
+ userScore.OnlineID = currentScoreId++;
+
bindHandler(userScore: userScore);
});
@@ -230,12 +241,12 @@ namespace osu.Game.Tests.Visual.Playlists
{
var multiplayerUserScore = new MultiplayerScore
{
- ID = (int)(userScore.OnlineScoreID ?? currentScoreId++),
+ ID = (int)(userScore.OnlineID > 0 ? userScore.OnlineID : currentScoreId++),
Accuracy = userScore.Accuracy,
EndedAt = userScore.Date,
Passed = userScore.Passed,
Rank = userScore.Rank,
- Position = 200,
+ Position = real_user_position,
MaxCombo = userScore.MaxCombo,
TotalScore = userScore.TotalScore,
User = userScore.User,
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs
index c5287d4257..a426f075e1 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs
@@ -15,9 +15,11 @@ using osu.Game.Database;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
+using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Screens.Play;
+using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual.OnlinePlay;
using osuTK.Input;
@@ -112,37 +114,80 @@ namespace osu.Game.Tests.Visual.Playlists
[Test]
public void TestBeatmapUpdatedOnReImport()
{
- BeatmapSetInfo importedSet = null;
+ string realHash = null;
+ int realOnlineId = 0;
+ int realOnlineSetId = 0;
- AddStep("import altered beatmap", () =>
+ AddStep("store real beatmap values", () =>
{
- IBeatmap beatmap = CreateBeatmap(new OsuRuleset().RulesetInfo);
-
- beatmap.BeatmapInfo.BaseDifficulty.CircleSize = 1;
-
- // intentionally increment online IDs to clash with import below.
- beatmap.BeatmapInfo.OnlineID++;
- beatmap.BeatmapInfo.BeatmapSet.OnlineID++;
-
- importedSet = manager.Import(beatmap.BeatmapInfo.BeatmapSet).Result.Value;
+ realHash = importedBeatmap.Value.Beatmaps[0].MD5Hash;
+ realOnlineId = importedBeatmap.Value.Beatmaps[0].OnlineID ?? -1;
+ realOnlineSetId = importedBeatmap.Value.OnlineID ?? -1;
});
+ AddStep("import modified beatmap", () =>
+ {
+ var modifiedBeatmap = new TestBeatmap(new OsuRuleset().RulesetInfo)
+ {
+ BeatmapInfo =
+ {
+ OnlineID = realOnlineId,
+ BeatmapSet =
+ {
+ OnlineID = realOnlineSetId
+ }
+ },
+ };
+
+ modifiedBeatmap.HitObjects.Clear();
+ modifiedBeatmap.HitObjects.Add(new HitCircle { StartTime = 5000 });
+
+ manager.Import(modifiedBeatmap.BeatmapInfo.BeatmapSet).Wait();
+ });
+
+ // Create the room using the real beatmap values.
setupAndCreateRoom(room =>
{
room.Name.Value = "my awesome room";
room.Host.Value = API.LocalUser.Value;
room.Playlist.Add(new PlaylistItem
{
- Beatmap = { Value = importedSet.Beatmaps[0] },
+ Beatmap =
+ {
+ Value = new BeatmapInfo
+ {
+ MD5Hash = realHash,
+ OnlineID = realOnlineId,
+ BeatmapSet = new BeatmapSetInfo
+ {
+ OnlineID = realOnlineSetId,
+ }
+ }
+ },
Ruleset = { Value = new OsuRuleset().RulesetInfo }
});
});
- AddAssert("match has altered beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize == 1);
+ AddAssert("match has default beatmap", () => match.Beatmap.IsDefault);
- importBeatmap();
+ AddStep("reimport original beatmap", () =>
+ {
+ var originalBeatmap = new TestBeatmap(new OsuRuleset().RulesetInfo)
+ {
+ BeatmapInfo =
+ {
+ OnlineID = realOnlineId,
+ BeatmapSet =
+ {
+ OnlineID = realOnlineSetId
+ }
+ },
+ };
- AddAssert("match has original beatmap", () => match.Beatmap.Value.Beatmap.Difficulty.CircleSize != 1);
+ manager.Import(originalBeatmap.BeatmapInfo.BeatmapSet).Wait();
+ });
+
+ AddUntilStep("match has correct beatmap", () => realHash == match.Beatmap.Value.BeatmapInfo.MD5Hash);
}
private void setupAndCreateRoom(Action room)
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs
index f246560c82..85306b9354 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneContractedPanelMiddleContent.cs
@@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -13,6 +14,7 @@ using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Ranking.Contracted;
+using osu.Game.Tests.Resources;
using osuTK;
namespace osu.Game.Tests.Visual.Ranking
@@ -22,13 +24,18 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestShowPanel()
{
- AddStep("show example score", () => showPanel(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), new TestScoreInfo(new OsuRuleset().RulesetInfo)));
+ AddStep("show example score", () => showPanel(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), TestResources.CreateTestScoreInfo()));
}
[Test]
public void TestExcessMods()
{
- AddStep("show excess mods score", () => showPanel(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), new TestScoreInfo(new OsuRuleset().RulesetInfo, true)));
+ AddStep("show excess mods score", () =>
+ {
+ var score = TestResources.CreateTestScoreInfo();
+ score.Mods = score.BeatmapInfo.Ruleset.CreateInstance().CreateAllMods().ToArray();
+ showPanel(CreateWorkingBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo)), score);
+ });
}
private void showPanel(WorkingBeatmap workingBeatmap, ScoreInfo score)
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs
index 9983993d9c..2cb4fb6b6b 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelMiddleContent.cs
@@ -20,6 +20,7 @@ using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Ranking.Expanded;
using osu.Game.Tests.Beatmaps;
+using osu.Game.Tests.Resources;
using osuTK;
namespace osu.Game.Tests.Visual.Ranking
@@ -34,21 +35,21 @@ namespace osu.Game.Tests.Visual.Ranking
{
var author = new APIUser { Username = "mapper_name" };
- AddStep("show example score", () => showPanel(new TestScoreInfo(new OsuRuleset().RulesetInfo)
- {
- BeatmapInfo = createTestBeatmap(author)
- }));
+ AddStep("show example score", () => showPanel(TestResources.CreateTestScoreInfo(createTestBeatmap(author))));
}
[Test]
public void TestExcessMods()
{
- var author = new APIUser { Username = "mapper_name" };
-
- AddStep("show excess mods score", () => showPanel(new TestScoreInfo(new OsuRuleset().RulesetInfo, true)
+ AddStep("show excess mods score", () =>
{
- BeatmapInfo = createTestBeatmap(author)
- }));
+ var author = new APIUser { Username = "mapper_name" };
+
+ var score = TestResources.CreateTestScoreInfo(createTestBeatmap(author));
+ score.Mods = score.BeatmapInfo.Ruleset.CreateInstance().CreateAllMods().ToArray();
+
+ showPanel(score);
+ });
AddAssert("mapper name present", () => this.ChildrenOfType().Any(spriteText => spriteText.Current.Value == "mapper_name"));
}
@@ -56,10 +57,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestMapWithUnknownMapper()
{
- AddStep("show example score", () => showPanel(new TestScoreInfo(new OsuRuleset().RulesetInfo)
- {
- BeatmapInfo = createTestBeatmap(new APIUser())
- }));
+ AddStep("show example score", () => showPanel(TestResources.CreateTestScoreInfo(createTestBeatmap(new APIUser()))));
AddAssert("mapped by text not present", () =>
this.ChildrenOfType().All(spriteText => !containsAny(spriteText.Text.ToString(), "mapped", "by")));
@@ -77,12 +75,12 @@ namespace osu.Game.Tests.Visual.Ranking
var mods = new Mod[] { ruleset.GetAutoplayMod() };
var beatmap = createTestBeatmap(new APIUser());
- showPanel(new TestScoreInfo(ruleset.RulesetInfo)
- {
- Mods = mods,
- BeatmapInfo = beatmap,
- Date = default,
- });
+ var score = TestResources.CreateTestScoreInfo(beatmap);
+
+ score.Mods = mods;
+ score.Date = default;
+
+ showPanel(score);
});
AddAssert("play time not displayed", () => !this.ChildrenOfType().Any());
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs
index a32bcbe7f0..a2fa142896 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneExpandedPanelTopContent.cs
@@ -5,8 +5,8 @@ using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
-using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Ranking.Expanded;
+using osu.Game.Tests.Resources;
using osuTK;
namespace osu.Game.Tests.Visual.Ranking
@@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Ranking
RelativeSizeAxes = Axes.Both,
Colour = Color4Extensions.FromHex("#444"),
},
- new ExpandedPanelTopContent(new TestScoreInfo(new OsuRuleset().RulesetInfo).User),
+ new ExpandedPanelTopContent(TestResources.CreateTestScoreInfo().User),
}
};
}
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs
index 94700bac6a..d0bd5a6e66 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneResultsScreen.cs
@@ -15,12 +15,12 @@ using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
-using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
using osu.Game.Screens;
using osu.Game.Screens.Play;
using osu.Game.Screens.Ranking;
using osu.Game.Screens.Ranking.Statistics;
+using osu.Game.Tests.Resources;
using osuTK;
using osuTK.Input;
@@ -72,11 +72,10 @@ namespace osu.Game.Tests.Visual.Ranking
{
TestResultsScreen screen = null;
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo)
- {
- Accuracy = accuracy,
- Rank = rank
- };
+ var score = TestResources.CreateTestScoreInfo();
+
+ score.Accuracy = accuracy;
+ score.Rank = rank;
AddStep("load results", () => Child = new TestResultsContainer(screen = createResultsScreen(score)));
AddUntilStep("wait for loaded", () => screen.IsLoaded);
@@ -204,7 +203,7 @@ namespace osu.Game.Tests.Visual.Ranking
{
DelayedFetchResultsScreen screen = null;
- AddStep("load results", () => Child = new TestResultsContainer(screen = new DelayedFetchResultsScreen(new TestScoreInfo(new OsuRuleset().RulesetInfo), 3000)));
+ AddStep("load results", () => Child = new TestResultsContainer(screen = new DelayedFetchResultsScreen(TestResources.CreateTestScoreInfo(), 3000)));
AddUntilStep("wait for loaded", () => screen.IsLoaded);
AddStep("click expanded panel", () =>
{
@@ -237,9 +236,9 @@ namespace osu.Game.Tests.Visual.Ranking
AddAssert("download button is enabled", () => screen.ChildrenOfType().Last().Enabled.Value);
}
- private TestResultsScreen createResultsScreen(ScoreInfo score = null) => new TestResultsScreen(score ?? new TestScoreInfo(new OsuRuleset().RulesetInfo));
+ private TestResultsScreen createResultsScreen(ScoreInfo score = null) => new TestResultsScreen(score ?? TestResources.CreateTestScoreInfo());
- private UnrankedSoloResultsScreen createUnrankedSoloResultsScreen() => new UnrankedSoloResultsScreen(new TestScoreInfo(new OsuRuleset().RulesetInfo));
+ private UnrankedSoloResultsScreen createUnrankedSoloResultsScreen() => new UnrankedSoloResultsScreen(TestResources.CreateTestScoreInfo());
private class TestResultsContainer : Container
{
@@ -282,7 +281,7 @@ namespace osu.Game.Tests.Visual.Ranking
for (int i = 0; i < 20; i++)
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var score = TestResources.CreateTestScoreInfo();
score.TotalScore += 10 - i;
score.Hash = $"test{i}";
scores.Add(score);
@@ -316,7 +315,7 @@ namespace osu.Game.Tests.Visual.Ranking
for (int i = 0; i < 20; i++)
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var score = TestResources.CreateTestScoreInfo();
score.TotalScore += 10 - i;
scores.Add(score);
}
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs
index 5af55e99f8..5dbeefd390 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanel.cs
@@ -3,10 +3,10 @@
using NUnit.Framework;
using osu.Framework.Graphics;
-using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
+using osu.Game.Tests.Resources;
namespace osu.Game.Tests.Visual.Ranking
{
@@ -17,7 +17,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestDRank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.5, Rank = ScoreRank.D };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.5;
+ score.Rank = ScoreRank.D;
addPanelStep(score);
}
@@ -25,7 +27,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestCRank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.75, Rank = ScoreRank.C };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.75;
+ score.Rank = ScoreRank.C;
addPanelStep(score);
}
@@ -33,7 +37,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestBRank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.85, Rank = ScoreRank.B };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.85;
+ score.Rank = ScoreRank.B;
addPanelStep(score);
}
@@ -41,7 +47,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestARank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.925, Rank = ScoreRank.A };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.925;
+ score.Rank = ScoreRank.A;
addPanelStep(score);
}
@@ -49,7 +57,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestSRank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.975, Rank = ScoreRank.S };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.975;
+ score.Rank = ScoreRank.S;
addPanelStep(score);
}
@@ -57,7 +67,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAlmostSSRank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.9999, Rank = ScoreRank.S };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.9999;
+ score.Rank = ScoreRank.S;
addPanelStep(score);
}
@@ -65,7 +77,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestSSRank()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 1, Rank = ScoreRank.X };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 1;
+ score.Rank = ScoreRank.X;
addPanelStep(score);
}
@@ -73,7 +87,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAllHitResults()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Statistics = { [HitResult.Perfect] = 350, [HitResult.Ok] = 200 } };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Statistics[HitResult.Perfect] = 350;
+ score.Statistics[HitResult.Ok] = 200;
addPanelStep(score);
}
@@ -81,7 +97,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestContractedPanel()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.925, Rank = ScoreRank.A };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.925;
+ score.Rank = ScoreRank.A;
addPanelStep(score, PanelState.Contracted);
}
@@ -89,7 +107,9 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestExpandAndContract()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo) { Accuracy = 0.925, Rank = ScoreRank.A };
+ var score = TestResources.CreateTestScoreInfo();
+ score.Accuracy = 0.925;
+ score.Rank = ScoreRank.A;
addPanelStep(score, PanelState.Contracted);
AddWaitStep("wait for transition", 10);
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs
index b7b7407428..f5ad352b9c 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneScorePanelList.cs
@@ -7,9 +7,9 @@ using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Framework.Utils;
-using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
+using osu.Game.Tests.Resources;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Ranking
@@ -29,14 +29,14 @@ namespace osu.Game.Tests.Visual.Ranking
{
createListStep(() => new ScorePanelList
{
- SelectedScore = { Value = new TestScoreInfo(new OsuRuleset().RulesetInfo) }
+ SelectedScore = { Value = TestResources.CreateTestScoreInfo() }
});
}
[Test]
public void TestAddPanelAfterSelectingScore()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var score = TestResources.CreateTestScoreInfo();
createListStep(() => new ScorePanelList
{
@@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAddPanelBeforeSelectingScore()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var score = TestResources.CreateTestScoreInfo();
createListStep(() => new ScorePanelList());
@@ -75,7 +75,7 @@ namespace osu.Game.Tests.Visual.Ranking
AddStep("add many scores", () =>
{
for (int i = 0; i < 20; i++)
- list.AddScore(new TestScoreInfo(new OsuRuleset().RulesetInfo));
+ list.AddScore(TestResources.CreateTestScoreInfo());
});
assertFirstPanelCentred();
@@ -84,7 +84,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAddManyScoresAfterExpandedPanel()
{
- var initialScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var initialScore = TestResources.CreateTestScoreInfo();
createListStep(() => new ScorePanelList());
@@ -97,7 +97,7 @@ namespace osu.Game.Tests.Visual.Ranking
AddStep("add many scores", () =>
{
for (int i = 0; i < 20; i++)
- list.AddScore(new TestScoreInfo(new OsuRuleset().RulesetInfo) { TotalScore = initialScore.TotalScore - i - 1 });
+ list.AddScore(createScoreForTotalScore(initialScore.TotalScore - i - 1));
});
assertScoreState(initialScore, true);
@@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAddManyScoresBeforeExpandedPanel()
{
- var initialScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var initialScore = TestResources.CreateTestScoreInfo();
createListStep(() => new ScorePanelList());
@@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Ranking
AddStep("add scores", () =>
{
for (int i = 0; i < 20; i++)
- list.AddScore(new TestScoreInfo(new OsuRuleset().RulesetInfo) { TotalScore = initialScore.TotalScore + i + 1 });
+ list.AddScore(createScoreForTotalScore(initialScore.TotalScore + i + 1));
});
assertScoreState(initialScore, true);
@@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAddManyPanelsOnBothSidesOfExpandedPanel()
{
- var initialScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var initialScore = TestResources.CreateTestScoreInfo();
createListStep(() => new ScorePanelList());
@@ -143,10 +143,10 @@ namespace osu.Game.Tests.Visual.Ranking
AddStep("add scores after", () =>
{
for (int i = 0; i < 20; i++)
- list.AddScore(new TestScoreInfo(new OsuRuleset().RulesetInfo) { TotalScore = initialScore.TotalScore - i - 1 });
+ list.AddScore(createScoreForTotalScore(initialScore.TotalScore - i - 1));
for (int i = 0; i < 20; i++)
- list.AddScore(new TestScoreInfo(new OsuRuleset().RulesetInfo) { TotalScore = initialScore.TotalScore + i + 1 });
+ list.AddScore(createScoreForTotalScore(initialScore.TotalScore + i + 1));
});
assertScoreState(initialScore, true);
@@ -156,11 +156,11 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestSelectMultipleScores()
{
- var firstScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
- var secondScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var firstScore = TestResources.CreateTestScoreInfo();
+ var secondScore = TestResources.CreateTestScoreInfo();
- firstScore.User.Username = "A";
- secondScore.User.Username = "B";
+ firstScore.UserString = "A";
+ secondScore.UserString = "B";
createListStep(() => new ScorePanelList());
@@ -190,7 +190,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestAddScoreImmediately()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo);
+ var score = TestResources.CreateTestScoreInfo();
createListStep(() =>
{
@@ -206,9 +206,14 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestKeyboardNavigation()
{
- var lowestScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { MaxCombo = 100 };
- var middleScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { MaxCombo = 200 };
- var highestScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { MaxCombo = 300 };
+ var lowestScore = TestResources.CreateTestScoreInfo();
+ lowestScore.MaxCombo = 100;
+
+ var middleScore = TestResources.CreateTestScoreInfo();
+ middleScore.MaxCombo = 200;
+
+ var highestScore = TestResources.CreateTestScoreInfo();
+ highestScore.MaxCombo = 300;
createListStep(() => new ScorePanelList());
@@ -270,6 +275,13 @@ namespace osu.Game.Tests.Visual.Ranking
assertExpandedPanelCentred();
}
+ private ScoreInfo createScoreForTotalScore(long totalScore)
+ {
+ var score = TestResources.CreateTestScoreInfo();
+ score.TotalScore = totalScore;
+ return score;
+ }
+
private void createListStep(Func creationFunc)
{
AddStep("create list", () => Child = list = creationFunc().With(d =>
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs
index d91aec753c..f64b7b2b65 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneStatisticsPanel.cs
@@ -6,11 +6,11 @@ using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking.Statistics;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring;
+using osu.Game.Tests.Resources;
using osuTK;
namespace osu.Game.Tests.Visual.Ranking
@@ -20,10 +20,8 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestScoreWithTimeStatistics()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo)
- {
- HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents()
- };
+ var score = TestResources.CreateTestScoreInfo();
+ score.HitEvents = TestSceneHitEventTimingDistributionGraph.CreateDistributedHitEvents();
loadPanel(score);
}
@@ -31,10 +29,8 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestScoreWithPositionStatistics()
{
- var score = new TestScoreInfo(new OsuRuleset().RulesetInfo)
- {
- HitEvents = createPositionDistributedHitEvents()
- };
+ var score = TestResources.CreateTestScoreInfo();
+ score.HitEvents = createPositionDistributedHitEvents();
loadPanel(score);
}
@@ -42,7 +38,7 @@ namespace osu.Game.Tests.Visual.Ranking
[Test]
public void TestScoreWithoutStatistics()
{
- loadPanel(new TestScoreInfo(new OsuRuleset().RulesetInfo));
+ loadPanel(TestResources.CreateTestScoreInfo());
}
[Test]
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index 0494d1de3c..be390742ea 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -835,12 +835,7 @@ namespace osu.Game.Tests.Visual.SongSelect
// this beatmap change should be overridden by the present.
Beatmap.Value = manager.GetWorkingBeatmap(getSwitchBeatmap());
- songSelect.PresentScore(new ScoreInfo
- {
- User = new APIUser { Username = "woo" },
- BeatmapInfo = getPresentBeatmap(),
- Ruleset = getPresentBeatmap().Ruleset
- });
+ songSelect.PresentScore(TestResources.CreateTestScoreInfo(getPresentBeatmap()));
});
AddUntilStep("wait for results screen presented", () => !songSelect.IsCurrentScreen());
diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs
index 9f0f4a6b8b..2363bbbfcf 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs
@@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{
var score = new ScoreInfo
{
- OnlineScoreID = i,
+ OnlineID = i,
BeatmapInfo = beatmapInfo,
BeatmapInfoID = beatmapInfo.ID,
Accuracy = RNG.NextDouble(),
@@ -163,7 +163,7 @@ namespace osu.Game.Tests.Visual.UserInterface
});
AddUntilStep("wait for fetch", () => leaderboard.Scores != null);
- AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineScoreID != scoreBeingDeleted.OnlineScoreID));
+ AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineID != scoreBeingDeleted.OnlineID));
}
[Test]
@@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{
AddStep("delete top score", () => scoreManager.Delete(importedScores[0]));
AddUntilStep("wait for fetch", () => leaderboard.Scores != null);
- AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineScoreID != importedScores[0].OnlineScoreID));
+ AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineID != importedScores[0].OnlineID));
}
}
}
diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs
index 13d362e0be..7cd9ae2885 100644
--- a/osu.Game/Database/OsuDbContext.cs
+++ b/osu.Game/Database/OsuDbContext.cs
@@ -147,7 +147,7 @@ namespace osu.Game.Database
modelBuilder.Entity().HasOne(b => b.BaseDifficulty);
- modelBuilder.Entity().HasIndex(b => b.OnlineScoreID).IsUnique();
+ modelBuilder.Entity().HasIndex(b => b.OnlineID).IsUnique();
}
private class OsuDbLoggerFactory : ILoggerFactory
diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs
index 2274da0fd4..f178a5c97b 100644
--- a/osu.Game/Extensions/ModelExtensions.cs
+++ b/osu.Game/Extensions/ModelExtensions.cs
@@ -104,6 +104,14 @@ namespace osu.Game.Extensions
/// Whether online IDs match. If either instance is missing an online ID, this will return false.
public static bool MatchesOnlineID(this APIUser? instance, APIUser? other) => matchesOnlineID(instance, other);
+ ///
+ /// Check whether the online ID of two s match.
+ ///
+ /// The instance to compare.
+ /// The other instance to compare against.
+ /// Whether online IDs match. If either instance is missing an online ID, this will return false.
+ public static bool MatchesOnlineID(this IScoreInfo? instance, IScoreInfo? other) => matchesOnlineID(instance, other);
+
private static bool matchesOnlineID(this IHasOnlineID? instance, IHasOnlineID? other)
{
if (instance == null || other == null)
diff --git a/osu.Game/Input/RealmKeyBindingStore.cs b/osu.Game/Input/RealmKeyBindingStore.cs
index 3bdb0a180d..cb51797685 100644
--- a/osu.Game/Input/RealmKeyBindingStore.cs
+++ b/osu.Game/Input/RealmKeyBindingStore.cs
@@ -81,20 +81,37 @@ namespace osu.Game.Input
// 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.RulesetName == rulesetName && k.Variant == variant && k.ActionInt == (int)defaultsForAction.Key);
+ IEnumerable existing = existingBindings.Where(k =>
+ k.RulesetName == rulesetName
+ && k.Variant == variant
+ && k.ActionInt == (int)defaultsForAction.Key);
- if (defaultsForAction.Count() <= existingCount)
- continue;
+ int defaultsCount = defaultsForAction.Count();
+ int existingCount = existing.Count();
- // insert any defaults which are missing.
- realm.Add(defaultsForAction.Skip(existingCount).Select(k => new RealmKeyBinding
+ if (defaultsCount > existingCount)
{
- KeyCombinationString = k.KeyCombination.ToString(),
- ActionInt = (int)k.Action,
- RulesetName = rulesetName,
- Variant = variant
- }));
+ // insert any defaults which are missing.
+ realm.Add(defaultsForAction.Skip(existingCount).Select(k => new RealmKeyBinding
+ {
+ KeyCombinationString = k.KeyCombination.ToString(),
+ ActionInt = (int)k.Action,
+ RulesetName = rulesetName,
+ Variant = variant
+ }));
+ }
+ else if (defaultsCount < existingCount)
+ {
+ // generally this shouldn't happen, but if the user has more key bindings for an action than we expect,
+ // remove the last entries until the count matches for sanity.
+ foreach (var k in existing.TakeLast(existingCount - defaultsCount).ToArray())
+ {
+ realm.Remove(k);
+
+ // Remove from the local flattened/cached list so future lookups don't query now deleted rows.
+ existingBindings.Remove(k);
+ }
+ }
}
}
diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs
index e13ac8e539..653abf7427 100644
--- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs
+++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs
@@ -8,7 +8,7 @@ using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests
{
- public class GetUserScoresRequest : PaginatedAPIRequest>
+ public class GetUserScoresRequest : PaginatedAPIRequest>
{
private readonly long userId;
private readonly ScoreType type;
diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScore.cs
similarity index 96%
rename from osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs
rename to osu.Game/Online/API/Requests/Responses/APIScore.cs
index 467d5a9f23..4f795bee6c 100644
--- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIScore.cs
@@ -13,10 +13,11 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
+using osu.Game.Users;
namespace osu.Game.Online.API.Requests.Responses
{
- public class APIScoreInfo : IScoreInfo
+ public class APIScore : IScoreInfo
{
[JsonProperty(@"score")]
public long TotalScore { get; set; }
@@ -101,7 +102,7 @@ namespace osu.Game.Online.API.Requests.Responses
BeatmapInfo = beatmap,
User = User,
Accuracy = Accuracy,
- OnlineScoreID = OnlineID,
+ OnlineID = OnlineID,
Date = Date,
PP = PP,
RulesetID = RulesetID,
@@ -150,6 +151,11 @@ namespace osu.Game.Online.API.Requests.Responses
public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID };
IEnumerable IHasNamedFiles.Files => throw new NotImplementedException();
+ #region Implementation of IScoreInfo
+
IBeatmapInfo IScoreInfo.Beatmap => Beatmap;
+ IUser IScoreInfo.User => User;
+
+ #endregion
}
}
diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs
index 48b7134901..d3c9ba0c7e 100644
--- a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs
@@ -14,7 +14,7 @@ namespace osu.Game.Online.API.Requests.Responses
public int? Position;
[JsonProperty(@"score")]
- public APIScoreInfo Score;
+ public APIScore Score;
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null)
{
diff --git a/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs b/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs
index 5304664bf8..283ebf2411 100644
--- a/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs
@@ -9,7 +9,7 @@ namespace osu.Game.Online.API.Requests.Responses
public class APIScoresCollection
{
[JsonProperty(@"scores")]
- public List Scores;
+ public List Scores;
[JsonProperty(@"userScore")]
public APIScoreWithPosition UserScore;
diff --git a/osu.Game/Online/Chat/MessageNotifier.cs b/osu.Game/Online/Chat/MessageNotifier.cs
index ca6317566f..a11af7b305 100644
--- a/osu.Game/Online/Chat/MessageNotifier.cs
+++ b/osu.Game/Online/Chat/MessageNotifier.cs
@@ -1,10 +1,10 @@
// 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 System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
+using System.Text.RegularExpressions;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@@ -120,16 +120,21 @@ namespace osu.Game.Online.Chat
private void checkForMentions(Channel channel, Message message)
{
- if (!notifyOnUsername.Value || !checkContainsUsername(message.Content, localUser.Value.Username)) return;
+ if (!notifyOnUsername.Value || !CheckContainsUsername(message.Content, localUser.Value.Username)) return;
notifications.Post(new MentionNotification(message.Sender.Username, channel));
}
///
- /// Checks if contains .
+ /// Checks if mentions .
/// This will match against the case where underscores are used instead of spaces (which is how osu-stable handles usernames with spaces).
///
- private static bool checkContainsUsername(string message, string username) => message.Contains(username, StringComparison.OrdinalIgnoreCase) || message.Contains(username.Replace(' ', '_'), StringComparison.OrdinalIgnoreCase);
+ public static bool CheckContainsUsername(string message, string username)
+ {
+ string fullName = Regex.Escape(username);
+ string underscoreName = Regex.Escape(username.Replace(' ', '_'));
+ return Regex.IsMatch(message, $@"(^|\W)({fullName}|{underscoreName})($|\W)", RegexOptions.IgnoreCase);
+ }
public class PrivateMessageNotification : OpenChannelNotification
{
diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs
index 644c2e2a99..14eec8b388 100644
--- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs
+++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs
@@ -111,7 +111,7 @@ namespace osu.Game.Online.Leaderboards
background = new Box
{
RelativeSizeAxes = Axes.Both,
- Colour = user.Id == api.LocalUser.Value.Id && allowHighlight ? colour.Green : Color4.Black,
+ Colour = user.OnlineID == api.LocalUser.Value.Id && allowHighlight ? colour.Green : Color4.Black,
Alpha = background_alpha,
},
},
diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
index 55b4def908..f366de557f 100644
--- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
@@ -95,8 +95,6 @@ namespace osu.Game.Online.Multiplayer
protected readonly BindableList PlayingUserIds = new BindableList();
- public readonly Bindable CurrentMatchPlayingItem = new Bindable();
-
///
/// The corresponding to the local player, if available.
///
@@ -162,9 +160,6 @@ namespace osu.Game.Online.Multiplayer
var joinedRoom = await JoinRoom(room.RoomID.Value.Value, password ?? room.Password.Value).ConfigureAwait(false);
Debug.Assert(joinedRoom != null);
- // Populate playlist items.
- var playlistItems = await Task.WhenAll(joinedRoom.Playlist.Select(item => createPlaylistItem(item, item.ID == joinedRoom.Settings.PlaylistItemId))).ConfigureAwait(false);
-
// Populate users.
Debug.Assert(joinedRoom.Users != null);
await Task.WhenAll(joinedRoom.Users.Select(PopulateUser)).ConfigureAwait(false);
@@ -176,7 +171,7 @@ namespace osu.Game.Online.Multiplayer
APIRoom = room;
APIRoom.Playlist.Clear();
- APIRoom.Playlist.AddRange(playlistItems);
+ APIRoom.Playlist.AddRange(joinedRoom.Playlist.Select(createPlaylistItem));
Debug.Assert(LocalUser != null);
addUserToAPIRoom(LocalUser);
@@ -219,7 +214,6 @@ namespace osu.Game.Online.Multiplayer
{
APIRoom = null;
Room = null;
- CurrentMatchPlayingItem.Value = null;
PlayingUserIds.Clear();
RoomUpdated?.Invoke();
@@ -477,28 +471,7 @@ namespace osu.Game.Online.Multiplayer
Debug.Assert(APIRoom != null);
Debug.Assert(Room != null);
- Scheduler.Add(() =>
- {
- // ensure the new selected item is populated immediately.
- var playlistItem = APIRoom.Playlist.Single(p => p.ID == newSettings.PlaylistItemId);
-
- if (playlistItem != null)
- {
- GetAPIBeatmap(playlistItem.BeatmapID).ContinueWith(b =>
- {
- // Should be called outside of the `Scheduler` logic (and specifically accessing `Exception`) to suppress an exception from firing outwards.
- bool success = b.Exception == null;
-
- Scheduler.Add(() =>
- {
- if (success)
- playlistItem.Beatmap.Value = b.Result;
-
- updateLocalRoomSettings(newSettings);
- });
- });
- }
- });
+ Scheduler.Add(() => updateLocalRoomSettings(newSettings));
return Task.CompletedTask;
}
@@ -653,12 +626,10 @@ namespace osu.Game.Online.Multiplayer
return Task.CompletedTask;
}
- public async Task PlaylistItemAdded(MultiplayerPlaylistItem item)
+ public Task PlaylistItemAdded(MultiplayerPlaylistItem item)
{
if (Room == null)
- return;
-
- var playlistItem = await createPlaylistItem(item, true).ConfigureAwait(false);
+ return Task.CompletedTask;
Scheduler.Add(() =>
{
@@ -668,11 +639,13 @@ namespace osu.Game.Online.Multiplayer
Debug.Assert(APIRoom != null);
Room.Playlist.Add(item);
- APIRoom.Playlist.Add(playlistItem);
+ APIRoom.Playlist.Add(createPlaylistItem(item));
ItemAdded?.Invoke(item);
RoomUpdated?.Invoke();
});
+
+ return Task.CompletedTask;
}
public Task PlaylistItemRemoved(long playlistItemId)
@@ -697,12 +670,10 @@ namespace osu.Game.Online.Multiplayer
return Task.CompletedTask;
}
- public async Task PlaylistItemChanged(MultiplayerPlaylistItem item)
+ public Task PlaylistItemChanged(MultiplayerPlaylistItem item)
{
if (Room == null)
- return;
-
- var playlistItem = await createPlaylistItem(item, true).ConfigureAwait(false);
+ return Task.CompletedTask;
Scheduler.Add(() =>
{
@@ -715,15 +686,13 @@ namespace osu.Game.Online.Multiplayer
int existingIndex = APIRoom.Playlist.IndexOf(APIRoom.Playlist.Single(existing => existing.ID == item.ID));
APIRoom.Playlist.RemoveAt(existingIndex);
- APIRoom.Playlist.Insert(existingIndex, playlistItem);
-
- // If the currently-selected item was the one that got replaced, update the selected item to the new one.
- if (CurrentMatchPlayingItem.Value?.ID == playlistItem.ID)
- CurrentMatchPlayingItem.Value = playlistItem;
+ APIRoom.Playlist.Insert(existingIndex, createPlaylistItem(item));
ItemChanged?.Invoke(item);
RoomUpdated?.Invoke();
});
+
+ return Task.CompletedTask;
}
///
@@ -752,12 +721,11 @@ namespace osu.Game.Online.Multiplayer
APIRoom.Password.Value = Room.Settings.Password;
APIRoom.Type.Value = Room.Settings.MatchType;
APIRoom.QueueMode.Value = Room.Settings.QueueMode;
- RoomUpdated?.Invoke();
- CurrentMatchPlayingItem.Value = APIRoom.Playlist.SingleOrDefault(p => p.ID == settings.PlaylistItemId);
+ RoomUpdated?.Invoke();
}
- private async Task createPlaylistItem(MultiplayerPlaylistItem item, bool populateBeatmapImmediately)
+ private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item)
{
var ruleset = Rulesets.GetRuleset(item.RulesetID);
@@ -779,9 +747,6 @@ namespace osu.Game.Online.Multiplayer
playlistItem.RequiredMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance)));
playlistItem.AllowedMods.AddRange(item.AllowedMods.Select(m => m.ToMod(rulesetInstance)));
- if (populateBeatmapImmediately)
- playlistItem.Beatmap.Value = await GetAPIBeatmap(item.BeatmapID).ConfigureAwait(false);
-
return playlistItem;
}
@@ -791,7 +756,7 @@ namespace osu.Game.Online.Multiplayer
/// The beatmap ID.
/// A token to cancel the request.
/// The retrieval task.
- protected abstract Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default);
+ public abstract Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default);
///
/// For the provided user ID, update whether the user is included in .
diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
index d268d2bf69..f911ef3121 100644
--- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
@@ -178,7 +178,7 @@ namespace osu.Game.Online.Multiplayer
return connection.InvokeAsync(nameof(IMultiplayerServer.RemovePlaylistItem), playlistItemId);
}
- protected override Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
+ public override Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
{
return beatmapLookupCache.GetBeatmapAsync(beatmapId, cancellationToken);
}
diff --git a/osu.Game/Online/Rooms/MultiplayerScore.cs b/osu.Game/Online/Rooms/MultiplayerScore.cs
index 7bc3377ad9..05c9a1b6cf 100644
--- a/osu.Game/Online/Rooms/MultiplayerScore.cs
+++ b/osu.Game/Online/Rooms/MultiplayerScore.cs
@@ -69,7 +69,7 @@ namespace osu.Game.Online.Rooms
var scoreInfo = new ScoreInfo
{
- OnlineScoreID = ID,
+ OnlineID = ID,
TotalScore = TotalScore,
MaxCombo = MaxCombo,
BeatmapInfo = beatmap,
diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs
index aa0e37363b..a32f069470 100644
--- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs
+++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs
@@ -40,6 +40,11 @@ namespace osu.Game.Online.Rooms
private BeatmapDownloadTracker downloadTracker;
+ ///
+ /// The beatmap matching the required hash (and providing a final state).
+ ///
+ private BeatmapInfo matchingHash;
+
protected override void LoadComplete()
{
base.LoadComplete();
@@ -71,13 +76,34 @@ namespace osu.Game.Online.Rooms
progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500);
}, true);
}, true);
+
+ // These events are needed for a fringe case where a modified/altered beatmap is imported with matching OnlineIDs.
+ // During the import process this will cause the existing beatmap set to be silently deleted and replaced with the new one.
+ // This is not exposed to us via `BeatmapDownloadTracker` so we have to take it into our own hands (as we care about the hash matching).
+ beatmapManager.ItemUpdated += itemUpdated;
+ beatmapManager.ItemRemoved += itemRemoved;
}
+ private void itemUpdated(BeatmapSetInfo item) => Schedule(() =>
+ {
+ if (matchingHash?.BeatmapSet.ID == item.ID || SelectedItem.Value?.Beatmap.Value.BeatmapSet?.OnlineID == item.OnlineID)
+ updateAvailability();
+ });
+
+ private void itemRemoved(BeatmapSetInfo item) => Schedule(() =>
+ {
+ if (matchingHash?.BeatmapSet.ID == item.ID)
+ updateAvailability();
+ });
+
private void updateAvailability()
{
if (downloadTracker == null)
return;
+ // will be repopulated below if still valid.
+ matchingHash = null;
+
switch (downloadTracker.State.Value)
{
case DownloadState.NotDownloaded:
@@ -93,7 +119,9 @@ namespace osu.Game.Online.Rooms
break;
case DownloadState.LocallyAvailable:
- bool hashMatches = checkHashValidity();
+ matchingHash = findMatchingHash();
+
+ bool hashMatches = matchingHash != null;
availability.Value = hashMatches ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
@@ -108,12 +136,23 @@ namespace osu.Game.Online.Rooms
}
}
- private bool checkHashValidity()
+ private BeatmapInfo findMatchingHash()
{
int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID;
string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash;
- return beatmapManager.QueryBeatmap(b => b.OnlineID == onlineId && b.MD5Hash == checksum && !b.BeatmapSet.DeletePending) != null;
+ return beatmapManager.QueryBeatmap(b => b.OnlineID == onlineId && b.MD5Hash == checksum && !b.BeatmapSet.DeletePending);
+ }
+
+ protected override void Dispose(bool isDisposing)
+ {
+ base.Dispose(isDisposing);
+
+ if (beatmapManager != null)
+ {
+ beatmapManager.ItemUpdated -= itemUpdated;
+ beatmapManager.ItemRemoved -= itemRemoved;
+ }
}
}
}
diff --git a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs
index d5da6c401c..e24d113822 100644
--- a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs
+++ b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs
@@ -31,6 +31,7 @@ namespace osu.Game.Online.Rooms
req.ContentType = "application/json";
req.Method = HttpMethod.Put;
+ req.Timeout = 30000;
req.AddRaw(JsonConvert.SerializeObject(score, new JsonSerializerSettings
{
diff --git a/osu.Game/Online/ScoreDownloadTracker.cs b/osu.Game/Online/ScoreDownloadTracker.cs
index e09cc7c9cd..68932cc388 100644
--- a/osu.Game/Online/ScoreDownloadTracker.cs
+++ b/osu.Game/Online/ScoreDownloadTracker.cs
@@ -3,6 +3,7 @@
using System;
using osu.Framework.Allocation;
+using osu.Game.Extensions;
using osu.Game.Online.API;
using osu.Game.Scoring;
@@ -35,7 +36,7 @@ namespace osu.Game.Online
var scoreInfo = new ScoreInfo
{
ID = TrackedItem.ID,
- OnlineScoreID = TrackedItem.OnlineScoreID
+ OnlineID = TrackedItem.OnlineID
};
if (Manager.IsAvailableLocally(scoreInfo))
@@ -113,7 +114,7 @@ namespace osu.Game.Online
UpdateState(DownloadState.NotDownloaded);
});
- private bool checkEquality(IScoreInfo x, IScoreInfo y) => x.OnlineID == y.OnlineID;
+ private bool checkEquality(IScoreInfo x, IScoreInfo y) => x.MatchesOnlineID(y);
#region Disposal
diff --git a/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs b/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs
index 25c2e5a61f..99cf5ceff5 100644
--- a/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs
+++ b/osu.Game/Online/Solo/SubmitSoloScoreRequest.cs
@@ -31,6 +31,7 @@ namespace osu.Game.Online.Solo
req.ContentType = "application/json";
req.Method = HttpMethod.Put;
+ req.Timeout = 30000;
req.AddRaw(JsonConvert.SerializeObject(score, new JsonSerializerSettings
{
diff --git a/osu.Game/Online/Solo/SubmittableScore.cs b/osu.Game/Online/Solo/SubmittableScore.cs
index 373c302844..5ca5ad9619 100644
--- a/osu.Game/Online/Solo/SubmittableScore.cs
+++ b/osu.Game/Online/Solo/SubmittableScore.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Online.Solo
{
///
/// A class specifically for sending scores to the API during score submission.
- /// This is used instead of due to marginally different serialisation naming requirements.
+ /// This is used instead of due to marginally different serialisation naming requirements.
///
[Serializable]
public class SubmittableScore
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 047c3b4225..a35191613c 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -103,7 +103,7 @@ namespace osu.Game
private Container topMostOverlayContent;
- private ScalingContainer screenContainer;
+ protected ScalingContainer ScreenContainer { get; private set; }
protected Container ScreenOffsetContainer { get; private set; }
@@ -179,7 +179,7 @@ namespace osu.Game
}
private void updateBlockingOverlayFade() =>
- screenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint);
+ ScreenContainer.FadeColour(visibleBlockingOverlays.Any() ? OsuColour.Gray(0.5f) : Color4.White, 500, Easing.OutQuint);
public void AddBlockingOverlay(OverlayContainer overlay)
{
@@ -487,8 +487,8 @@ namespace osu.Game
// to ensure all the required data for presenting a replay are present.
ScoreInfo databasedScoreInfo = null;
- if (score.OnlineScoreID != null)
- databasedScoreInfo = ScoreManager.Query(s => s.OnlineScoreID == score.OnlineScoreID);
+ if (score.OnlineID > 0)
+ databasedScoreInfo = ScoreManager.Query(s => s.OnlineID == score.OnlineID);
databasedScoreInfo ??= ScoreManager.Query(s => s.Hash == score.Hash);
@@ -698,7 +698,7 @@ namespace osu.Game
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
- screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays)
+ ScreenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
@@ -801,7 +801,7 @@ namespace osu.Game
loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true);
loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true);
loadComponentSingleFile(wikiOverlay = new WikiOverlay(), overlayContent.Add, true);
- loadComponentSingleFile(skinEditor = new SkinEditorOverlay(screenContainer), overlayContent.Add, true);
+ loadComponentSingleFile(skinEditor = new SkinEditorOverlay(ScreenContainer), overlayContent.Add, true);
loadComponentSingleFile(new LoginOverlay
{
diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
index 2fcdc9402d..695661d5c9 100644
--- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
+++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
@@ -94,7 +94,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
topScoresContainer.Add(new DrawableTopScore(topScore));
- if (userScoreInfo != null && userScoreInfo.OnlineScoreID != topScore.OnlineScoreID)
+ if (userScoreInfo != null && userScoreInfo.OnlineID != topScore.OnlineID)
topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position));
}), TaskContinuationOptions.OnlyOnRanToCompletion);
});
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs
index fb464e1b41..562be0403e 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs
@@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
private const float performance_background_shear = 0.45f;
- protected readonly APIScoreInfo Score;
+ protected readonly APIScore Score;
[Resolved]
private OsuColour colours { get; set; }
@@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
[Resolved]
private OverlayColourProvider colourProvider { get; set; }
- public DrawableProfileScore(APIScoreInfo score)
+ public DrawableProfileScore(APIScore score)
{
Score = score;
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs
index e653be5cfa..78ae0a5634 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileWeightedScore.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
{
private readonly double weight;
- public DrawableProfileWeightedScore(APIScoreInfo score, double weight)
+ public DrawableProfileWeightedScore(APIScore score, double weight)
: base(score)
{
this.weight = weight;
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
index c3f10587a9..5532e35cc5 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
@@ -15,7 +15,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
- public class PaginatedScoreContainer : PaginatedProfileSubsection
+ public class PaginatedScoreContainer : PaginatedProfileSubsection
{
private readonly ScoreType type;
@@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
}
}
- protected override void OnItemsReceived(List items)
+ protected override void OnItemsReceived(List items)
{
if (VisiblePages == 0)
drawableItemIndex = 0;
@@ -59,12 +59,12 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
base.OnItemsReceived(items);
}
- protected override APIRequest> CreateRequest() =>
+ protected override APIRequest> CreateRequest() =>
new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
private int drawableItemIndex;
- protected override Drawable CreateDrawableItem(APIScoreInfo model)
+ protected override Drawable CreateDrawableItem(APIScore model)
{
switch (type)
{
diff --git a/osu.Game/Scoring/IScoreInfo.cs b/osu.Game/Scoring/IScoreInfo.cs
index 8b5b228632..b4ad183cd3 100644
--- a/osu.Game/Scoring/IScoreInfo.cs
+++ b/osu.Game/Scoring/IScoreInfo.cs
@@ -4,14 +4,14 @@
using System;
using osu.Game.Beatmaps;
using osu.Game.Database;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
+using osu.Game.Users;
namespace osu.Game.Scoring
{
public interface IScoreInfo : IHasOnlineID, IHasNamedFiles
{
- APIUser User { get; }
+ IUser User { get; }
long TotalScore { get; }
diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs
index f943422389..fefee370b9 100644
--- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs
+++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs
@@ -80,12 +80,9 @@ namespace osu.Game.Scoring.Legacy
byte[] compressedReplay = sr.ReadByteArray();
if (version >= 20140721)
- scoreInfo.OnlineScoreID = sr.ReadInt64();
+ scoreInfo.OnlineID = sr.ReadInt64();
else if (version >= 20121008)
- scoreInfo.OnlineScoreID = sr.ReadInt32();
-
- if (scoreInfo.OnlineScoreID <= 0)
- scoreInfo.OnlineScoreID = null;
+ scoreInfo.OnlineID = sr.ReadInt32();
if (compressedReplay?.Length > 0)
{
diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs
index 5dc88d7644..7acc7bd055 100644
--- a/osu.Game/Scoring/ScoreInfo.cs
+++ b/osu.Game/Scoring/ScoreInfo.cs
@@ -14,6 +14,7 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
+using osu.Game.Users;
using osu.Game.Utils;
namespace osu.Game.Scoring
@@ -136,7 +137,14 @@ namespace osu.Game.Scoring
[Column("Beatmap")]
public BeatmapInfo BeatmapInfo { get; set; }
- public long? OnlineScoreID { get; set; }
+ private long? onlineID;
+
+ [Column("OnlineScoreID")]
+ public long? OnlineID
+ {
+ get => onlineID;
+ set => onlineID = value > 0 ? value : null;
+ }
public DateTimeOffset Date { get; set; }
@@ -231,24 +239,18 @@ namespace osu.Game.Scoring
public bool Equals(ScoreInfo other)
{
- if (other == null)
- return false;
+ if (ReferenceEquals(this, other)) return true;
+ if (other == null) return false;
if (ID != 0 && other.ID != 0)
return ID == other.ID;
- if (OnlineScoreID.HasValue && other.OnlineScoreID.HasValue)
- return OnlineScoreID == other.OnlineScoreID;
-
- if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash))
- return Hash == other.Hash;
-
- return ReferenceEquals(this, other);
+ return false;
}
#region Implementation of IHasOnlineID
- public long OnlineID => OnlineScoreID ?? -1;
+ long IHasOnlineID.OnlineID => OnlineID ?? -1;
#endregion
@@ -256,6 +258,7 @@ namespace osu.Game.Scoring
IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo;
IRulesetInfo IScoreInfo.Ruleset => Ruleset;
+ IUser IScoreInfo.User => User;
bool IScoreInfo.HasReplay => Files.Any();
#endregion
diff --git a/osu.Game/Scoring/ScoreManager.cs b/osu.Game/Scoring/ScoreManager.cs
index e9cd44ae83..6de6b57066 100644
--- a/osu.Game/Scoring/ScoreManager.cs
+++ b/osu.Game/Scoring/ScoreManager.cs
@@ -71,7 +71,7 @@ namespace osu.Game.Scoring
return scores.Select((score, index) => (score, totalScore: totalScores[index]))
.OrderByDescending(g => g.totalScore)
- .ThenBy(g => g.score.OnlineScoreID)
+ .ThenBy(g => g.score.OnlineID)
.Select(g => g.score)
.ToArray();
}
diff --git a/osu.Game/Scoring/ScoreModelDownloader.cs b/osu.Game/Scoring/ScoreModelDownloader.cs
index 038a4bc351..514b7a57de 100644
--- a/osu.Game/Scoring/ScoreModelDownloader.cs
+++ b/osu.Game/Scoring/ScoreModelDownloader.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Database;
+using osu.Game.Extensions;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
@@ -17,6 +18,6 @@ namespace osu.Game.Scoring
protected override ArchiveDownloadRequest CreateDownloadRequest(IScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score);
public override ArchiveDownloadRequest GetExistingDownload(IScoreInfo model)
- => CurrentDownloads.Find(r => r.Model.OnlineID == model.OnlineID);
+ => CurrentDownloads.Find(r => r.Model.MatchesOnlineID(model));
}
}
diff --git a/osu.Game/Scoring/ScoreModelManager.cs b/osu.Game/Scoring/ScoreModelManager.cs
index 2cbd3aded7..44f0fe4fdf 100644
--- a/osu.Game/Scoring/ScoreModelManager.cs
+++ b/osu.Game/Scoring/ScoreModelManager.cs
@@ -66,6 +66,6 @@ namespace osu.Game.Scoring
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable items)
=> base.CheckLocalAvailability(model, items)
- || (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
+ || (model.OnlineID > 0 && items.Any(i => i.OnlineID == model.OnlineID));
}
}
diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs
index 4a922c45b9..452f033dcc 100644
--- a/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs
+++ b/osu.Game/Screens/Backgrounds/BackgroundScreenDefault.cs
@@ -48,16 +48,19 @@ namespace osu.Game.Screens.Backgrounds
AddInternal(seasonalBackgroundLoader);
- user.ValueChanged += _ => Next();
- skin.ValueChanged += _ => Next();
- mode.ValueChanged += _ => Next();
- beatmap.ValueChanged += _ => Next();
- introSequence.ValueChanged += _ => Next();
- seasonalBackgroundLoader.SeasonalBackgroundChanged += () => Next();
+ user.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired);
+ skin.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired);
+ mode.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired);
+ beatmap.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired);
+ introSequence.ValueChanged += _ => Scheduler.AddOnce(loadNextIfRequired);
+ seasonalBackgroundLoader.SeasonalBackgroundChanged += () => Scheduler.AddOnce(loadNextIfRequired);
currentDisplay = RNG.Next(0, background_count);
Next();
+
+ // helper function required for AddOnce usage.
+ void loadNextIfRequired() => Next();
}
private ScheduledDelegate nextTask;
@@ -67,7 +70,7 @@ namespace osu.Game.Screens.Backgrounds
/// Request loading the next background.
///
/// Whether a new background was queued for load. May return false if the current background is still valid.
- public bool Next()
+ public virtual bool Next()
{
var nextBackground = createBackground();
diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs
index 2a01a5b6b2..15d70e28b6 100644
--- a/osu.Game/Screens/Edit/EditorLoader.cs
+++ b/osu.Game/Screens/Edit/EditorLoader.cs
@@ -1,6 +1,7 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
@@ -9,6 +10,7 @@ using osu.Framework.Screens;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
+using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
@@ -53,6 +55,14 @@ namespace osu.Game.Screens.Edit
});
}
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ // will be restored via lease, see `DisallowExternalBeatmapRulesetChanges`.
+ Mods.Value = Array.Empty();
+ }
+
protected virtual Editor CreateEditor() => new Editor(this);
protected override void LogoArriving(OsuLogo logo, bool resuming)
diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs
index 02565c6ebe..238aa4059d 100644
--- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
+using osu.Framework.Development;
using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Game.Online.API;
@@ -107,6 +108,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
public void AddOrUpdateRoom(Room room)
{
+ Debug.Assert(ThreadSafety.IsUpdateThread);
Debug.Assert(room.RoomID.Value != null);
if (ignoredRooms.Contains(room.RoomID.Value.Value))
@@ -136,12 +138,16 @@ namespace osu.Game.Screens.OnlinePlay.Components
public void RemoveRoom(Room room)
{
+ Debug.Assert(ThreadSafety.IsUpdateThread);
+
rooms.Remove(room);
notifyRoomsUpdated();
}
public void ClearRooms()
{
+ Debug.Assert(ThreadSafety.IsUpdateThread);
+
rooms.Clear();
notifyRoomsUpdated();
}
diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
index 8042f7d772..e1f7ea5e92 100644
--- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
+++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
@@ -24,6 +25,7 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online;
using osu.Game.Online.Chat;
+using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
using osu.Game.Overlays.BeatmapSet;
using osu.Game.Rulesets;
@@ -90,6 +92,10 @@ namespace osu.Game.Screens.OnlinePlay
[Resolved]
private UserLookupCache userLookupCache { get; set; }
+ [CanBeNull]
+ [Resolved(CanBeNull = true)]
+ private MultiplayerClient multiplayerClient { get; set; }
+
[Resolved]
private BeatmapLookupCache beatmapLookupCache { get; set; }
@@ -157,7 +163,15 @@ namespace osu.Game.Screens.OnlinePlay
if (Item.Beatmap.Value == null)
{
- var foundBeatmap = await beatmapLookupCache.GetBeatmapAsync(Item.BeatmapID).ConfigureAwait(false);
+ IBeatmapInfo foundBeatmap;
+
+ if (multiplayerClient != null)
+ // This call can eventually go away (and use the else case below).
+ // Currently required only due to the method being overridden to provide special behaviour in tests.
+ foundBeatmap = await multiplayerClient.GetAPIBeatmap(Item.BeatmapID).ConfigureAwait(false);
+ else
+ foundBeatmap = await beatmapLookupCache.GetBeatmapAsync(Item.BeatmapID).ConfigureAwait(false);
+
Schedule(() => Item.Beatmap.Value = foundBeatmap);
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
index 184ac2c563..a560d85b7d 100644
--- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
@@ -28,7 +28,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
public abstract class RoomSubScreen : OnlinePlaySubScreen, IPreviewTrackOwner
{
[Cached(typeof(IBindable))]
- protected readonly Bindable SelectedItem = new Bindable();
+ public readonly Bindable SelectedItem = new Bindable();
public override bool? AllowTrackAdjustments => true;
@@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
protected OnlinePlayScreen ParentScreen { get; private set; }
[Cached]
- private OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker { get; set; }
+ private readonly OnlinePlayBeatmapAvailabilityTracker beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
protected IBindable BeatmapAvailability => beatmapAvailabilityTracker.Availability;
@@ -90,11 +90,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
Padding = new MarginPadding { Top = Header.HEIGHT };
- beatmapAvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
- {
- SelectedItem = { BindTarget = SelectedItem }
- };
-
RoomId.BindTo(room.RoomID);
}
@@ -247,10 +242,10 @@ namespace osu.Game.Screens.OnlinePlay.Match
}, true);
SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged));
-
- beatmapManager.ItemUpdated += beatmapUpdated;
-
UserMods.BindValueChanged(_ => Scheduler.AddOnce(UpdateMods));
+
+ beatmapAvailabilityTracker.SelectedItem.BindTo(SelectedItem);
+ beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateWorkingBeatmap());
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@@ -374,8 +369,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
}
}
- private void beatmapUpdated(BeatmapSetInfo set) => Schedule(updateWorkingBeatmap);
-
private void updateWorkingBeatmap()
{
var beatmap = SelectedItem.Value?.Beatmap.Value;
@@ -443,14 +436,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
/// The room to change the settings of.
protected abstract RoomSettingsOverlay CreateRoomSettingsOverlay(Room room);
- protected override void Dispose(bool isDisposing)
- {
- base.Dispose(isDisposing);
-
- if (beatmapManager != null)
- beatmapManager.ItemUpdated -= beatmapUpdated;
- }
-
public class UserModSelectButton : PurpleTriangleButton
{
}
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs
index 874113d859..06959d942f 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs
@@ -63,6 +63,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
sampleUnready = audio.Samples.Get(@"Multiplayer/player-unready");
}
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ SelectedItem.BindValueChanged(_ => updateState());
+ }
+
protected override void OnRoomUpdated()
{
base.OnRoomUpdated();
@@ -104,7 +111,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
bool enableButton =
Room?.State == MultiplayerRoomState.Open
- && Client.CurrentMatchPlayingItem.Value?.Expired == false
+ && SelectedItem.Value?.ID == Room.Settings.PlaylistItemId
+ && !Room.Playlist.Single(i => i.ID == Room.Settings.PlaylistItemId).Expired
&& !operationInProgress.Value;
// When the local user is the host and spectating the match, the "start match" state should be enabled if any users are ready.
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
index 8d3686dd6d..073497e1ce 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
@@ -25,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
[Resolved]
private MultiplayerClient client { get; set; }
- private readonly PlaylistItem itemToEdit;
+ private readonly long? itemToEdit;
private LoadingLayer loadingLayer;
@@ -36,7 +36,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
/// The item to be edited. May be null, in which case a new item will be added to the playlist.
/// An optional initial beatmap selection to perform.
/// An optional initial ruleset selection to perform.
- public MultiplayerMatchSongSelect(Room room, PlaylistItem itemToEdit = null, WorkingBeatmap beatmap = null, RulesetInfo ruleset = null)
+ public MultiplayerMatchSongSelect(Room room, long? itemToEdit = null, WorkingBeatmap beatmap = null, RulesetInfo ruleset = null)
: base(room)
{
this.itemToEdit = itemToEdit;
@@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
var multiplayerItem = new MultiplayerPlaylistItem
{
- ID = itemToEdit?.ID ?? 0,
+ ID = itemToEdit ?? 0,
BeatmapID = item.BeatmapID,
BeatmapChecksum = item.Beatmap.Value.MD5Hash,
RulesetID = item.RulesetID,
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
index 946c749db3..6895608c8e 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
@@ -67,8 +68,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
base.LoadComplete();
- SelectedItem.BindTo(client.CurrentMatchPlayingItem);
-
BeatmapAvailability.BindValueChanged(updateBeatmapAvailability, true);
UserMods.BindValueChanged(onUserModsChanged);
@@ -147,7 +146,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
new MultiplayerPlaylist
{
RelativeSizeAxes = Axes.Both,
- RequestEdit = OpenSongSelection
+ RequestEdit = item => OpenSongSelection(item.ID)
}
},
new[]
@@ -224,7 +223,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
/// Opens the song selection screen to add or edit an item.
///
/// An optional playlist item to edit. If null, a new item will be added instead.
- internal void OpenSongSelection([CanBeNull] PlaylistItem itemToEdit = null)
+ internal void OpenSongSelection(long? itemToEdit = null)
{
if (!this.IsCurrentScreen())
return;
@@ -327,10 +326,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
if (client.LocalUser?.State == MultiplayerUserState.Ready)
client.ChangeState(MultiplayerUserState.Idle);
}
- else
+ else if (client.LocalUser?.State == MultiplayerUserState.Spectating
+ && (client.Room?.State == MultiplayerRoomState.WaitingForLoad || client.Room?.State == MultiplayerRoomState.Playing))
{
- if (client.LocalUser?.State == MultiplayerUserState.Spectating && (client.Room?.State == MultiplayerRoomState.WaitingForLoad || client.Room?.State == MultiplayerRoomState.Playing))
- onLoadRequested();
+ onLoadRequested();
}
}
@@ -389,11 +388,50 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return;
}
+ updateCurrentItem();
+
addItemButton.Alpha = client.IsHost || Room.QueueMode.Value != QueueMode.HostOnly ? 1 : 0;
Scheduler.AddOnce(UpdateMods);
}
+ private void updateCurrentItem()
+ {
+ Debug.Assert(client.Room != null);
+
+ var expectedSelectedItem = Room.Playlist.SingleOrDefault(i => i.ID == client.Room.Settings.PlaylistItemId);
+
+ if (expectedSelectedItem == null)
+ return;
+
+ // There's no reason to renew the selected item if its content hasn't changed.
+ if (SelectedItem.Value?.Equals(expectedSelectedItem) == true && expectedSelectedItem.Beatmap.Value != null)
+ return;
+
+ // Clear the selected item while the lookup is performed, so components like the ready button can enter their disabled states.
+ SelectedItem.Value = null;
+
+ if (expectedSelectedItem.Beatmap.Value == null)
+ {
+ Task.Run(async () =>
+ {
+ var beatmap = await client.GetAPIBeatmap(expectedSelectedItem.BeatmapID).ConfigureAwait(false);
+
+ Schedule(() =>
+ {
+ expectedSelectedItem.Beatmap.Value = beatmap;
+
+ if (Room.Playlist.SingleOrDefault(i => i.ID == client.Room?.Settings.PlaylistItemId)?.Equals(expectedSelectedItem) == true)
+ applyCurrentItem();
+ });
+ });
+ }
+ else
+ applyCurrentItem();
+
+ void applyCurrentItem() => SelectedItem.Value = expectedSelectedItem;
+ }
+
private void handleRoomLost() => Schedule(() =>
{
if (this.IsCurrentScreen())
@@ -446,6 +484,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
if (!this.IsCurrentScreen())
return;
+ if (client.Room == null)
+ return;
+
if (!client.IsHost)
{
// todo: should handle this when the request queue is implemented.
@@ -454,7 +495,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return;
}
- this.Push(new MultiplayerMatchSongSelect(Room, SelectedItem.Value, beatmap, ruleset));
+ this.Push(new MultiplayerMatchSongSelect(Room, client.Room.Settings.PlaylistItemId, beatmap, ruleset));
}
protected override void Dispose(bool isDisposing)
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs
index aed3635cbc..1e6722d51e 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs
@@ -87,6 +87,13 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{
var allScores = new List { userScore };
+ // Other scores could have arrived between score submission and entering the results screen. Ensure the local player score position is up to date.
+ if (Score != null)
+ {
+ Score.Position = userScore.Position;
+ ScorePanelList.GetPanelForScore(Score).ScorePosition.Value = userScore.Position;
+ }
+
if (userScore.ScoresAround?.Higher != null)
{
allScores.AddRange(userScore.ScoresAround.Higher.Scores);
@@ -186,12 +193,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
Schedule(() =>
{
// Prefer selecting the local user's score, or otherwise default to the first visible score.
- SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.Id == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
+ SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.OnlineID == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
});
}
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
- callback.Invoke(scoreInfos.Where(s => s.OnlineScoreID != Score?.OnlineScoreID));
+ callback.Invoke(scoreInfos.Where(s => s.OnlineID != Score?.OnlineID));
hideLoadingSpinners(pivot);
}));
diff --git a/osu.Game/Screens/Play/FailAnimation.cs b/osu.Game/Screens/Play/FailAnimation.cs
index 193e1e4129..cfbfdc9966 100644
--- a/osu.Game/Screens/Play/FailAnimation.cs
+++ b/osu.Game/Screens/Play/FailAnimation.cs
@@ -6,6 +6,7 @@ using osu.Framework.Bindables;
using osu.Game.Rulesets.UI;
using System;
using System.Collections.Generic;
+using JetBrains.Annotations;
using ManagedBass.Fx;
using osu.Framework.Allocation;
using osu.Framework.Audio.Sample;
@@ -18,6 +19,7 @@ using osu.Framework.Utils;
using osu.Game.Audio.Effects;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
+using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osuTK;
using osuTK.Graphics;
@@ -58,6 +60,12 @@ namespace osu.Game.Screens.Play
RelativeSizeAxes = Axes.Both,
};
+ ///
+ /// The player screen background, used to adjust appearance on failing.
+ ///
+ [CanBeNull]
+ public BackgroundScreen Background { private get; set; }
+
public FailAnimation(DrawableRuleset drawableRuleset)
{
this.drawableRuleset = drawableRuleset;
@@ -136,6 +144,9 @@ namespace osu.Game.Screens.Play
Content.ScaleTo(0.85f, duration, Easing.OutQuart);
Content.RotateTo(1, duration, Easing.OutQuart);
Content.FadeColour(Color4.Gray, duration);
+
+ // Will be restored by `ApplyToBackground` logic in `SongSelect`.
+ Background?.FadeColour(OsuColour.Gray(0.3f), 60);
}
public void RemoveFilters(bool resetTrackFrequency = true)
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index a0e9428cff..745e1f9e7c 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -921,6 +921,8 @@ namespace osu.Game.Screens.Play
b.IsBreakTime.BindTo(breakTracker.IsBreakTime);
b.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
+
+ failAnimationLayer.Background = b;
});
HUDOverlay.IsBreakTime.BindTo(breakTracker.IsBreakTime);
@@ -1031,13 +1033,13 @@ namespace osu.Game.Screens.Play
//
// Until we better define the server-side logic behind this, let's not store the online ID to avoid potential unique constraint
// conflicts across various systems (ie. solo and multiplayer).
- long? onlineScoreId = score.ScoreInfo.OnlineScoreID;
- score.ScoreInfo.OnlineScoreID = null;
+ long? onlineScoreId = score.ScoreInfo.OnlineID;
+ score.ScoreInfo.OnlineID = -1;
await scoreManager.Import(score.ScoreInfo, replayReader).ConfigureAwait(false);
// ... And restore the online ID for other processes to handle correctly (e.g. de-duplication for the results screen).
- score.ScoreInfo.OnlineScoreID = onlineScoreId;
+ score.ScoreInfo.OnlineID = onlineScoreId;
}
///
diff --git a/osu.Game/Screens/Play/SpectatorPlayer.cs b/osu.Game/Screens/Play/SpectatorPlayer.cs
index f6a89e7fa9..d42643c416 100644
--- a/osu.Game/Screens/Play/SpectatorPlayer.cs
+++ b/osu.Game/Screens/Play/SpectatorPlayer.cs
@@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play
private void userSentFrames(int userId, FrameDataBundle bundle)
{
- if (userId != score.ScoreInfo.User.Id)
+ if (userId != score.ScoreInfo.User.OnlineID)
return;
if (!LoadedBeatmapSuccessfully)
diff --git a/osu.Game/Screens/Play/SubmittingPlayer.cs b/osu.Game/Screens/Play/SubmittingPlayer.cs
index c07cfa9c4d..c613167908 100644
--- a/osu.Game/Screens/Play/SubmittingPlayer.cs
+++ b/osu.Game/Screens/Play/SubmittingPlayer.cs
@@ -156,7 +156,7 @@ namespace osu.Game.Screens.Play
request.Success += s =>
{
- score.ScoreInfo.OnlineScoreID = s.ID;
+ score.ScoreInfo.OnlineID = s.ID;
score.ScoreInfo.Position = s.Position;
scoreSubmissionSource.SetResult(true);
diff --git a/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs b/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs
index 0935ee7fb2..beff509dc6 100644
--- a/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs
+++ b/osu.Game/Screens/Ranking/Contracted/ContractedPanelTopContent.cs
@@ -2,36 +2,42 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
+using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
-using osu.Game.Scoring;
namespace osu.Game.Screens.Ranking.Contracted
{
public class ContractedPanelTopContent : CompositeDrawable
{
- private readonly ScoreInfo score;
+ public readonly Bindable ScorePosition = new Bindable();
- public ContractedPanelTopContent(ScoreInfo score)
+ private OsuSpriteText text;
+
+ public ContractedPanelTopContent()
{
- this.score = score;
-
RelativeSizeAxes = Axes.Both;
}
[BackgroundDependencyLoader]
private void load()
{
- InternalChild = new OsuSpriteText
+ InternalChild = text = new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Y = 6,
- Text = score.Position != null ? $"#{score.Position}" : string.Empty,
Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold)
};
}
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ ScorePosition.BindValueChanged(pos => text.Text = pos.NewValue != null ? $"#{pos.NewValue}" : string.Empty, true);
+ }
}
}
diff --git a/osu.Game/Screens/Ranking/ScorePanel.cs b/osu.Game/Screens/Ranking/ScorePanel.cs
index 6ddecf8297..bc6eb9e366 100644
--- a/osu.Game/Screens/Ranking/ScorePanel.cs
+++ b/osu.Game/Screens/Ranking/ScorePanel.cs
@@ -4,6 +4,7 @@
using System;
using osu.Framework;
using osu.Framework.Allocation;
+using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
@@ -78,6 +79,11 @@ namespace osu.Game.Screens.Ranking
public event Action StateChanged;
+ ///
+ /// The position of the score in the rankings.
+ ///
+ public readonly Bindable ScorePosition = new Bindable();
+
///
/// An action to be invoked if this is clicked while in an expanded state.
///
@@ -103,6 +109,8 @@ namespace osu.Game.Screens.Ranking
{
Score = score;
displayWithFlair = isNewLocalScore;
+
+ ScorePosition.Value = score.Position;
}
[BackgroundDependencyLoader]
@@ -211,8 +219,8 @@ namespace osu.Game.Screens.Ranking
topLayerBackground.FadeColour(expanded_top_layer_colour, RESIZE_DURATION, Easing.OutQuint);
middleLayerBackground.FadeColour(expanded_middle_layer_colour, RESIZE_DURATION, Easing.OutQuint);
- topLayerContentContainer.Add(topLayerContent = new ExpandedPanelTopContent(Score.User).With(d => d.Alpha = 0));
- middleLayerContentContainer.Add(middleLayerContent = new ExpandedPanelMiddleContent(Score, displayWithFlair).With(d => d.Alpha = 0));
+ topLayerContentContainer.Add(topLayerContent = new ExpandedPanelTopContent(Score.User) { Alpha = 0 });
+ middleLayerContentContainer.Add(middleLayerContent = new ExpandedPanelMiddleContent(Score, displayWithFlair) { Alpha = 0 });
// only the first expanded display should happen with flair.
displayWithFlair = false;
@@ -224,8 +232,13 @@ namespace osu.Game.Screens.Ranking
topLayerBackground.FadeColour(contracted_top_layer_colour, RESIZE_DURATION, Easing.OutQuint);
middleLayerBackground.FadeColour(contracted_middle_layer_colour, RESIZE_DURATION, Easing.OutQuint);
- topLayerContentContainer.Add(topLayerContent = new ContractedPanelTopContent(Score).With(d => d.Alpha = 0));
- middleLayerContentContainer.Add(middleLayerContent = new ContractedPanelMiddleContent(Score).With(d => d.Alpha = 0));
+ topLayerContentContainer.Add(topLayerContent = new ContractedPanelTopContent
+ {
+ ScorePosition = { BindTarget = ScorePosition },
+ Alpha = 0
+ });
+
+ middleLayerContentContainer.Add(middleLayerContent = new ContractedPanelMiddleContent(Score) { Alpha = 0 });
break;
}
diff --git a/osu.Game/Screens/Ranking/ScorePanelList.cs b/osu.Game/Screens/Ranking/ScorePanelList.cs
index 22be91b974..f3de48dcf0 100644
--- a/osu.Game/Screens/Ranking/ScorePanelList.cs
+++ b/osu.Game/Screens/Ranking/ScorePanelList.cs
@@ -341,7 +341,7 @@ namespace osu.Game.Screens.Ranking
private IEnumerable applySorting(IEnumerable drawables) => drawables.OfType()
.OrderByDescending(GetLayoutPosition)
- .ThenBy(s => s.Panel.Score.OnlineScoreID);
+ .ThenBy(s => s.Panel.Score.OnlineID);
}
private class Scroll : OsuScrollContainer
diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs
index 929bda6508..afebc728b4 100644
--- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs
+++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs
@@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking
return null;
getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset);
- getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo)));
+ getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo)));
return getScoreRequest;
}
diff --git a/osu.Game/Storyboards/StoryboardSprite.cs b/osu.Game/Storyboards/StoryboardSprite.cs
index 6fb2f5994b..ebd1a941a8 100644
--- a/osu.Game/Storyboards/StoryboardSprite.cs
+++ b/osu.Game/Storyboards/StoryboardSprite.cs
@@ -33,10 +33,8 @@ namespace osu.Game.Storyboards
foreach (var l in loops)
{
- if (!(l.EarliestDisplayedTime is double lEarliest))
- continue;
-
- earliestStartTime = Math.Min(earliestStartTime, lEarliest);
+ if (l.EarliestDisplayedTime is double loopEarliestDisplayTime)
+ earliestStartTime = Math.Min(earliestStartTime, l.LoopStartTime + loopEarliestDisplayTime);
}
if (earliestStartTime < double.MaxValue)
diff --git a/osu.Game/Tests/TestScoreInfo.cs b/osu.Game/Tests/TestScoreInfo.cs
deleted file mode 100644
index a53cb0ae78..0000000000
--- a/osu.Game/Tests/TestScoreInfo.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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 System.Linq;
-using osu.Game.Online.API.Requests.Responses;
-using osu.Game.Rulesets;
-using osu.Game.Rulesets.Mods;
-using osu.Game.Rulesets.Scoring;
-using osu.Game.Scoring;
-using osu.Game.Tests.Beatmaps;
-
-namespace osu.Game.Tests
-{
- public class TestScoreInfo : ScoreInfo
- {
- public TestScoreInfo(RulesetInfo ruleset, bool excessMods = false)
- {
- User = new APIUser
- {
- Id = 2,
- Username = "peppy",
- CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
- };
-
- BeatmapInfo = new TestBeatmap(ruleset).BeatmapInfo;
- Ruleset = ruleset;
- RulesetID = ruleset.ID ?? 0;
-
- Mods = excessMods
- ? ruleset.CreateInstance().CreateAllMods().ToArray()
- : new Mod[] { new TestModHardRock(), new TestModDoubleTime() };
-
- TotalScore = 2845370;
- Accuracy = 0.95;
- MaxCombo = 999;
- Rank = ScoreRank.S;
- Date = DateTimeOffset.Now;
-
- Statistics[HitResult.Miss] = 1;
- Statistics[HitResult.Meh] = 50;
- Statistics[HitResult.Ok] = 100;
- Statistics[HitResult.Good] = 200;
- Statistics[HitResult.Great] = 300;
- Statistics[HitResult.Perfect] = 320;
- Statistics[HitResult.SmallTickHit] = 50;
- Statistics[HitResult.SmallTickMiss] = 25;
- Statistics[HitResult.LargeTickHit] = 100;
- Statistics[HitResult.LargeTickMiss] = 50;
- Statistics[HitResult.SmallBonus] = 10;
- Statistics[HitResult.SmallBonus] = 50;
-
- Position = 1;
- }
-
- private class TestModHardRock : ModHardRock
- {
- public override double ScoreMultiplier => 1;
- }
-
- private class TestModDoubleTime : ModDoubleTime
- {
- public override double ScoreMultiplier => 1;
- }
- }
-}
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
index d22f0415e6..d20d6b1d37 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
@@ -376,7 +376,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public override Task RemovePlaylistItem(long playlistItemId) => RemoveUserPlaylistItem(api.LocalUser.Value.OnlineID, playlistItemId);
- protected override Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
+ public override Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
{
IBeatmapSetInfo? set = roomManager.ServerSideRooms.SelectMany(r => r.Playlist)
.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index adb25f46fe..46064e320b 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -20,7 +20,7 @@
-
+
@@ -31,15 +31,15 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
diff --git a/osu.iOS.props b/osu.iOS.props
index db5d9af865..fdb63a19d3 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -60,7 +60,7 @@
-
+
@@ -83,7 +83,7 @@
-
+