diff --git a/osu.Android.props b/osu.Android.props
index eab2be1b72..24a0d20874 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs
index efd5868504..5b7a460079 100644
--- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs
+++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs
@@ -10,10 +10,10 @@ namespace osu.Game.Rulesets.Mania.Difficulty
public class ManiaDifficultyAttributes : DifficultyAttributes
{
///
- /// The perceived hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc).
+ /// The hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc).
///
///
- /// Rate-adjusting mods don't directly affect the hit window, but have a perceived effect as a result of adjusting audio timing.
+ /// Rate-adjusting mods do not affect the hit window at all in osu-stable.
///
[JsonProperty("great_hit_window")]
public double GreatHitWindow { get; set; }
diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs
index 1f82eb7ccd..b17aa7fc4d 100644
--- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs
@@ -48,7 +48,9 @@ namespace osu.Game.Rulesets.Mania.Difficulty
{
StarRating = skills[0].DifficultyValue() * star_scaling_factor,
Mods = mods,
- GreatHitWindow = Math.Ceiling(getHitWindow300(mods) / clockRate),
+ // In osu-stable mania, rate-adjustment mods don't affect the hit window.
+ // This is done the way it is to introduce fractional differences in order to match osu-stable for the time being.
+ GreatHitWindow = Math.Ceiling((int)(getHitWindow300(mods) * clockRate) / clockRate),
ScoreMultiplier = getScoreMultiplier(mods),
MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1),
};
@@ -108,7 +110,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
}
}
- private int getHitWindow300(Mod[] mods)
+ private double getHitWindow300(Mod[] mods)
{
if (isForCurrentRuleset)
{
@@ -121,19 +123,14 @@ namespace osu.Game.Rulesets.Mania.Difficulty
return applyModAdjustments(47, mods);
- static int applyModAdjustments(double value, Mod[] mods)
+ static double applyModAdjustments(double value, Mod[] mods)
{
if (mods.Any(m => m is ManiaModHardRock))
value /= 1.4;
else if (mods.Any(m => m is ManiaModEasy))
value *= 1.4;
- if (mods.Any(m => m is ManiaModDoubleTime))
- value *= 1.5;
- else if (mods.Any(m => m is ManiaModHalfTime))
- value *= 0.75;
-
- return (int)value;
+ return value;
}
}
diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs
index 8a8c41bb8a..722cb55036 100644
--- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs
@@ -43,14 +43,11 @@ namespace osu.Game.Rulesets.Mania.Difficulty
countMeh = Score.Statistics.GetValueOrDefault(HitResult.Meh);
countMiss = Score.Statistics.GetValueOrDefault(HitResult.Miss);
- IEnumerable scoreIncreaseMods = Ruleset.GetModsFor(ModType.DifficultyIncrease);
-
- double scoreMultiplier = 1.0;
- foreach (var m in mods.Where(m => !scoreIncreaseMods.Contains(m)))
- scoreMultiplier *= m.ScoreMultiplier;
-
- // Scale score up, so it's comparable to other keymods
- scaledScore *= 1.0 / scoreMultiplier;
+ if (Attributes.ScoreMultiplier > 0)
+ {
+ // Scale score up, so it's comparable to other keymods
+ scaledScore *= 1.0 / Attributes.ScoreMultiplier;
+ }
// Arbitrary initial value for scaling pp in order to standardize distributions across game modes.
// The specific number has no intrinsic meaning and can be adjusted as needed.
diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs
index 952fc7ddd6..fdacc75c92 100644
--- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs
+++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyStageBackground.cs
@@ -98,8 +98,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
float rightLineWidth = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.RightLineWidth, columnIndex)?.Value ?? 1;
bool hasLeftLine = leftLineWidth > 0;
- bool hasRightLine = rightLineWidth > 0 && skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value >= 2.4m
- || isLastColumn;
+ bool hasRightLine = (rightLineWidth > 0 && skin.GetConfig(SkinConfiguration.LegacySetting.Version)?.Value >= 2.4m) || isLastColumn;
Color4 lineColour = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.ColumnLineColour, columnIndex)?.Value ?? Color4.White;
Color4 backgroundColour = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour, columnIndex)?.Value ?? Color4.Black;
diff --git a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
index c4bffbc0ab..2521d570f2 100644
--- a/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
+++ b/osu.Game.Tests/Online/TestSceneOnlinePlayBeatmapAvailabilityTracker.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
@@ -12,6 +13,7 @@ using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
+using osu.Framework.Graphics;
using osu.Framework.IO.Stores;
using osu.Framework.Platform;
using osu.Framework.Testing;
@@ -21,6 +23,8 @@ using osu.Game.Database;
using osu.Game.IO;
using osu.Game.IO.Archives;
using osu.Game.Online.API;
+using osu.Game.Online.API.Requests;
+using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Tests.Resources;
@@ -53,6 +57,25 @@ namespace osu.Game.Tests.Online
[SetUp]
public void SetUp() => Schedule(() =>
{
+ ((DummyAPIAccess)API).HandleRequest = req =>
+ {
+ switch (req)
+ {
+ case GetBeatmapsRequest beatmapsReq:
+ var beatmap = CreateAPIBeatmap();
+ beatmap.OnlineID = testBeatmapInfo.OnlineID;
+ beatmap.OnlineBeatmapSetID = testBeatmapSet.OnlineID;
+ beatmap.Checksum = testBeatmapInfo.MD5Hash;
+ beatmap.BeatmapSet!.OnlineID = testBeatmapSet.OnlineID;
+
+ beatmapsReq.TriggerSuccess(new GetBeatmapsResponse { Beatmaps = new List { beatmap } });
+ return true;
+
+ default:
+ return false;
+ }
+ };
+
beatmaps.AllowImport = new TaskCompletionSource();
testBeatmapFile = TestResources.GetQuickTestBeatmapForImport();
@@ -63,18 +86,35 @@ namespace osu.Game.Tests.Online
Realm.Write(r => r.RemoveAll());
Realm.Write(r => r.RemoveAll());
- selectedItem.Value = new PlaylistItem
+ selectedItem.Value = new PlaylistItem(testBeatmapInfo)
{
- Beatmap = { Value = testBeatmapInfo },
RulesetID = testBeatmapInfo.Ruleset.OnlineID,
};
- Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
- {
- SelectedItem = { BindTarget = selectedItem, }
- };
+ recreateChildren();
});
+ private void recreateChildren()
+ {
+ var beatmapLookupCache = new BeatmapLookupCache();
+
+ Child = new DependencyProvidingContainer
+ {
+ CachedDependencies = new[]
+ {
+ (typeof(BeatmapLookupCache), (object)beatmapLookupCache)
+ },
+ Children = new Drawable[]
+ {
+ beatmapLookupCache,
+ availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
+ {
+ SelectedItem = { BindTarget = selectedItem, }
+ }
+ }
+ };
+ }
+
[Test]
public void TestBeatmapDownloadingFlow()
{
@@ -123,10 +163,7 @@ namespace osu.Game.Tests.Online
});
addAvailabilityCheckStep("state not downloaded", BeatmapAvailability.NotDownloaded);
- AddStep("recreate tracker", () => Child = availabilityTracker = new OnlinePlayBeatmapAvailabilityTracker
- {
- SelectedItem = { BindTarget = selectedItem }
- });
+ AddStep("recreate tracker", recreateChildren);
addAvailabilityCheckStep("state not downloaded as well", BeatmapAvailability.NotDownloaded);
AddStep("reimport original beatmap", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely());
@@ -167,7 +204,8 @@ namespace osu.Game.Tests.Online
public Live CurrentImport { get; private set; }
- public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore resources, GameHost host = null, WorkingBeatmap defaultBeatmap = null)
+ public TestBeatmapManager(Storage storage, RealmAccess realm, RulesetStore rulesets, IAPIProvider api, [NotNull] AudioManager audioManager, IResourceStore resources,
+ GameHost host = null, WorkingBeatmap defaultBeatmap = null)
: base(storage, realm, rulesets, api, audioManager, resources, host, defaultBeatmap)
{
}
diff --git a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
index d33081662d..9e7ea02101 100644
--- a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
+++ b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
@@ -3,6 +3,7 @@
using System;
using NUnit.Framework;
+using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
namespace osu.Game.Tests.OnlinePlay
@@ -29,9 +30,9 @@ namespace osu.Game.Tests.OnlinePlay
{
var items = new[]
{
- new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1 },
- new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2 },
- new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, PlaylistOrder = 1 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, PlaylistOrder = 2 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1003 }) { ID = 3, PlaylistOrder = 3 },
};
Assert.Multiple(() =>
@@ -47,9 +48,9 @@ namespace osu.Game.Tests.OnlinePlay
{
var items = new[]
{
- new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2 },
- new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1 },
- new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, PlaylistOrder = 2 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, PlaylistOrder = 1 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1003 }) { ID = 3, PlaylistOrder = 3 },
};
Assert.Multiple(() =>
@@ -65,9 +66,9 @@ namespace osu.Game.Tests.OnlinePlay
{
var items = new[]
{
- new PlaylistItem { ID = 1, BeatmapID = 1001, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
- new PlaylistItem { ID = 2, BeatmapID = 1002, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
- new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1003 }) { ID = 3, PlaylistOrder = 3 },
};
Assert.Multiple(() =>
@@ -83,9 +84,9 @@ namespace osu.Game.Tests.OnlinePlay
{
var items = new[]
{
- new PlaylistItem { ID = 1, BeatmapID = 1001, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
- new PlaylistItem { ID = 2, BeatmapID = 1002, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
- new PlaylistItem { ID = 3, BeatmapID = 1002, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 57, 0, TimeSpan.Zero) },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1001 }) { ID = 1, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 55, 0, TimeSpan.Zero) },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 2, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 53, 0, TimeSpan.Zero) },
+ new PlaylistItem(new APIBeatmap { OnlineID = 1002 }) { ID = 3, Expired = true, PlayedAt = new DateTimeOffset(2021, 12, 21, 7, 57, 0, TimeSpan.Zero) },
};
Assert.Multiple(() =>
diff --git a/osu.Game.Tests/Utils/NamingUtilsTest.cs b/osu.Game.Tests/Utils/NamingUtilsTest.cs
new file mode 100644
index 0000000000..62e688db90
--- /dev/null
+++ b/osu.Game.Tests/Utils/NamingUtilsTest.cs
@@ -0,0 +1,132 @@
+// 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.Game.Utils;
+
+namespace osu.Game.Tests.Utils
+{
+ [TestFixture]
+ public class NamingUtilsTest
+ {
+ [Test]
+ public void TestEmptySet()
+ {
+ string nextBestName = NamingUtils.GetNextBestName(Enumerable.Empty(), "New Difficulty");
+
+ Assert.AreEqual("New Difficulty", nextBestName);
+ }
+
+ [Test]
+ public void TestNotTaken()
+ {
+ string[] existingNames =
+ {
+ "Something",
+ "Entirely",
+ "Different"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty", nextBestName);
+ }
+
+ [Test]
+ public void TestNotTakenButClose()
+ {
+ string[] existingNames =
+ {
+ "New Difficulty(1)",
+ "New Difficulty (abcd)",
+ "New Difficulty but not really"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty", nextBestName);
+ }
+
+ [Test]
+ public void TestAlreadyTaken()
+ {
+ string[] existingNames =
+ {
+ "New Difficulty"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty (1)", nextBestName);
+ }
+
+ [Test]
+ public void TestAlreadyTakenWithDifferentCase()
+ {
+ string[] existingNames =
+ {
+ "new difficulty"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty (1)", nextBestName);
+ }
+
+ [Test]
+ public void TestAlreadyTakenWithBrackets()
+ {
+ string[] existingNames =
+ {
+ "new difficulty (copy)"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty (copy)");
+
+ Assert.AreEqual("New Difficulty (copy) (1)", nextBestName);
+ }
+
+ [Test]
+ public void TestMultipleAlreadyTaken()
+ {
+ string[] existingNames =
+ {
+ "New Difficulty",
+ "New difficulty (1)",
+ "new Difficulty (2)",
+ "New DIFFICULTY (3)"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty (4)", nextBestName);
+ }
+
+ [Test]
+ public void TestEvenMoreAlreadyTaken()
+ {
+ string[] existingNames = Enumerable.Range(1, 30).Select(i => $"New Difficulty ({i})").Append("New Difficulty").ToArray();
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty (31)", nextBestName);
+ }
+
+ [Test]
+ public void TestMultipleAlreadyTakenWithGaps()
+ {
+ string[] existingNames =
+ {
+ "New Difficulty",
+ "New Difficulty (1)",
+ "New Difficulty (4)",
+ "New Difficulty (9)"
+ };
+
+ string nextBestName = NamingUtils.GetNextBestName(existingNames, "New Difficulty");
+
+ Assert.AreEqual("New Difficulty (2)", nextBestName);
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs
index 0a2f622da1..ecd4035edd 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs
@@ -269,11 +269,12 @@ namespace osu.Game.Tests.Visual.Editing
}
[Test]
- public void TestCreateNewBeatmapFailsWithBlankNamedDifficulties()
+ public void TestCreateMultipleNewDifficultiesSucceeds()
{
Guid setId = Guid.Empty;
AddStep("retrieve set ID", () => setId = EditorBeatmap.BeatmapInfo.BeatmapSet!.ID);
+ AddStep("set difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = "New Difficulty");
AddStep("save beatmap", () => Editor.Save());
AddAssert("new beatmap persisted", () =>
{
@@ -282,15 +283,24 @@ namespace osu.Game.Tests.Visual.Editing
});
AddStep("try to create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
- AddAssert("beatmap set unchanged", () =>
+ AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
+ AddStep("confirm creation with no objects", () => DialogOverlay.CurrentDialog.PerformOkAction());
+
+ AddUntilStep("wait for created", () =>
+ {
+ string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName;
+ return difficultyName != null && difficultyName != "New Difficulty";
+ });
+ AddAssert("new difficulty has correct name", () => EditorBeatmap.BeatmapInfo.DifficultyName == "New Difficulty (1)");
+ AddAssert("new difficulty persisted", () =>
{
var set = beatmapManager.QueryBeatmapSet(s => s.ID == setId);
- return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1);
+ return set != null && set.PerformRead(s => s.Beatmaps.Count == 2 && s.Files.Count == 2);
});
}
[Test]
- public void TestCreateNewBeatmapFailsWithSameNamedDifficulties([Values] bool sameRuleset)
+ public void TestSavingBeatmapFailsWithSameNamedDifficulties([Values] bool sameRuleset)
{
Guid setId = Guid.Empty;
const string duplicate_difficulty_name = "duplicate";
diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
index 2c994576f3..bafc579134 100644
--- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
@@ -71,9 +71,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
QueueMode = { Value = Mode },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(InitialBeatmap)
{
- Beatmap = { Value = InitialBeatmap },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
index 423822cbe4..d8ec0ad1f0 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs
@@ -53,19 +53,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
Type = { Value = MatchType.HeadToHead },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
- Beatmap =
+ BeatmapInfo =
{
- Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
- {
- BeatmapInfo =
- {
- StarRating = 2.5
- }
- }.BeatmapInfo,
+ StarRating = 2.5
}
- }
+ }.BeatmapInfo)
}
}),
createLoungeRoom(new Room
@@ -76,26 +70,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
Type = { Value = MatchType.HeadToHead },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
- Beatmap =
+ BeatmapInfo =
{
- Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
+ StarRating = 2.5,
+ Metadata =
{
- BeatmapInfo =
- {
- StarRating = 2.5,
- Metadata =
- {
- Artist = "very very very very very very very very very long artist",
- ArtistUnicode = "very very very very very very very very very long artist",
- Title = "very very very very very very very very very very very long title",
- TitleUnicode = "very very very very very very very very very very very long title",
- }
- }
- }.BeatmapInfo,
+ Artist = "very very very very very very very very very long artist",
+ ArtistUnicode = "very very very very very very very very very long artist",
+ Title = "very very very very very very very very very very very long title",
+ TitleUnicode = "very very very very very very very very very very very long title",
+ }
}
- }
+ }.BeatmapInfo)
}
}),
createLoungeRoom(new Room
@@ -105,32 +93,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
EndDate = { Value = DateTimeOffset.Now.AddDays(1) },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
- Beatmap =
+ BeatmapInfo =
{
- Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
- {
- BeatmapInfo =
- {
- StarRating = 2.5
- }
- }.BeatmapInfo,
+ StarRating = 2.5
}
- },
- new PlaylistItem
+ }.BeatmapInfo),
+ new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo)
{
- Beatmap =
+ BeatmapInfo =
{
- Value = new TestBeatmap(new OsuRuleset().RulesetInfo)
- {
- BeatmapInfo =
- {
- StarRating = 4.5
- }
- }.BeatmapInfo,
+ StarRating = 4.5
}
- }
+ }.BeatmapInfo)
}
}),
createLoungeRoom(new Room
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
index 4dc7dc1c42..76353323d6 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs
@@ -168,7 +168,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
assertDownloadButtonVisible(false);
void assertDownloadButtonVisible(bool visible) => AddUntilStep($"download button {(visible ? "shown" : "hidden")}",
- () => playlist.ChildrenOfType().Single().Alpha == (visible ? 1 : 0));
+ () => playlist.ChildrenOfType().SingleOrDefault()?.Alpha == (visible ? 1 : 0));
}
[Test]
@@ -209,10 +209,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
Size = new Vector2(500, 300),
Items =
{
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
ID = 0,
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
Expired = true,
RequiredMods = new[]
@@ -222,10 +221,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
new APIMod(new OsuModAutoplay())
}
},
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
ID = 1,
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
RequiredMods = new[]
{
@@ -262,7 +260,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
}
private void moveToItem(int index, Vector2? offset = null)
- => AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType().ElementAt(index), offset));
+ => AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType().ElementAt(index), offset));
private void moveToDragger(int index, Vector2? offset = null) => AddStep($"move mouse to dragger {index}", () =>
{
@@ -293,25 +291,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
for (int i = 0; i < 20; i++)
{
- playlist.Items.Add(new PlaylistItem
+ playlist.Items.Add(new PlaylistItem(i % 2 == 1
+ ? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
+ : new BeatmapInfo
+ {
+ Metadata = new BeatmapMetadata
+ {
+ Artist = "Artist",
+ Author = new RealmUser { Username = "Creator name here" },
+ Title = "Long title used to check background colour",
+ },
+ BeatmapSet = new BeatmapSetInfo()
+ })
{
ID = i,
OwnerID = 2,
- Beatmap =
- {
- Value = i % 2 == 1
- ? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
- : new BeatmapInfo
- {
- Metadata = new BeatmapMetadata
- {
- Artist = "Artist",
- Author = new RealmUser { Username = "Creator name here" },
- Title = "Long title used to check background colour",
- },
- BeatmapSet = new BeatmapSetInfo()
- }
- },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
RequiredMods = new[]
{
@@ -341,11 +335,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
foreach (var b in beatmaps())
{
- playlist.Items.Add(new PlaylistItem
+ playlist.Items.Add(new PlaylistItem(b)
{
ID = index++,
OwnerID = 2,
- Beatmap = { Value = b },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
RequiredMods = new[]
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs
index a308d60cf1..c3ec7a5369 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs
@@ -58,12 +58,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
RunGameplay();
IBeatmapInfo firstBeatmap = null;
- AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.APIRoom?.Playlist[0].Beatmap.Value);
+ AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.APIRoom?.Playlist[0].Beatmap);
selectNewItem(() => OtherBeatmap);
- AddAssert("first playlist item hasn't changed", () => MultiplayerClient.APIRoom?.Playlist[0].Beatmap.Value == firstBeatmap);
- AddAssert("second playlist item changed", () => MultiplayerClient.APIRoom?.Playlist[1].Beatmap.Value != firstBeatmap);
+ AddAssert("first playlist item hasn't changed", () => MultiplayerClient.APIRoom?.Playlist[0].Beatmap == firstBeatmap);
+ AddAssert("second playlist item changed", () => MultiplayerClient.APIRoom?.Playlist[1].Beatmap != firstBeatmap);
}
[Test]
@@ -105,7 +105,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", () => (CurrentSubScreen as MultiplayerMatchSubScreen)?.SelectedItem.Value?.BeatmapID == otherBeatmap.OnlineID);
+ AddUntilStep("selected item is new beatmap", () => (CurrentSubScreen as MultiplayerMatchSubScreen)?.SelectedItem.Value?.Beatmap.OnlineID == otherBeatmap.OnlineID);
}
private void addItem(Func beatmap)
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs
index 6144824ba0..6f43511e8a 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchBeatmapDetailArea.cs
@@ -32,10 +32,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createNewItem()
{
- SelectedRoom.Value.Playlist.Add(new PlaylistItem
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
ID = SelectedRoom.Value.Playlist.Count,
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
RequiredMods = new[]
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index fc8c3f7f58..e38da96bd5 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -93,9 +93,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -229,9 +228,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -251,9 +249,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -281,9 +278,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -312,9 +308,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Password = { Value = "password" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -334,9 +329,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Password = { Value = "password" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -367,9 +361,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Password = { Value = "password" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -387,9 +380,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -409,9 +401,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -448,9 +439,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -487,9 +477,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -526,9 +515,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -560,9 +548,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -600,9 +587,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -620,9 +606,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
AllowedMods = new[] { new APIMod(new OsuModHidden()) }
}
@@ -660,10 +645,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
@@ -691,10 +675,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
QueueMode = { Value = QueueMode.AllPlayers },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
}, API.LocalUser.Value);
@@ -708,11 +691,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("change server-side settings", () =>
{
roomManager.ServerSideRooms[0].Name.Value = "New name";
- roomManager.ServerSideRooms[0].Playlist.Add(new PlaylistItem
+ roomManager.ServerSideRooms[0].Playlist.Add(new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
ID = 2,
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
});
});
@@ -737,10 +719,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
QueueMode = { Value = QueueMode.AllPlayers },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
@@ -773,10 +754,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
QueueMode = { Value = QueueMode.AllPlayers },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
@@ -812,21 +792,20 @@ namespace osu.Game.Tests.Visual.Multiplayer
QueueMode = { Value = QueueMode.AllPlayers },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
enterGameplay();
-
AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 }));
- AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem
- {
- BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID
- })).WaitSafely());
+ AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
+ {
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
+ })).WaitSafely());
AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2);
@@ -843,10 +822,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
QueueMode = { Value = QueueMode.AllPlayers },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
@@ -854,10 +832,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
enterGameplay();
AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 }));
- AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem
- {
- BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID
- })).WaitSafely());
+ AddStep("add item as other user", () => multiplayerClient.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
+ {
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
+ })).WaitSafely());
AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2);
@@ -876,9 +855,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs
index 1eebe781f1..057032c413 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs
@@ -73,9 +73,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item", () =>
{
- SelectedRoom.Value.Playlist.Add(new PlaylistItem
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
@@ -90,9 +89,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item", () =>
{
- SelectedRoom.Value.Playlist.Add(new PlaylistItem
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new TaikoRuleset().RulesetInfo).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(new TaikoRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new TaikoRuleset().RulesetInfo.OnlineID,
AllowedMods = new[] { new APIMod(new TaikoModSwap()) }
});
@@ -113,9 +111,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set playlist", () =>
{
- SelectedRoom.Value.Playlist.Add(new PlaylistItem
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
@@ -128,9 +125,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("set playlist", () =>
{
- SelectedRoom.Value.Playlist.Add(new PlaylistItem
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
@@ -159,9 +155,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("add playlist item with allowed mod", () =>
{
- SelectedRoom.Value.Playlist.Add(new PlaylistItem
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
AllowedMods = new[] { new APIMod(new OsuModDoubleTime()) }
});
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
index d391fbcf8f..312281ac18 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
@@ -28,9 +28,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("initialise gameplay", () =>
{
- Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.APIRoom, new PlaylistItem
+ Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.APIRoom, new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
- Beatmap = { Value = Beatmap.Value.BeatmapInfo },
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID,
}, MultiplayerClient.Room?.Users.ToArray()));
});
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs
index af12046d76..6b5b45b73e 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs
@@ -143,14 +143,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "test name" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(Ruleset.Value).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
- RulesetID = Ruleset.Value.OnlineID,
+ RulesetID = Ruleset.Value.OnlineID
},
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(Ruleset.Value).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
RulesetID = Ruleset.Value.OnlineID,
Expired = true
}
@@ -167,10 +165,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
///
/// Adds a step to create a new playlist item.
///
- private void addItemStep(bool expired = false) => AddStep("add item", () => MultiplayerClient.AddPlaylistItem(new MultiplayerPlaylistItem(new PlaylistItem
+ private void addItemStep(bool expired = false) => AddStep("add item", () => MultiplayerClient.AddPlaylistItem(new MultiplayerPlaylistItem(new PlaylistItem(importedBeatmap)
{
- Beatmap = { Value = importedBeatmap },
- BeatmapID = importedBeatmap.OnlineID,
Expired = expired,
PlayedAt = DateTimeOffset.Now
})));
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs
index 397c2d16d1..117aaeba83 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs
@@ -120,11 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add playlist item", () =>
{
- MultiplayerPlaylistItem item = new MultiplayerPlaylistItem(new PlaylistItem
- {
- Beatmap = { Value = importedBeatmap },
- BeatmapID = importedBeatmap.OnlineID,
- });
+ MultiplayerPlaylistItem item = new MultiplayerPlaylistItem(new PlaylistItem(importedBeatmap));
MultiplayerClient.AddUserPlaylistItem(userId(), item).WaitSafely();
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
index 6851dba721..35992a0b38 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
@@ -54,9 +54,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
- selectedItem.Value = new PlaylistItem
+ selectedItem.Value = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
- Beatmap = { Value = Beatmap.Value.BeatmapInfo },
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID
};
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
index 44a1745eee..cc08135939 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerResults.cs
@@ -22,12 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
var score = TestResources.CreateTestScoreInfo(beatmapInfo);
- PlaylistItem playlistItem = new PlaylistItem
- {
- BeatmapID = beatmapInfo.OnlineID,
- };
-
- Stack.Push(screen = new MultiplayerResultsScreen(score, 1, playlistItem));
+ Stack.Push(screen = new MultiplayerResultsScreen(score, 1, new PlaylistItem(beatmapInfo)));
});
AddUntilStep("wait for loaded", () => screen.IsLoaded);
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs
index 0033a4ca74..956d40a456 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs
@@ -55,9 +55,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSets().First();
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
- selectedItem.Value = new PlaylistItem
+ selectedItem.Value = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
- Beatmap = { Value = Beatmap.Value.BeatmapInfo },
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID,
};
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
index dfc16c44f2..bdc348b043 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerTeamResults.cs
@@ -26,18 +26,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
var beatmapInfo = CreateBeatmap(rulesetInfo).BeatmapInfo;
var score = TestResources.CreateTestScoreInfo(beatmapInfo);
- PlaylistItem playlistItem = new PlaylistItem
- {
- BeatmapID = beatmapInfo.OnlineID,
- };
-
SortedDictionary teamScores = new SortedDictionary
{
{ 0, new BindableInt(team1Score) },
{ 1, new BindableInt(team2Score) }
};
- Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, playlistItem, teamScores));
+ Stack.Push(screen = new MultiplayerTeamResultsScreen(score, 1, new PlaylistItem(beatmapInfo), teamScores));
});
AddUntilStep("wait for loaded", () => screen.IsLoaded);
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs
index 9adf2c0370..98dc243ab5 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestScenePlaylistsRoomSettingsPlaylist.cs
@@ -8,7 +8,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
-using osu.Game.Beatmaps.Drawables;
using osu.Game.Graphics.Containers;
using osu.Game.Models;
using osu.Game.Online.API;
@@ -107,18 +106,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddAssert("item 0 is selected", () => playlist.SelectedItem.Value == playlist.Items[0]);
}
- [Test]
- public void TestChangeBeatmapAndRemove()
- {
- createPlaylist();
-
- AddStep("change beatmap of first item", () => playlist.Items[0].BeatmapID = 30);
- moveToDeleteButton(0);
- AddStep("click delete button", () => InputManager.Click(MouseButton.Left));
- }
-
private void moveToItem(int index, Vector2? offset = null)
- => AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType().ElementAt(index), offset));
+ => AddStep($"move mouse to item {index}", () => InputManager.MoveMouseTo(playlist.ChildrenOfType().ElementAt(index), offset));
private void moveToDeleteButton(int index, Vector2? offset = null) => AddStep($"move mouse to delete button {index}", () =>
{
@@ -139,25 +128,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
for (int i = 0; i < 20; i++)
{
- playlist.Items.Add(new PlaylistItem
+ playlist.Items.Add(new PlaylistItem(i % 2 == 1
+ ? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
+ : new BeatmapInfo
+ {
+ Metadata = new BeatmapMetadata
+ {
+ Artist = "Artist",
+ Author = new RealmUser { Username = "Creator name here" },
+ Title = "Long title used to check background colour",
+ },
+ BeatmapSet = new BeatmapSetInfo()
+ })
{
ID = i,
OwnerID = 2,
- Beatmap =
- {
- Value = i % 2 == 1
- ? new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo
- : new BeatmapInfo
- {
- Metadata = new BeatmapMetadata
- {
- Artist = "Artist",
- Author = new RealmUser { Username = "Creator name here" },
- Title = "Long title used to check background colour",
- },
- BeatmapSet = new BeatmapSetInfo()
- }
- },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
RequiredMods = new[]
{
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs
index 20db922122..5e4013b0f1 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneStarRatingRangeDisplay.cs
@@ -31,8 +31,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
SelectedRoom.Value.Playlist.AddRange(new[]
{
- new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarRating = min } } },
- new PlaylistItem { Beatmap = { Value = new BeatmapInfo { StarRating = max } } },
+ new PlaylistItem(new BeatmapInfo { StarRating = min }),
+ new PlaylistItem(new BeatmapInfo { StarRating = max }),
});
});
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
index 05b97e333f..19e1f62fd5 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
@@ -67,9 +67,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Type = { Value = MatchType.TeamVersus },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -88,9 +87,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Type = { Value = MatchType.TeamVersus },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}
}
@@ -126,10 +124,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
Type = { Value = MatchType.HeadToHead },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
@@ -152,10 +149,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "Test Room" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo)
{
- Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo },
- RulesetID = new OsuRuleset().RulesetInfo.OnlineID
+ RulesetID = new OsuRuleset().RulesetInfo.OnlineID,
}
}
});
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs
index ca3387392a..666e32d1d0 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsMatchSettingsOverlay.cs
@@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("set name", () => SelectedRoom.Value.Name.Value = "Room name");
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
- AddStep("set beatmap", () => SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }));
+ AddStep("set beatmap", () => SelectedRoom.Value.Playlist.Add(new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo)));
AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value);
AddStep("clear name", () => SelectedRoom.Value.Name.Value = "");
@@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
settings.NameField.Current.Value = expected_name;
settings.DurationField.Current.Value = expectedDuration;
- SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo));
RoomManager.CreateRequested = r =>
{
@@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.Playlists
var beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo;
SelectedRoom.Value.Name.Value = "Test Room";
- SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = beatmap } });
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(beatmap));
errorMessage = $"{not_found_prefix} {beatmap.OnlineID}";
@@ -121,7 +121,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("setup", () =>
{
SelectedRoom.Value.Name.Value = "Test Room";
- SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
+ SelectedRoom.Value.Playlist.Add(new PlaylistItem(CreateBeatmap(Ruleset.Value).BeatmapInfo));
RoomManager.CreateRequested = _ => failText;
});
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
index a05d01613c..161624413d 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
@@ -165,9 +165,8 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("load results", () =>
{
- LoadScreen(resultsScreen = new TestResultsScreen(getScore?.Invoke(), 1, new PlaylistItem
+ LoadScreen(resultsScreen = new TestResultsScreen(getScore?.Invoke(), 1, new PlaylistItem(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
}));
});
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs
index a6f1762cb3..14f8c1d6d4 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsRoomCreation.cs
@@ -64,9 +64,8 @@ namespace osu.Game.Tests.Visual.Playlists
room.Host.Value = API.LocalUser.Value;
room.RecentParticipants.Add(room.Host.Value);
room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
- room.Playlist.Add(new PlaylistItem
+ room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
{
- Beatmap = { Value = importedBeatmap.Beatmaps.First() },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
@@ -89,9 +88,8 @@ namespace osu.Game.Tests.Visual.Playlists
room.Host.Value = API.LocalUser.Value;
room.RecentParticipants.Add(room.Host.Value);
room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
- room.Playlist.Add(new PlaylistItem
+ room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
{
- Beatmap = { Value = importedBeatmap.Beatmaps.First() },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
@@ -106,9 +104,8 @@ namespace osu.Game.Tests.Visual.Playlists
{
room.Name.Value = "my awesome room";
room.Host.Value = API.LocalUser.Value;
- room.Playlist.Add(new PlaylistItem
+ room.Playlist.Add(new PlaylistItem(importedBeatmap.Beatmaps.First())
{
- Beatmap = { Value = importedBeatmap.Beatmaps.First() },
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
@@ -158,21 +155,17 @@ namespace osu.Game.Tests.Visual.Playlists
{
room.Name.Value = "my awesome room";
room.Host.Value = API.LocalUser.Value;
- room.Playlist.Add(new PlaylistItem
+ room.Playlist.Add(new PlaylistItem(new BeatmapInfo
{
- Beatmap =
+ MD5Hash = realHash,
+ OnlineID = realOnlineId,
+ Metadata = new BeatmapMetadata(),
+ BeatmapSet = new BeatmapSetInfo
{
- Value = new BeatmapInfo
- {
- MD5Hash = realHash,
- OnlineID = realOnlineId,
- Metadata = new BeatmapMetadata(),
- BeatmapSet = new BeatmapSetInfo
- {
- OnlineID = realOnlineSetId,
- }
- }
- },
+ OnlineID = realOnlineSetId,
+ }
+ })
+ {
RulesetID = new OsuRuleset().RulesetInfo.OnlineID
});
});
diff --git a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
index 062aa33b99..c43ed744bd 100644
--- a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
+++ b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
@@ -5,6 +5,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Screens;
using osu.Game.Database;
+using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens;
@@ -46,6 +47,9 @@ namespace osu.Game.Tests.Visual
[Cached]
private readonly BeatmapLookupCache beatmapLookupCache = new BeatmapLookupCache();
+ [Resolved]
+ private BeatmapManager beatmapManager { get; set; }
+
private readonly OsuScreenStack screenStack;
private readonly TestMultiplayer multiplayerScreen;
@@ -69,9 +73,9 @@ namespace osu.Game.Tests.Visual
}
[BackgroundDependencyLoader]
- private void load(IAPIProvider api, OsuGameBase game)
+ private void load(IAPIProvider api)
{
- ((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, game);
+ ((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, beatmapManager);
}
public override bool OnBackButton() => (screenStack.CurrentScreen as OsuScreen)?.OnBackButton() ?? base.OnBackButton();
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index 777d5db2ad..5f7de0d762 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -22,6 +22,7 @@ using osu.Game.Overlays.Notifications;
using osu.Game.Rulesets;
using osu.Game.Skinning;
using osu.Game.Stores;
+using osu.Game.Utils;
#nullable enable
@@ -123,7 +124,10 @@ namespace osu.Game.Beatmaps
{
var playableBeatmap = referenceWorkingBeatmap.GetPlayableBeatmap(rulesetInfo);
- var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), playableBeatmap.Metadata.DeepClone());
+ var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), playableBeatmap.Metadata.DeepClone())
+ {
+ DifficultyName = NamingUtils.GetNextBestName(targetBeatmapSet.Beatmaps.Select(b => b.DifficultyName), "New Difficulty")
+ };
var newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo };
foreach (var timingPoint in playableBeatmap.ControlPointInfo.TimingPoints)
newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone());
@@ -150,8 +154,10 @@ namespace osu.Game.Beatmaps
newBeatmap.BeatmapInfo = newBeatmapInfo = referenceWorkingBeatmap.BeatmapInfo.Clone();
// assign a new ID to the clone.
newBeatmapInfo.ID = Guid.NewGuid();
- // add "(copy)" suffix to difficulty name to avoid clashes on save.
- newBeatmapInfo.DifficultyName += " (copy)";
+ // add "(copy)" suffix to difficulty name, and additionally ensure that it doesn't conflict with any other potentially pre-existing copies.
+ newBeatmapInfo.DifficultyName = NamingUtils.GetNextBestName(
+ targetBeatmapSet.Beatmaps.Select(b => b.DifficultyName),
+ $"{newBeatmapInfo.DifficultyName} (copy)");
// clear the hash, as that's what is used to match .osu files with their corresponding realm beatmaps.
newBeatmapInfo.Hash = string.Empty;
// clear online properties.
diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs
index a39d7bfb47..b0f20de685 100644
--- a/osu.Game/Graphics/ScreenshotManager.cs
+++ b/osu.Game/Graphics/ScreenshotManager.cs
@@ -112,6 +112,8 @@ namespace osu.Game.Graphics
if (Interlocked.Decrement(ref screenShotTasks) == 0 && cursorVisibility.Value == false)
cursorVisibility.Value = true;
+ host.GetClipboard()?.SetImage(image);
+
string filename = getFilename();
if (filename == null) return;
diff --git a/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs
index 1d71e22b77..22af022659 100644
--- a/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs
+++ b/osu.Game/Online/API/Requests/GetBeatmapsRequest.cs
@@ -2,12 +2,13 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Collections.Generic;
namespace osu.Game.Online.API.Requests
{
public class GetBeatmapsRequest : APIRequest
{
- private readonly int[] beatmapIds;
+ public readonly IReadOnlyList BeatmapIds;
private const int max_ids_per_request = 50;
@@ -16,9 +17,9 @@ namespace osu.Game.Online.API.Requests
if (beatmapIds.Length > max_ids_per_request)
throw new ArgumentException($"{nameof(GetBeatmapsRequest)} calls only support up to {max_ids_per_request} IDs at once");
- this.beatmapIds = beatmapIds;
+ BeatmapIds = beatmapIds;
}
- protected override string Target => "beatmaps/?ids[]=" + string.Join("&ids[]=", beatmapIds);
+ protected override string Target => "beatmaps/?ids[]=" + string.Join("&ids[]=", BeatmapIds);
}
}
diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs
index dca60e54cb..f5795141c5 100644
--- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs
@@ -112,7 +112,27 @@ namespace osu.Game.Online.API.Requests.Responses
public int OnlineID { get; set; } = -1;
public string Name => $@"{nameof(APIRuleset)} (ID: {OnlineID})";
- public string ShortName => nameof(APIRuleset);
+
+ public string ShortName
+ {
+ get
+ {
+ // TODO: this should really not exist.
+ switch (OnlineID)
+ {
+ case 0: return "osu";
+
+ case 1: return "taiko";
+
+ case 2: return "fruits";
+
+ case 3: return "mania";
+
+ default: throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+
public string InstantiationInfo => string.Empty;
public Ruleset CreateInstance() => throw new NotImplementedException();
diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
index 9d45229961..a56cc7f8d6 100644
--- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
@@ -727,10 +727,9 @@ namespace osu.Game.Online.Multiplayer
RoomUpdated?.Invoke();
}
- private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item) => new PlaylistItem
+ private PlaylistItem createPlaylistItem(MultiplayerPlaylistItem item) => new PlaylistItem(new APIBeatmap { OnlineID = item.BeatmapID })
{
ID = item.ID,
- BeatmapID = item.BeatmapID,
OwnerID = item.OwnerID,
RulesetID = item.RulesetID,
Expired = item.Expired,
@@ -740,14 +739,6 @@ namespace osu.Game.Online.Multiplayer
AllowedMods = item.AllowedMods.ToArray()
};
- ///
- /// Retrieves a from an online source.
- ///
- /// The beatmap ID.
- /// A token to cancel the request.
- /// The retrieval task.
- 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 ad898759ff..7e62908ecd 100644
--- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
@@ -10,9 +10,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
-using osu.Game.Database;
using osu.Game.Online.API;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
namespace osu.Game.Online.Multiplayer
@@ -30,9 +28,6 @@ namespace osu.Game.Online.Multiplayer
private HubConnection? connection => connector?.CurrentConnection;
- [Resolved]
- private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
-
public OnlineMultiplayerClient(EndpointConfiguration endpoints)
{
endpoint = endpoints.MultiplayerEndpointUrl;
@@ -215,11 +210,6 @@ namespace osu.Game.Online.Multiplayer
return connection.InvokeAsync(nameof(IMultiplayerServer.RemovePlaylistItem), playlistItemId);
}
- public override Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
- {
- return beatmapLookupCache.GetBeatmapAsync(beatmapId, cancellationToken);
- }
-
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs
index d74cdd8c34..388a02f798 100644
--- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs
+++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs
@@ -63,8 +63,8 @@ namespace osu.Game.Online.Rooms
{
ID = item.ID;
OwnerID = item.OwnerID;
- BeatmapID = item.BeatmapID;
- BeatmapChecksum = item.Beatmap.Value?.MD5Hash ?? string.Empty;
+ BeatmapID = item.Beatmap.OnlineID;
+ BeatmapChecksum = item.Beatmap.MD5Hash;
RulesetID = item.RulesetID;
RequiredMods = item.RequiredMods.ToArray();
AllowedMods = item.AllowedMods.ToArray();
diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs
index c67cbade6a..07506ba1f0 100644
--- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs
+++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs
@@ -4,14 +4,17 @@
using System;
using System.Diagnostics;
using System.Linq;
+using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
+using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Database;
+using osu.Game.Online.API.Requests.Responses;
using Realms;
namespace osu.Game.Online.Rooms
@@ -32,6 +35,9 @@ namespace osu.Game.Online.Rooms
[Resolved]
private RealmAccess realm { get; set; } = null!;
+ [Resolved]
+ private BeatmapLookupCache beatmapLookupCache { get; set; } = null!;
+
///
/// The availability state of the currently selected playlist item.
///
@@ -40,10 +46,9 @@ namespace osu.Game.Online.Rooms
private readonly Bindable availability = new Bindable(BeatmapAvailability.NotDownloaded());
private ScheduledDelegate progressUpdate;
-
private BeatmapDownloadTracker downloadTracker;
-
private IDisposable realmSubscription;
+ private APIBeatmap selectedBeatmap;
protected override void LoadComplete()
{
@@ -57,40 +62,55 @@ namespace osu.Game.Online.Rooms
return;
downloadTracker?.RemoveAndDisposeImmediately();
+ selectedBeatmap = null;
- Debug.Assert(item.NewValue.Beatmap.Value.BeatmapSet != null);
-
- downloadTracker = new BeatmapDownloadTracker(item.NewValue.Beatmap.Value.BeatmapSet);
-
- AddInternal(downloadTracker);
-
- downloadTracker.State.BindValueChanged(_ => Scheduler.AddOnce(updateAvailability), true);
- downloadTracker.Progress.BindValueChanged(_ =>
+ beatmapLookupCache.GetBeatmapAsync(item.NewValue.Beatmap.OnlineID).ContinueWith(task => Schedule(() =>
{
- if (downloadTracker.State.Value != DownloadState.Downloading)
- return;
+ var beatmap = task.GetResultSafely();
- // incoming progress changes are going to be at a very high rate.
- // we don't want to flood the network with this, so rate limit how often we send progress updates.
- if (progressUpdate?.Completed != false)
- progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500);
- }, true);
-
- // handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow).
- realmSubscription?.Dispose();
- realmSubscription = realm.RegisterForNotifications(r => filteredBeatmaps(), (items, changes, ___) =>
- {
- if (changes == null)
- return;
-
- Scheduler.AddOnce(updateAvailability);
- });
+ if (SelectedItem.Value?.Beatmap.OnlineID == beatmap.OnlineID)
+ {
+ selectedBeatmap = beatmap;
+ beginTracking();
+ }
+ }), TaskContinuationOptions.OnlyOnRanToCompletion);
}, true);
}
+ private void beginTracking()
+ {
+ Debug.Assert(selectedBeatmap.BeatmapSet != null);
+
+ downloadTracker = new BeatmapDownloadTracker(selectedBeatmap.BeatmapSet);
+
+ AddInternal(downloadTracker);
+
+ downloadTracker.State.BindValueChanged(_ => Scheduler.AddOnce(updateAvailability), true);
+ downloadTracker.Progress.BindValueChanged(_ =>
+ {
+ if (downloadTracker.State.Value != DownloadState.Downloading)
+ return;
+
+ // incoming progress changes are going to be at a very high rate.
+ // we don't want to flood the network with this, so rate limit how often we send progress updates.
+ if (progressUpdate?.Completed != false)
+ progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500);
+ }, true);
+
+ // handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow).
+ realmSubscription?.Dispose();
+ realmSubscription = realm.RegisterForNotifications(r => filteredBeatmaps(), (items, changes, ___) =>
+ {
+ if (changes == null)
+ return;
+
+ Scheduler.AddOnce(updateAvailability);
+ });
+ }
+
private void updateAvailability()
{
- if (downloadTracker == null || SelectedItem.Value == null)
+ if (downloadTracker == null || selectedBeatmap == null)
return;
switch (downloadTracker.State.Value)
@@ -108,12 +128,12 @@ namespace osu.Game.Online.Rooms
break;
case DownloadState.LocallyAvailable:
- bool hashMatches = filteredBeatmaps().Any();
+ bool available = filteredBeatmaps().Any();
- availability.Value = hashMatches ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
+ availability.Value = available ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded();
// only display a message to the user if a download seems to have just completed.
- if (!hashMatches && downloadTracker.Progress.Value == 1)
+ if (!available && downloadTracker.Progress.Value == 1)
Logger.Log("The imported beatmap set does not match the online version.", LoggingTarget.Runtime, LogLevel.Important);
break;
@@ -125,8 +145,8 @@ namespace osu.Game.Online.Rooms
private IQueryable filteredBeatmaps()
{
- int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID;
- string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash;
+ int onlineId = selectedBeatmap.OnlineID;
+ string checksum = selectedBeatmap.MD5Hash;
return realm.Realm
.All()
diff --git a/osu.Game/Online/Rooms/PlaylistExtensions.cs b/osu.Game/Online/Rooms/PlaylistExtensions.cs
index e78f91f20b..34c93bd9e0 100644
--- a/osu.Game/Online/Rooms/PlaylistExtensions.cs
+++ b/osu.Game/Online/Rooms/PlaylistExtensions.cs
@@ -41,6 +41,6 @@ namespace osu.Game.Online.Rooms
}
public static string GetTotalDuration(this BindableList playlist) =>
- playlist.Select(p => p.Beatmap.Value.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2);
+ playlist.Select(p => p.Beatmap.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2);
}
}
diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs
index c082babb01..33718f050b 100644
--- a/osu.Game/Online/Rooms/PlaylistItem.cs
+++ b/osu.Game/Online/Rooms/PlaylistItem.cs
@@ -1,6 +1,8 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+#nullable enable
+
using System;
using System.Linq;
using JetBrains.Annotations;
@@ -12,6 +14,7 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.Rooms
{
+ [JsonObject(MemberSerialization.OptIn)]
public class PlaylistItem : IEquatable
{
[JsonProperty("id")]
@@ -20,9 +23,6 @@ namespace osu.Game.Online.Rooms
[JsonProperty("owner_id")]
public int OwnerID { get; set; }
- [JsonProperty("beatmap_id")]
- public int BeatmapID { get; set; }
-
[JsonProperty("ruleset_id")]
public int RulesetID { get; set; }
@@ -38,35 +38,50 @@ namespace osu.Game.Online.Rooms
[JsonProperty("played_at")]
public DateTimeOffset? PlayedAt { get; set; }
- [JsonIgnore]
- public IBindable Valid => valid;
-
- private readonly Bindable valid = new BindableBool(true);
-
- [JsonIgnore]
- public readonly Bindable Beatmap = new Bindable();
-
- [JsonProperty("beatmap")]
- private APIBeatmap apiBeatmap { get; set; }
-
[JsonProperty("allowed_mods")]
public APIMod[] AllowedMods { get; set; } = Array.Empty();
[JsonProperty("required_mods")]
public APIMod[] RequiredMods { get; set; } = Array.Empty();
- public PlaylistItem()
+ ///
+ /// Used for deserialising from the API.
+ ///
+ [JsonProperty("beatmap")]
+ private APIBeatmap apiBeatmap
{
- Beatmap.BindValueChanged(beatmap => BeatmapID = beatmap.NewValue?.OnlineID ?? -1);
+ // This getter is required/used internally by JSON.NET during deserialisation to do default-value comparisons. It is never used during serialisation (see: ShouldSerializeapiBeatmap()).
+ // It will always return a null value on deserialisation, which JSON.NET will handle gracefully.
+ get => (APIBeatmap)Beatmap;
+ set => Beatmap = value;
+ }
+
+ ///
+ /// Used for serialising to the API.
+ ///
+ [JsonProperty("beatmap_id")]
+ private int onlineBeatmapId => Beatmap.OnlineID;
+
+ [JsonIgnore]
+ public IBeatmapInfo Beatmap { get; set; } = null!;
+
+ [JsonIgnore]
+ public IBindable Valid => valid;
+
+ private readonly Bindable valid = new BindableBool(true);
+
+ [JsonConstructor]
+ private PlaylistItem()
+ {
+ }
+
+ public PlaylistItem(IBeatmapInfo beatmap)
+ {
+ Beatmap = beatmap;
}
public void MarkInvalid() => valid.Value = false;
- public void MapObjects()
- {
- Beatmap.Value ??= apiBeatmap;
- }
-
#region Newtonsoft.Json implicit ShouldSerialize() methods
// The properties in this region are used implicitly by Newtonsoft.Json to not serialise certain fields in some cases.
@@ -82,9 +97,22 @@ namespace osu.Game.Online.Rooms
#endregion
- public bool Equals(PlaylistItem other)
+ public PlaylistItem With(IBeatmapInfo beatmap) => new PlaylistItem(beatmap)
+ {
+ ID = ID,
+ OwnerID = OwnerID,
+ RulesetID = RulesetID,
+ Expired = Expired,
+ PlaylistOrder = PlaylistOrder,
+ PlayedAt = PlayedAt,
+ AllowedMods = AllowedMods,
+ RequiredMods = RequiredMods,
+ valid = { Value = Valid.Value },
+ };
+
+ public bool Equals(PlaylistItem? other)
=> ID == other?.ID
- && BeatmapID == other.BeatmapID
+ && Beatmap.OnlineID == other.Beatmap.OnlineID
&& RulesetID == other.RulesetID
&& Expired == other.Expired
&& AllowedMods.SequenceEqual(other.AllowedMods)
diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs
index e948c1adae..7cbe1a9017 100644
--- a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs
@@ -68,14 +68,14 @@ namespace osu.Game.Screens.OnlinePlay.Components
}
else
{
- var metadataInfo = beatmap.Value.Metadata;
+ var metadataInfo = beatmap.Metadata;
string artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode;
string titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode;
var title = new RomanisableString($"{artistUnicode} - {titleUnicode}".Trim(), $"{metadataInfo.Artist} - {metadataInfo.Title}".Trim());
- textFlow.AddLink(title, LinkAction.OpenBeatmap, beatmap.Value.OnlineID.ToString(), "Open beatmap");
+ textFlow.AddLink(title, LinkAction.OpenBeatmap, beatmap.OnlineID.ToString(), "Open beatmap");
}
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs b/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs
index d534a1e374..8402619ebc 100644
--- a/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/ModeTypeInfo.cs
@@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
var mods = item.RequiredMods.Select(m => m.ToMod(ruleset)).ToArray();
drawableRuleset.FadeIn(transition_duration);
- drawableRuleset.Child = new DifficultyIcon(item.Beatmap.Value, ruleset.RulesetInfo, mods) { Size = new Vector2(height) };
+ drawableRuleset.Child = new DifficultyIcon(item.Beatmap, ruleset.RulesetInfo, mods) { Size = new Vector2(height) };
}
else
drawableRuleset.FadeOut(transition_duration);
diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs
index ffc5c07d4e..8906bebf0e 100644
--- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs
@@ -60,7 +60,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
{
Schedule(() =>
{
- var beatmap = playlistItem?.Beatmap.Value;
+ var beatmap = playlistItem?.Beatmap;
string? lastCover = (background?.Beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover;
string? newCover = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover;
diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
index d144e1e3a9..d46ff12279 100644
--- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
@@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
private void updateBeatmap()
{
- sprite.Beatmap.Value = Playlist.GetCurrentItem()?.Beatmap.Value;
+ sprite.Beatmap.Value = Playlist.GetCurrentItem()?.Beatmap;
}
protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs
index f3e90aa396..7e31591389 100644
--- a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
public PlaylistItemBackground(PlaylistItem? playlistItem)
{
- Beatmap = playlistItem?.Beatmap.Value;
+ Beatmap = playlistItem?.Beatmap;
}
[BackgroundDependencyLoader]
diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs
index 21b64b61bb..4242886e66 100644
--- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs
@@ -112,9 +112,6 @@ namespace osu.Game.Screens.OnlinePlay.Components
try
{
- foreach (var pi in room.Playlist)
- pi.MapObjects();
-
var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value);
if (existing == null)
rooms.Add(room);
diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs
index edf9c5d155..95ecadd21a 100644
--- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs
@@ -80,7 +80,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
private void updateRange(object sender, NotifyCollectionChangedEventArgs e)
{
- var orderedDifficulties = Playlist.Where(p => p.Beatmap.Value != null).Select(p => p.Beatmap.Value).OrderBy(b => b.StarRating).ToArray();
+ var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray();
StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0);
StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0);
diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
index dcf2a5a480..25b36e0774 100644
--- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
+++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs
@@ -5,7 +5,6 @@ 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;
@@ -25,7 +24,6 @@ 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;
@@ -68,8 +66,8 @@ namespace osu.Game.Screens.OnlinePlay
private readonly DelayedLoadWrapper onScreenLoader = new DelayedLoadWrapper(Empty) { RelativeSizeAxes = Axes.Both };
private readonly IBindable valid = new Bindable();
- private readonly Bindable beatmap = new Bindable();
+ private IBeatmapInfo beatmap;
private IRulesetInfo ruleset;
private Mod[] requiredMods;
@@ -96,10 +94,6 @@ 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; }
@@ -110,7 +104,6 @@ namespace osu.Game.Screens.OnlinePlay
{
Item = item;
- beatmap.BindTo(item.Beatmap);
valid.BindTo(item.Valid);
if (item.Expired)
@@ -151,7 +144,6 @@ namespace osu.Game.Screens.OnlinePlay
maskingContainer.BorderThickness = isCurrent ? 5 : 0;
}, true);
- beatmap.BindValueChanged(_ => Scheduler.AddOnce(refresh));
valid.BindValueChanged(_ => Scheduler.AddOnce(refresh));
onScreenLoader.DelayedLoadStarted += _ =>
@@ -166,19 +158,9 @@ namespace osu.Game.Screens.OnlinePlay
Schedule(() => ownerAvatar.User = foundUser);
}
- if (Item.Beatmap.Value == null)
- {
- IBeatmapInfo foundBeatmap;
+ beatmap = await beatmapLookupCache.GetBeatmapAsync(Item.Beatmap.OnlineID).ConfigureAwait(false);
- 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);
- }
+ Scheduler.AddOnce(refresh);
}
catch (Exception e)
{
@@ -280,32 +262,36 @@ namespace osu.Game.Screens.OnlinePlay
maskingContainer.BorderColour = colours.Red;
}
- if (Item.Beatmap.Value != null)
- difficultyIconContainer.Child = new DifficultyIcon(Item.Beatmap.Value, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) };
+ if (beatmap != null)
+ difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) };
else
difficultyIconContainer.Clear();
- panelBackground.Beatmap.Value = Item.Beatmap.Value;
+ panelBackground.Beatmap.Value = beatmap;
beatmapText.Clear();
- if (Item.Beatmap.Value != null)
+ if (beatmap != null)
{
- beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineID.ToString(), null, text =>
- {
- text.Truncate = true;
- });
+ beatmapText.AddLink(beatmap.GetDisplayTitleRomanisable(includeCreator: false),
+ LinkAction.OpenBeatmap,
+ beatmap.OnlineID.ToString(),
+ null,
+ text =>
+ {
+ text.Truncate = true;
+ });
}
authorText.Clear();
- if (!string.IsNullOrEmpty(Item.Beatmap.Value?.Metadata.Author.Username))
+ if (!string.IsNullOrEmpty(beatmap?.Metadata.Author.Username))
{
authorText.AddText("mapped by ");
- authorText.AddUserLink(Item.Beatmap.Value.Metadata.Author);
+ authorText.AddUserLink(beatmap.Metadata.Author);
}
- bool hasExplicitContent = (Item.Beatmap.Value?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true;
+ bool hasExplicitContent = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true;
explicitContentPill.Alpha = hasExplicitContent ? 1 : 0;
modDisplay.Current.Value = requiredMods.ToArray();
@@ -457,7 +443,7 @@ namespace osu.Game.Screens.OnlinePlay
Alpha = AllowShowingResults ? 1 : 0,
TooltipText = "View results"
},
- Item.Beatmap.Value == null ? Empty() : new PlaylistDownloadButton(Item),
+ beatmap == null ? Empty() : new PlaylistDownloadButton(beatmap),
editButton = new PlaylistEditButton
{
Size = new Vector2(30, 30),
@@ -499,7 +485,7 @@ namespace osu.Game.Screens.OnlinePlay
private sealed class PlaylistDownloadButton : BeatmapDownloadButton
{
- private readonly PlaylistItem playlistItem;
+ private readonly IBeatmapInfo beatmap;
[Resolved]
private BeatmapManager beatmapManager { get; set; }
@@ -509,10 +495,10 @@ namespace osu.Game.Screens.OnlinePlay
private const float width = 50;
- public PlaylistDownloadButton(PlaylistItem playlistItem)
- : base(playlistItem.Beatmap.Value.BeatmapSet)
+ public PlaylistDownloadButton(IBeatmapInfo beatmap)
+ : base(beatmap.BeatmapSet)
{
- this.playlistItem = playlistItem;
+ this.beatmap = beatmap;
Size = new Vector2(width, 30);
Alpha = 0;
@@ -532,7 +518,7 @@ namespace osu.Game.Screens.OnlinePlay
{
case DownloadState.LocallyAvailable:
// Perform a local query of the beatmap by beatmap checksum, and reset the state if not matching.
- if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null)
+ if (beatmapManager.QueryBeatmap(b => b.MD5Hash == beatmap.MD5Hash) == null)
State.Value = DownloadState.NotDownloaded;
else
{
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
index a87f21630c..a1a82c907a 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs
@@ -2,8 +2,10 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
+using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
+using osu.Framework.Extensions;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
@@ -12,6 +14,7 @@ using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
+using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
@@ -328,6 +331,9 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
[Resolved]
private OsuColour colours { get; set; }
+ [Resolved]
+ private BeatmapLookupCache beatmapLookupCache { get; set; }
+
private SpriteText statusText;
private LinkFlowContainer beatmapText;
@@ -385,8 +391,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
SelectedItem.BindValueChanged(onSelectedItemChanged, true);
}
+ private CancellationTokenSource beatmapLookupCancellation;
+
private void onSelectedItemChanged(ValueChangedEvent item)
{
+ beatmapLookupCancellation?.Cancel();
beatmapText.Clear();
if (Type.Value == MatchType.Playlists)
@@ -395,17 +404,25 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
return;
}
- if (item.NewValue?.Beatmap.Value != null)
- {
- statusText.Text = "Currently playing ";
- beatmapText.AddLink(item.NewValue.Beatmap.Value.GetDisplayTitleRomanisable(),
- LinkAction.OpenBeatmap,
- item.NewValue.Beatmap.Value.OnlineID.ToString(),
- creationParameters: s =>
- {
- s.Truncate = true;
- });
- }
+ var beatmap = item.NewValue?.Beatmap;
+ if (beatmap == null)
+ return;
+
+ var cancellationSource = beatmapLookupCancellation = new CancellationTokenSource();
+ beatmapLookupCache.GetBeatmapAsync(beatmap.OnlineID, cancellationSource.Token)
+ .ContinueWith(task => Schedule(() =>
+ {
+ if (cancellationSource.IsCancellationRequested)
+ return;
+
+ var retrievedBeatmap = task.GetResultSafely();
+
+ statusText.Text = "Currently playing ";
+ beatmapText.AddLink(retrievedBeatmap.GetDisplayTitleRomanisable(),
+ LinkAction.OpenBeatmap,
+ retrievedBeatmap.OnlineID.ToString(),
+ creationParameters: s => s.Truncate = true);
+ }), cancellationSource.Token);
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs
index a7b907c7d2..cdd2ae0c9c 100644
--- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs
+++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs
@@ -62,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
if (editButton != null)
host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true);
- SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap.Value, true);
+ SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap, true);
}
protected override Drawable CreateBackground() => background = new BackgroundSprite();
diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
index 836629ada0..e297c90491 100644
--- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs
@@ -376,7 +376,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
private void updateWorkingBeatmap()
{
- var beatmap = SelectedItem.Value?.Beatmap.Value;
+ var beatmap = SelectedItem.Value?.Beatmap;
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineID == beatmap.OnlineID);
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
index 12caf1fde1..e30ec36e9c 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
@@ -67,8 +67,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
var multiplayerItem = new MultiplayerPlaylistItem
{
ID = itemToEdit ?? 0,
- BeatmapID = item.BeatmapID,
- BeatmapChecksum = item.Beatmap.Value.MD5Hash,
+ BeatmapID = item.Beatmap.OnlineID,
+ BeatmapChecksum = item.Beatmap.MD5Hash,
RulesetID = item.RulesetID,
RequiredMods = item.RequiredMods.ToArray(),
AllowedMods = item.AllowedMods.ToArray()
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
index cb50a56052..429b0ad89b 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
@@ -5,7 +5,6 @@ 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;
@@ -398,38 +397,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
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;
+ SelectedItem.Value = Room.Playlist.SingleOrDefault(i => i.ID == client.Room.Settings.PlaylistItemId);
}
private void handleRoomLost() => Schedule(() =>
diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs
index eab1f83967..7b64784316 100644
--- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs
+++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs
@@ -113,12 +113,8 @@ namespace osu.Game.Screens.OnlinePlay
{
itemSelected = true;
- var item = new PlaylistItem
+ var item = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
- Beatmap =
- {
- Value = Beatmap.Value.BeatmapInfo
- },
RulesetID = Ruleset.Value.OnlineID,
RequiredMods = Mods.Value.Select(m => new APIMod(m)).ToArray(),
AllowedMods = FreeMods.Value.Select(m => new APIMod(m)).ToArray()
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs
index 2b071175d5..8403e1e0fe 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs
@@ -34,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
private void load(IBindable ruleset)
{
// Sanity checks to ensure that PlaylistsPlayer matches the settings for the current PlaylistItem
- if (!Beatmap.Value.BeatmapInfo.MatchesOnlineID(PlaylistItem.Beatmap.Value))
+ if (!Beatmap.Value.BeatmapInfo.MatchesOnlineID(PlaylistItem.Beatmap))
throw new InvalidOperationException("Current Beatmap does not match PlaylistItem's Beatmap");
if (ruleset.Value.OnlineID != PlaylistItem.RulesetID)
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs
index 6c8ab52d22..6674a37c3c 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSettingsOverlay.cs
@@ -392,7 +392,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
foreach (var item in Playlist)
{
- if (invalidBeatmapIDs.Contains(item.BeatmapID))
+ if (invalidBeatmapIDs.Contains(item.Beatmap.OnlineID))
item.MarkInvalid();
}
}
diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs
index 3ac576b18e..86591c1d6d 100644
--- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs
+++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsSongSelect.cs
@@ -41,10 +41,9 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
private void createNewItem()
{
- PlaylistItem item = new PlaylistItem
+ PlaylistItem item = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
ID = Playlist.Count == 0 ? 0 : Playlist.Max(p => p.ID) + 1,
- Beatmap = { Value = Beatmap.Value.BeatmapInfo },
RulesetID = Ruleset.Value.OnlineID,
RequiredMods = Mods.Value.Select(m => new APIMod(m)).ToArray(),
AllowedMods = FreeMods.Value.Select(m => new APIMod(m)).ToArray()
diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
index 19f9952d14..6c40546325 100644
--- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
@@ -46,9 +46,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
Name = { Value = "test name" },
Playlist =
{
- new PlaylistItem
+ new PlaylistItem(new TestBeatmap(Ruleset.Value).BeatmapInfo)
{
- Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
RulesetID = Ruleset.Value.OnlineID
}
}
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
index 15ede6cc26..6dc5159b6f 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
@@ -7,14 +7,11 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
-using osu.Game.Beatmaps;
using osu.Game.Online.API;
-using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
using osu.Game.Online.Rooms;
@@ -39,9 +36,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Resolved]
private IAPIProvider api { get; set; } = null!;
- [Resolved]
- private BeatmapManager beatmaps { get; set; } = null!;
-
private readonly TestMultiplayerRoomManager roomManager;
///
@@ -407,23 +401,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
public override Task RemovePlaylistItem(long playlistItemId) => RemoveUserPlaylistItem(api.LocalUser.Value.OnlineID, playlistItemId);
- public override Task GetAPIBeatmap(int beatmapId, CancellationToken cancellationToken = default)
- {
- IBeatmapInfo? beatmap = roomManager.ServerSideRooms.SelectMany(r => r.Playlist)
- .FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value
- ?? beatmaps.QueryBeatmap(b => b.OnlineID == beatmapId);
-
- if (beatmap == null)
- throw new InvalidOperationException("Beatmap not found.");
-
- return Task.FromResult(new APIBeatmap
- {
- BeatmapSet = new APIBeatmapSet { OnlineID = beatmap.BeatmapSet?.OnlineID ?? -1 },
- OnlineID = beatmapId,
- Checksum = beatmap.MD5Hash
- });
- }
-
private async Task changeMatchType(MatchType type)
{
Debug.Assert(Room != null);
diff --git a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs
index baff7c168f..b6a347a896 100644
--- a/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs
+++ b/osu.Game/Tests/Visual/OnlinePlay/OnlinePlayTestScene.cs
@@ -8,6 +8,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Database;
+using osu.Game.Beatmaps;
using osu.Game.Online.API;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
@@ -33,9 +34,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay
protected override Container Content => content;
- [Resolved]
- private OsuGameBase game { get; set; }
-
private readonly Container content;
private readonly Container drawableDependenciesContainer;
private DelegatedDependencyContainer dependencies;
@@ -62,19 +60,16 @@ namespace osu.Game.Tests.Visual.OnlinePlay
drawableDependenciesContainer.Clear();
dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies();
drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents);
+
+ var handler = OnlinePlayDependencies.RequestsHandler;
+
+ // Resolving the BeatmapManager in the test scene will inject the game-wide BeatmapManager, while many test scenes cache their own BeatmapManager instead.
+ // To get around this, the BeatmapManager is looked up from the dependencies provided to the children of the test scene instead.
+ var beatmapManager = dependencies.Get();
+
+ ((DummyAPIAccess)API).HandleRequest = request => handler.HandleRequest(request, API.LocalUser.Value, beatmapManager);
});
- public override void SetUpSteps()
- {
- base.SetUpSteps();
-
- AddStep("setup API", () =>
- {
- var handler = OnlinePlayDependencies.RequestsHandler;
- ((DummyAPIAccess)API).HandleRequest = request => handler.HandleRequest(request, API.LocalUser.Value, game);
- });
- }
-
///
/// Creates the room dependencies. Called every .
///
diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs
index 73d0df2c36..8dfd969c51 100644
--- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs
+++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs
@@ -43,16 +43,9 @@ namespace osu.Game.Tests.Visual.OnlinePlay
if (ruleset != null)
{
- room.Playlist.Add(new PlaylistItem
+ room.Playlist.Add(new PlaylistItem(new BeatmapInfo { Metadata = new BeatmapMetadata() })
{
RulesetID = ruleset.OnlineID,
- Beatmap =
- {
- Value = new BeatmapInfo
- {
- Metadata = new BeatmapMetadata()
- }
- }
});
}
diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs
index 5a0a7e71d4..8290af8f78 100644
--- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs
+++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomRequestsHandler.cs
@@ -4,12 +4,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using osu.Game.Beatmaps;
using osu.Game.Online.API;
+using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
+using osu.Game.Rulesets;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Components;
+using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual.OnlinePlay
{
@@ -33,9 +37,9 @@ namespace osu.Game.Tests.Visual.OnlinePlay
///
/// The API request to handle.
/// The local user to store in responses where required.
- /// The game base for cases where actual online requests need to be sent.
+ /// The beatmap manager to attempt to retrieve beatmaps from, prior to returning dummy beatmaps.
/// Whether the request was successfully handled.
- public bool HandleRequest(APIRequest request, APIUser localUser, OsuGameBase game)
+ public bool HandleRequest(APIRequest request, APIUser localUser, BeatmapManager beatmapManager)
{
switch (request)
{
@@ -128,6 +132,26 @@ namespace osu.Game.Tests.Visual.OnlinePlay
Statistics = new Dictionary()
});
return true;
+
+ case GetBeatmapsRequest getBeatmapsRequest:
+ var result = new List();
+
+ foreach (int id in getBeatmapsRequest.BeatmapIds)
+ {
+ var baseBeatmap = beatmapManager.QueryBeatmap(b => b.OnlineID == id);
+
+ if (baseBeatmap == null)
+ {
+ baseBeatmap = new TestBeatmap(new RulesetInfo { OnlineID = 0 }).BeatmapInfo;
+ baseBeatmap.OnlineID = id;
+ baseBeatmap.BeatmapSet!.OnlineID = id;
+ }
+
+ result.Add(OsuTestScene.CreateAPIBeatmap(baseBeatmap));
+ }
+
+ getBeatmapsRequest.TriggerSuccess(new GetBeatmapsResponse { Beatmaps = result });
+ return true;
}
return false;
diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs
index ec02655544..f287a04d71 100644
--- a/osu.Game/Tests/Visual/OsuTestScene.cs
+++ b/osu.Game/Tests/Visual/OsuTestScene.cs
@@ -225,12 +225,24 @@ namespace osu.Game.Tests.Visual
protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset);
///
- /// Returns a sample API Beatmap with BeatmapSet populated.
+ /// Returns a sample API beatmap with a populated beatmap set.
///
/// The ruleset to create the sample model using. osu! ruleset will be used if not specified.
- protected APIBeatmap CreateAPIBeatmap(RulesetInfo ruleset = null)
+ protected APIBeatmap CreateAPIBeatmap(RulesetInfo ruleset = null) => CreateAPIBeatmap(CreateBeatmap(ruleset ?? Ruleset.Value).BeatmapInfo);
+
+ ///
+ /// Constructs a sample API beatmap set containing a beatmap.
+ ///
+ /// The ruleset to create the sample model using. osu! ruleset will be used if not specified.
+ protected APIBeatmapSet CreateAPIBeatmapSet(RulesetInfo ruleset = null) => CreateAPIBeatmapSet(CreateBeatmap(ruleset ?? Ruleset.Value).BeatmapInfo);
+
+ ///
+ /// Constructs a sample API beatmap with a populated beatmap set from a given source beatmap.
+ ///
+ /// The source beatmap.
+ public static APIBeatmap CreateAPIBeatmap(IBeatmapInfo original)
{
- var beatmapSet = CreateAPIBeatmapSet(ruleset ?? Ruleset.Value);
+ var beatmapSet = CreateAPIBeatmapSet(original);
// Avoid circular reference.
var beatmap = beatmapSet.Beatmaps.First();
@@ -243,18 +255,16 @@ namespace osu.Game.Tests.Visual
}
///
- /// Returns a sample API BeatmapSet with beatmaps populated.
+ /// Constructs a sample API beatmap set containing a beatmap from a given source beatmap.
///
- /// The ruleset to create the sample model using. osu! ruleset will be used if not specified.
- protected APIBeatmapSet CreateAPIBeatmapSet(RulesetInfo ruleset = null)
+ /// The source beatmap.
+ public static APIBeatmapSet CreateAPIBeatmapSet(IBeatmapInfo original)
{
- var beatmap = CreateBeatmap(ruleset ?? Ruleset.Value).BeatmapInfo;
-
- Debug.Assert(beatmap.BeatmapSet != null);
+ Debug.Assert(original.BeatmapSet != null);
return new APIBeatmapSet
{
- OnlineID = ((IBeatmapSetInfo)beatmap.BeatmapSet).OnlineID,
+ OnlineID = original.BeatmapSet.OnlineID,
Status = BeatmapOnlineStatus.Ranked,
Covers = new BeatmapSetOnlineCovers
{
@@ -262,29 +272,29 @@ namespace osu.Game.Tests.Visual
Card = "https://assets.ppy.sh/beatmaps/163112/covers/card.jpg",
List = "https://assets.ppy.sh/beatmaps/163112/covers/list.jpg"
},
- Title = beatmap.Metadata.Title,
- TitleUnicode = beatmap.Metadata.TitleUnicode,
- Artist = beatmap.Metadata.Artist,
- ArtistUnicode = beatmap.Metadata.ArtistUnicode,
+ Title = original.Metadata.Title,
+ TitleUnicode = original.Metadata.TitleUnicode,
+ Artist = original.Metadata.Artist,
+ ArtistUnicode = original.Metadata.ArtistUnicode,
Author = new APIUser
{
- Username = beatmap.Metadata.Author.Username,
- Id = beatmap.Metadata.Author.OnlineID
+ Username = original.Metadata.Author.Username,
+ Id = original.Metadata.Author.OnlineID
},
- Source = beatmap.Metadata.Source,
- Tags = beatmap.Metadata.Tags,
+ Source = original.Metadata.Source,
+ Tags = original.Metadata.Tags,
Beatmaps = new[]
{
new APIBeatmap
{
- OnlineID = ((IBeatmapInfo)beatmap).OnlineID,
- OnlineBeatmapSetID = ((IBeatmapSetInfo)beatmap.BeatmapSet).OnlineID,
- Status = beatmap.Status,
- Checksum = beatmap.MD5Hash,
- AuthorID = beatmap.Metadata.Author.OnlineID,
- RulesetID = beatmap.Ruleset.OnlineID,
- StarRating = beatmap.StarRating,
- DifficultyName = beatmap.DifficultyName,
+ OnlineID = original.OnlineID,
+ OnlineBeatmapSetID = original.BeatmapSet.OnlineID,
+ Status = ((BeatmapInfo)original).Status,
+ Checksum = original.MD5Hash,
+ AuthorID = original.Metadata.Author.OnlineID,
+ RulesetID = original.Ruleset.OnlineID,
+ StarRating = original.StarRating,
+ DifficultyName = original.DifficultyName,
}
}
};
diff --git a/osu.Game/Utils/NamingUtils.cs b/osu.Game/Utils/NamingUtils.cs
new file mode 100644
index 0000000000..482e3d0954
--- /dev/null
+++ b/osu.Game/Utils/NamingUtils.cs
@@ -0,0 +1,61 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace osu.Game.Utils
+{
+ public static class NamingUtils
+ {
+ ///
+ /// Given a set of and a target ,
+ /// finds a "best" name closest to that is not in .
+ ///
+ ///
+ ///
+ /// This helper is most useful in scenarios when creating new objects in a set
+ /// (such as adding new difficulties to a beatmap set, or creating a clone of an existing object that needs a unique name).
+ /// If is already present in ,
+ /// this method will append the lowest possible number in brackets that doesn't conflict with
+ /// to and return that.
+ /// See osu.Game.Tests.Utils.NamingUtilsTest for concrete examples of behaviour.
+ ///
+ ///
+ /// and are compared in a case-insensitive manner,
+ /// so this method is safe to use for naming files in a platform-invariant manner.
+ ///
+ ///
+ public static string GetNextBestName(IEnumerable existingNames, string desiredName)
+ {
+ string pattern = $@"^(?i){Regex.Escape(desiredName)}(?-i)( \((?[1-9][0-9]*)\))?$";
+ var regex = new Regex(pattern, RegexOptions.Compiled);
+ var takenNumbers = new HashSet();
+
+ foreach (string name in existingNames)
+ {
+ var match = regex.Match(name);
+ if (!match.Success)
+ continue;
+
+ string copyNumberString = match.Groups[@"copyNumber"].Value;
+
+ if (string.IsNullOrEmpty(copyNumberString))
+ {
+ takenNumbers.Add(0);
+ continue;
+ }
+
+ takenNumbers.Add(int.Parse(copyNumberString));
+ }
+
+ int bestNumber = 0;
+ while (takenNumbers.Contains(bestNumber))
+ bestNumber += 1;
+
+ return bestNumber == 0
+ ? desiredName
+ : $"{desiredName} ({bestNumber})";
+ }
+ }
+}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 7b50c804ff..4c6f81defa 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -36,7 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 03a105673c..99b9de3fe2 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -60,7 +60,7 @@
-
+
@@ -83,7 +83,7 @@
-
+