From f0f739707f2e9a91cc4d64096afe4aae1e8a5ab0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 17:51:42 +0900 Subject: [PATCH 1/4] Add playlist support to match song select --- .../Multiplayer/TestSceneMatchSongSelect.cs | 101 +++++++++++++++++- osu.Game/Screens/Select/MatchSongSelect.cs | 42 +++----- 2 files changed, 114 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs index f6e4715182..434b265f9c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs @@ -3,9 +3,19 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Extensions; +using osu.Framework.Platform; +using osu.Framework.Screens; +using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Select; @@ -22,6 +32,72 @@ namespace osu.Game.Tests.Visual.Multiplayer [Resolved] private BeatmapManager beatmapManager { get; set; } + private BeatmapManager manager; + + private RulesetStore rulesets; + + private TestMatchSongSelect songSelect; + + [BackgroundDependencyLoader] + private void load(GameHost host, AudioManager audio) + { + Dependencies.Cache(rulesets = new RulesetStore(ContextFactory)); + Dependencies.Cache(manager = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, host, Beatmap.Default)); + + var beatmaps = new List(); + + for (int i = 0; i < 6; i++) + { + int beatmapId = 10 * 10 + i; + + int length = RNG.Next(30000, 200000); + double bpm = RNG.NextSingle(80, 200); + + beatmaps.Add(new BeatmapInfo + { + Ruleset = new OsuRuleset().RulesetInfo, + OnlineBeatmapID = beatmapId, + Path = "normal.osu", + Version = $"{beatmapId} (length {TimeSpan.FromMilliseconds(length):m\\:ss}, bpm {bpm:0.#})", + Length = length, + BPM = bpm, + BaseDifficulty = new BeatmapDifficulty + { + OverallDifficulty = 3.5f, + }, + }); + } + + manager.Import(new BeatmapSetInfo + { + OnlineBeatmapSetID = 10, + Hash = new MemoryStream(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())).ComputeMD5Hash(), + Metadata = new BeatmapMetadata + { + // Create random metadata, then we can check if sorting works based on these + Artist = "Some Artist " + RNG.Next(0, 9), + Title = $"Some Song (set id 10), max bpm {beatmaps.Max(b => b.BPM):0.#})", + AuthorString = "Some Guy " + RNG.Next(0, 9), + }, + Beatmaps = beatmaps, + DateAdded = DateTimeOffset.UtcNow, + }).Wait(); + } + + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("reset", () => + { + Ruleset.Value = new OsuRuleset().RulesetInfo; + Beatmap.SetDefault(); + }); + + AddStep("create song select", () => LoadScreen(songSelect = new TestMatchSongSelect())); + AddUntilStep("wait for present", () => songSelect.IsCurrentScreen()); + } + [SetUp] public void Setup() => Schedule(() => { @@ -29,9 +105,30 @@ namespace osu.Game.Tests.Visual.Multiplayer }); [Test] - public void TestLoadSongSelect() + public void TestItemAddedIfEmptyOnStart() { - AddStep("create song select", () => LoadScreen(new MatchSongSelect())); + AddStep("finalise selection", () => songSelect.FinaliseSelection()); + AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + } + + [Test] + public void TestItemAddedWhenCreateNewItemClicked() + { + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + } + + [Test] + public void TestItemNotAddedIfExistingOnStart() + { + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddStep("finalise selection", () => songSelect.FinaliseSelection()); + AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); + } + + private class TestMatchSongSelect : MatchSongSelect + { + public new MatchBeatmapDetailArea BeatmapDetails => (MatchBeatmapDetailArea)base.BeatmapDetails; } } } diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 94d65889d1..4edc968e8a 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -10,7 +9,6 @@ using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; -using osu.Game.Rulesets.Mods; using osu.Game.Screens.Multi; using osu.Game.Screens.Multi.Components; @@ -36,42 +34,32 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; } - protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea(); + protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea + { + CreateNewItem = createNewItem + }; protected override bool OnStart() { - var item = new PlaylistItem - { - Beatmap = { Value = Beatmap.Value.BeatmapInfo }, - Ruleset = { Value = Ruleset.Value }, - RulesetID = Ruleset.Value.ID ?? 0 - }; + if (Playlist.Count == 0) + createNewItem(); - item.RequiredMods.AddRange(Mods.Value); - - Selected?.Invoke(item); - - if (this.IsCurrentScreen()) - this.Exit(); + this.Exit(); return true; } - public override bool OnExiting(IScreen next) + private void createNewItem() { - if (base.OnExiting(next)) - return true; - - var firstItem = Playlist.FirstOrDefault(); - - if (firstItem != null) + PlaylistItem item = new PlaylistItem { - Ruleset.Value = firstItem.Ruleset.Value; - Beatmap.Value = beatmaps.GetWorkingBeatmap(firstItem.Beatmap.Value); - Mods.Value = firstItem.RequiredMods?.ToArray() ?? Array.Empty(); - } + Beatmap = { Value = Beatmap.Value.BeatmapInfo }, + Ruleset = { Value = Ruleset.Value } + }; - return false; + item.RequiredMods.AddRange(Mods.Value); + + Playlist.Add(item); } } } From f31220c1ee7aaf3f559b73248961d79208a089d8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 14 Feb 2020 19:56:01 +0900 Subject: [PATCH 2/4] Fix exception when adding duplicate items --- .../Visual/Multiplayer/TestSceneMatchSongSelect.cs | 8 ++++++++ osu.Game/Screens/Select/MatchSongSelect.cs | 2 ++ 2 files changed, 10 insertions(+) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs index 434b265f9c..5820da811d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchSongSelect.cs @@ -126,6 +126,14 @@ namespace osu.Game.Tests.Visual.Multiplayer AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1); } + [Test] + public void TestAddSameItemMultipleTimes() + { + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem()); + AddAssert("playlist has 2 items", () => Room.Playlist.Count == 2); + } + private class TestMatchSongSelect : MatchSongSelect { public new MatchBeatmapDetailArea BeatmapDetails => (MatchBeatmapDetailArea)base.BeatmapDetails; diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index 4edc968e8a..cb0d09b6bb 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -53,6 +54,7 @@ namespace osu.Game.Screens.Select { PlaylistItem item = new PlaylistItem { + ID = (Playlist.LastOrDefault()?.ID + 1) ?? 0, Beatmap = { Value = Beatmap.Value.BeatmapInfo }, Ruleset = { Value = Ruleset.Value } }; From 637c1dc8407d31c72023758b794ee9577ca01336 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Feb 2020 14:41:16 +0900 Subject: [PATCH 3/4] In the case of only one playlist item, update with current selection on select --- osu.Game/Screens/Select/MatchSongSelect.cs | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/MatchSongSelect.cs b/osu.Game/Screens/Select/MatchSongSelect.cs index cb0d09b6bb..a115ab9841 100644 --- a/osu.Game/Screens/Select/MatchSongSelect.cs +++ b/osu.Game/Screens/Select/MatchSongSelect.cs @@ -42,8 +42,16 @@ namespace osu.Game.Screens.Select protected override bool OnStart() { - if (Playlist.Count == 0) - createNewItem(); + switch (Playlist.Count) + { + case 0: + createNewItem(); + break; + + case 1: + populateItemFromCurrent(Playlist.Single()); + break; + } this.Exit(); @@ -55,13 +63,20 @@ namespace osu.Game.Screens.Select PlaylistItem item = new PlaylistItem { ID = (Playlist.LastOrDefault()?.ID + 1) ?? 0, - Beatmap = { Value = Beatmap.Value.BeatmapInfo }, - Ruleset = { Value = Ruleset.Value } }; - item.RequiredMods.AddRange(Mods.Value); + populateItemFromCurrent(item); Playlist.Add(item); } + + private void populateItemFromCurrent(PlaylistItem item) + { + item.Beatmap.Value = Beatmap.Value.BeatmapInfo; + item.Ruleset.Value = Ruleset.Value; + + item.RequiredMods.Clear(); + item.RequiredMods.AddRange(Mods.Value); + } } } From f54844d8a54e520947885fdf45ee4f11f8551328 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 15 Feb 2020 15:07:10 +0900 Subject: [PATCH 4/4] Schedule selection update handling in MatchSubScreen to avoid firing when not the current screen --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 890664e99b..bd9aceecc3 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -164,8 +164,8 @@ namespace osu.Game.Screens.Multi.Match { base.LoadComplete(); - Playlist.ItemsAdded += _ => updateSelectedItem(); - Playlist.ItemsRemoved += _ => updateSelectedItem(); + Playlist.ItemsAdded += _ => Scheduler.AddOnce(updateSelectedItem); + Playlist.ItemsRemoved += _ => Scheduler.AddOnce(updateSelectedItem); updateSelectedItem(); }