From 176bb4a4e22901a37761ab6e1812663d3ec6c7dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Feb 2022 15:25:54 +0900 Subject: [PATCH 01/38] Update desktop projects to target .NET 6 --- .run/osu! (Second Client).run.xml | 8 ++++---- .../osu.Game.Rulesets.EmptyFreeform.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.EmptyScrolling.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 4 ++-- osu.Desktop/osu.Desktop.csproj | 2 +- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Mania.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Osu.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Taiko.Tests.csproj | 4 ++-- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- .../osu.Game.Tournament.Tests.csproj | 4 ++-- osu.iOS.props | 2 +- 14 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.run/osu! (Second Client).run.xml b/.run/osu! (Second Client).run.xml index 599b4b986b..9a471df902 100644 --- a/.run/osu! (Second Client).run.xml +++ b/.run/osu! (Second Client).run.xml @@ -1,8 +1,8 @@ - - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index 3c6aaa39ca..cb922c5a58 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -20,7 +20,7 @@ WinExe - net5.0 + net6.0 osu.Game.Rulesets.EmptyFreeform.Tests - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 0719dd30df..5ecd9cc675 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -20,7 +20,7 @@ WinExe - net5.0 + net6.0 osu.Game.Rulesets.Pippidon.Tests - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index d0db43cc81..33ad0ac4f7 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -20,7 +20,7 @@ WinExe - net5.0 + net6.0 osu.Game.Rulesets.EmptyScrolling.Tests - \ No newline at end of file + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 0719dd30df..5ecd9cc675 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -20,7 +20,7 @@ WinExe - net5.0 + net6.0 osu.Game.Rulesets.Pippidon.Tests - \ No newline at end of file + diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 89b9ffb94b..5e203af1f2 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -1,6 +1,6 @@  - net5.0 + net6.0 WinExe true A free-to-win rhythm game. Rhythm is just a *click* away! diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 57b914bee6..434c0e0367 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 Exe false diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 13f2e25f05..fc6d900567 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -9,9 +9,9 @@ WinExe - net5.0 + net6.0 - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index d51a6da4f9..ddad2adfea 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -9,9 +9,9 @@ WinExe - net5.0 + net6.0 - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index fea2e408f6..bd4c3d3345 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -10,9 +10,9 @@ WinExe - net5.0 + net6.0 - \ No newline at end of file + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index ad3713e047..a6b8eb8651 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -9,9 +9,9 @@ WinExe - net5.0 + net6.0 - \ No newline at end of file + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 3b115d43e5..acf1e8470b 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -12,7 +12,7 @@ WinExe - net5.0 + net6.0 tests.ruleset diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 130fcfaca1..c7314a4969 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -11,7 +11,7 @@ WinExe - net5.0 + net6.0 @@ -20,4 +20,4 @@ - \ No newline at end of file + diff --git a/osu.iOS.props b/osu.iOS.props index 5978f6d685..7e5ab37257 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -63,7 +63,7 @@ - + $(NoWarn);NU1605 From 908c31c68764370e44e9e3a6055aa881a7ce1971 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Feb 2022 16:02:25 +0900 Subject: [PATCH 02/38] Update stream read operations to use new helper methods --- osu.Game/Database/ImportTask.cs | 5 ++--- osu.Game/IO/Archives/ArchiveReader.cs | 14 +++----------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/osu.Game/Database/ImportTask.cs b/osu.Game/Database/ImportTask.cs index cd9e396d13..d75c1a73e6 100644 --- a/osu.Game/Database/ImportTask.cs +++ b/osu.Game/Database/ImportTask.cs @@ -4,6 +4,7 @@ #nullable enable using System.IO; +using osu.Framework.Extensions; using osu.Game.IO.Archives; using osu.Game.Stores; using osu.Game.Utils; @@ -63,9 +64,7 @@ namespace osu.Game.Database if (!(stream is MemoryStream memoryStream)) { // This isn't used in any current path. May need to reconsider for performance reasons (ie. if we don't expect the incoming stream to be copied out). - byte[] buffer = new byte[stream.Length]; - stream.Read(buffer, 0, (int)stream.Length); - memoryStream = new MemoryStream(buffer); + memoryStream = new MemoryStream(stream.ReadAllBytesToArray()); } if (ZipUtils.IsZipArchive(memoryStream)) diff --git a/osu.Game/IO/Archives/ArchiveReader.cs b/osu.Game/IO/Archives/ArchiveReader.cs index 1d8da16c72..dab70eaf70 100644 --- a/osu.Game/IO/Archives/ArchiveReader.cs +++ b/osu.Game/IO/Archives/ArchiveReader.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; +using osu.Framework.Extensions; using osu.Framework.IO.Stores; namespace osu.Game.IO.Archives @@ -35,14 +36,7 @@ namespace osu.Game.IO.Archives public virtual byte[] Get(string name) { using (Stream input = GetStream(name)) - { - if (input == null) - return null; - - byte[] buffer = new byte[input.Length]; - input.Read(buffer); - return buffer; - } + return input?.ReadAllBytesToArray(); } public async Task GetAsync(string name, CancellationToken cancellationToken = default) @@ -52,9 +46,7 @@ namespace osu.Game.IO.Archives if (input == null) return null; - byte[] buffer = new byte[input.Length]; - await input.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); - return buffer; + return await input.ReadAllBytesToArrayAsync(cancellationToken).ConfigureAwait(false); } } } From 6005daeba8bda373622123167bc533e2738704d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Feb 2022 16:02:42 +0900 Subject: [PATCH 03/38] Fix fire-and-forget async calls to use `WaitSafely` --- osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 8f6ba6375f..7661cf671b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -829,7 +829,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem { BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID - }))); + })).WaitSafely()); AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2); @@ -860,11 +860,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem { BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID - }))); + })).WaitSafely()); AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2); - AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2)); + AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2).WaitSafely()); AddUntilStep("item removed from playlist", () => client.Room?.Playlist.Count == 1); AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent()); From a2c2b2bbb3dcbd87f9c4c08582b00b98f1096e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 17:52:59 +0100 Subject: [PATCH 04/38] Add flow for copying existing difficulty content --- osu.Game/Beatmaps/BeatmapManager.cs | 34 ++++++++------ .../Screens/Edit/CreateNewDifficultyDialog.cs | 45 +++++++++++++++++++ osu.Game/Screens/Edit/Editor.cs | 20 ++++++++- osu.Game/Screens/Edit/EditorLoader.cs | 7 ++- .../Edit/NewDifficultyCreationParameters.cs | 36 +++++++++++++++ osu.Game/Tests/Visual/EditorTestScene.cs | 2 +- 6 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs create mode 100644 osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 633eb8f15e..bd9cdba9fb 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -20,6 +20,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; +using osu.Game.Screens.Edit; using osu.Game.Skinning; using osu.Game.Stores; @@ -112,29 +113,36 @@ namespace osu.Game.Beatmaps /// The new difficulty will be backed by a model /// and represented by the returned . /// - public virtual WorkingBeatmap CreateNewBlankDifficulty(BeatmapSetInfo beatmapSetInfo, RulesetInfo rulesetInfo) + public virtual WorkingBeatmap CreateNewBlankDifficulty(NewDifficultyCreationParameters creationParameters) { - // fetch one of the existing difficulties to copy timing points and metadata from, - // so that the user doesn't have to fill all of that out again. - // this silently assumes that all difficulties have the same timing points and metadata, - // but cases where this isn't true seem rather rare / pathological. - var referenceBeatmap = GetWorkingBeatmap(beatmapSetInfo.Beatmaps.First()); + var referenceBeatmap = creationParameters.ReferenceBeatmap; + var targetBeatmapSet = creationParameters.BeatmapSet; - var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone()); + var newBeatmapInfo = new BeatmapInfo(creationParameters.Ruleset, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone()); // populate circular beatmap set info <-> beatmap info references manually. // several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()` // rely on them being freely traversable in both directions for correct operation. - beatmapSetInfo.Beatmaps.Add(newBeatmapInfo); - newBeatmapInfo.BeatmapSet = beatmapSetInfo; + targetBeatmapSet.Beatmaps.Add(newBeatmapInfo); + newBeatmapInfo.BeatmapSet = targetBeatmapSet; - var newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; - foreach (var timingPoint in referenceBeatmap.Beatmap.ControlPointInfo.TimingPoints) - newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone()); + IBeatmap newBeatmap; + + if (creationParameters.ClearAllObjects) + { + newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; + foreach (var timingPoint in referenceBeatmap.ControlPointInfo.TimingPoints) + newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone()); + } + else + { + newBeatmap = referenceBeatmap.Clone(); + newBeatmap.BeatmapInfo = newBeatmapInfo; + } beatmapModelManager.Save(newBeatmapInfo, newBeatmap); - workingBeatmapCache.Invalidate(beatmapSetInfo); + workingBeatmapCache.Invalidate(targetBeatmapSet); return GetWorkingBeatmap(newBeatmap.BeatmapInfo); } diff --git a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs new file mode 100644 index 0000000000..472f0e8948 --- /dev/null +++ b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays.Dialog; + +namespace osu.Game.Screens.Edit +{ + public class CreateNewDifficultyDialog : PopupDialog + { + /// + /// Delegate used to create new difficulties. + /// A value of in the clearAllObjects parameter + /// indicates that the new difficulty should have its hitobjects cleared; + /// otherwise, the new difficulty should be an exact copy of an existing one. + /// + public delegate void CreateNewDifficulty(bool clearAllObjects); + + public CreateNewDifficultyDialog(CreateNewDifficulty createNewDifficulty) + { + HeaderText = "Would you like to clear all objects?"; + + Icon = FontAwesome.Regular.Clone; + + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = "Yeah, let's start from scratch!", + Action = () => createNewDifficulty.Invoke(true) + }, + new PopupDialogCancelButton + { + Text = "No, create an exact copy of this difficulty", + Action = () => createNewDifficulty.Invoke(false) + }, + new PopupDialogCancelButton + { + Text = "I changed my mind, I want to keep editing this difficulty", + Action = () => { } + } + }; + } + } +} diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 2aec63fa65..c5578287e3 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -841,7 +841,25 @@ namespace osu.Game.Screens.Edit } protected void CreateNewDifficulty(RulesetInfo rulesetInfo) - => loader?.ScheduleSwitchToNewDifficulty(editorBeatmap.BeatmapInfo.BeatmapSet, rulesetInfo, GetState()); + { + if (!rulesetInfo.Equals(editorBeatmap.BeatmapInfo.Ruleset)) + { + switchToNewDifficulty(rulesetInfo, true); + return; + } + + dialogOverlay.Push(new CreateNewDifficultyDialog(clearAllObjects => switchToNewDifficulty(rulesetInfo, clearAllObjects))); + } + + private void switchToNewDifficulty(RulesetInfo rulesetInfo, bool clearAllObjects) + => loader?.ScheduleSwitchToNewDifficulty(new NewDifficultyCreationParameters + { + BeatmapSet = editorBeatmap.BeatmapInfo.BeatmapSet, + Ruleset = rulesetInfo, + ReferenceBeatmap = playableBeatmap, + ClearAllObjects = clearAllObjects, + EditorState = GetState() + }); private EditorMenuItem createDifficultySwitchMenu() { diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index de47411fdc..169b601a94 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -11,7 +11,6 @@ using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; -using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; @@ -80,12 +79,12 @@ namespace osu.Game.Screens.Edit } } - public void ScheduleSwitchToNewDifficulty(BeatmapSetInfo beatmapSetInfo, RulesetInfo rulesetInfo, EditorState editorState) + public void ScheduleSwitchToNewDifficulty(NewDifficultyCreationParameters creationParameters) => scheduleDifficultySwitch(() => { try { - return beatmapManager.CreateNewBlankDifficulty(beatmapSetInfo, rulesetInfo); + return beatmapManager.CreateNewBlankDifficulty(creationParameters); } catch (Exception ex) { @@ -94,7 +93,7 @@ namespace osu.Game.Screens.Edit Logger.Error(ex, ex.Message); return Beatmap.Value; } - }, editorState); + }, creationParameters.EditorState); public void ScheduleSwitchToExistingDifficulty(BeatmapInfo beatmapInfo, EditorState editorState) => scheduleDifficultySwitch(() => beatmapManager.GetWorkingBeatmap(beatmapInfo), editorState); diff --git a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs new file mode 100644 index 0000000000..dd03fd3644 --- /dev/null +++ b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs @@ -0,0 +1,36 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Beatmaps; +using osu.Game.Rulesets; + +namespace osu.Game.Screens.Edit +{ + public class NewDifficultyCreationParameters + { + /// + /// The that should contain the newly-created difficulty. + /// + public BeatmapSetInfo BeatmapSet { get; set; } + + /// + /// The that the new difficulty should be playable for. + /// + public RulesetInfo Ruleset { get; set; } + + /// + /// A reference upon which the new difficulty should be based. + /// + public IBeatmap ReferenceBeatmap { get; set; } + + /// + /// Whether all objects should be cleared from the new difficulty. + /// + public bool ClearAllObjects { get; set; } + + /// + /// The saved state of the previous which should be restored upon opening the newly-created difficulty. + /// + public EditorState EditorState { get; set; } + } +} diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 331bf04644..ff09598eef 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual return new TestWorkingBeatmapCache(this, audioManager, resources, storage, defaultBeatmap, host); } - public override WorkingBeatmap CreateNewBlankDifficulty(BeatmapSetInfo beatmapSetInfo, RulesetInfo rulesetInfo) + public override WorkingBeatmap CreateNewBlankDifficulty(NewDifficultyCreationParameters creationParameters) { // don't actually care about properly creating a difficulty for this context. return TestBeatmap; From 0d1171b7fae94ea769598bb2b5f0dff194c6c32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 17:56:51 +0100 Subject: [PATCH 05/38] Adjust existing test coverage to pass --- .../Editing/TestSceneEditorBeatmapCreation.cs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index a14c9aded3..89a9307f9f 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -10,6 +10,7 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Setup; @@ -92,7 +93,7 @@ namespace osu.Game.Tests.Visual.Editing } [Test] - public void TestCreateNewDifficulty() + public void TestCreateNewDifficulty([Values] bool sameRuleset) { string firstDifficultyName = Guid.NewGuid().ToString(); string secondDifficultyName = Guid.NewGuid().ToString(); @@ -111,7 +112,14 @@ namespace osu.Game.Tests.Visual.Editing }); AddAssert("can save again", () => Editor.Save()); - AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo)); + AddStep("create new difficulty", () => Editor.CreateNewDifficulty(sameRuleset ? new OsuRuleset().RulesetInfo : new CatchRuleset().RulesetInfo)); + + if (sameRuleset) + { + 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; @@ -154,7 +162,7 @@ namespace osu.Game.Tests.Visual.Editing } [Test] - public void TestCreateNewBeatmapFailsWithSameNamedDifficulties() + public void TestCreateNewBeatmapFailsWithSameNamedDifficulties([Values] bool sameRuleset) { Guid setId = Guid.Empty; const string duplicate_difficulty_name = "duplicate"; @@ -168,7 +176,14 @@ namespace osu.Game.Tests.Visual.Editing return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1); }); - AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo)); + AddStep("create new difficulty", () => Editor.CreateNewDifficulty(sameRuleset ? new OsuRuleset().RulesetInfo : new CatchRuleset().RulesetInfo)); + + if (sameRuleset) + { + 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; From eb939547a9978e0d4e47a65f90c3b5b902b7d988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 18:03:54 +0100 Subject: [PATCH 06/38] Add test coverage for difficulty copy flow --- .../Editing/TestSceneEditorBeatmapCreation.cs | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 89a9307f9f..91f667d8b0 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -9,13 +9,17 @@ using osu.Framework.Allocation; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Osu.UI; using osu.Game.Screens.Edit; using osu.Game.Screens.Edit.Setup; using osu.Game.Storyboards; using osu.Game.Tests.Resources; +using osuTK; using SharpCompress.Archives; using SharpCompress.Archives.Zip; @@ -99,6 +103,21 @@ namespace osu.Game.Tests.Visual.Editing string secondDifficultyName = Guid.NewGuid().ToString(); AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName); + AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 })); + AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[] + { + new HitCircle + { + Position = new Vector2(0), + StartTime = 0 + }, + new HitCircle + { + Position = OsuPlayfield.BASE_SIZE, + StartTime = 1000 + } + })); + AddStep("save beatmap", () => Editor.Save()); AddAssert("new beatmap persisted", () => { @@ -126,6 +145,80 @@ namespace osu.Game.Tests.Visual.Editing return difficultyName != null && difficultyName != firstDifficultyName; }); + AddAssert("created difficulty has timing point", () => + { + var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single(); + return timingPoint.Time == 0 && timingPoint.BeatLength == 1000; + }); + AddAssert("created difficulty has no objects", () => EditorBeatmap.HitObjects.Count == 0); + + AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); + AddStep("save beatmap", () => Editor.Save()); + AddAssert("new beatmap persisted", () => + { + var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == secondDifficultyName); + var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + + return beatmap != null + && beatmap.DifficultyName == secondDifficultyName + && set != null + && set.PerformRead(s => s.Beatmaps.Count == 2 && s.Beatmaps.Any(b => b.DifficultyName == secondDifficultyName)); + }); + } + + [Test] + public void TestCopyDifficulty() + { + string firstDifficultyName = Guid.NewGuid().ToString(); + string secondDifficultyName = Guid.NewGuid().ToString(); + + AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName); + AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 })); + AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[] + { + new HitCircle + { + Position = new Vector2(0), + StartTime = 0 + }, + new HitCircle + { + Position = OsuPlayfield.BASE_SIZE, + StartTime = 1000 + } + })); + + AddStep("save beatmap", () => Editor.Save()); + AddAssert("new beatmap persisted", () => + { + var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == firstDifficultyName); + var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + + return beatmap != null + && beatmap.DifficultyName == firstDifficultyName + && set != null + && set.PerformRead(s => s.Beatmaps.Single().ID == beatmap.ID); + }); + AddAssert("can save again", () => Editor.Save()); + + AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo)); + + AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog); + AddStep("confirm creation as a copy", () => DialogOverlay.CurrentDialog.Buttons.ElementAt(1).TriggerClick()); + + AddUntilStep("wait for created", () => + { + string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; + return difficultyName != null && difficultyName != firstDifficultyName; + }); + + AddAssert("created difficulty has timing point", () => + { + var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single(); + return timingPoint.Time == 0 && timingPoint.BeatLength == 1000; + }); + AddAssert("created difficulty has objects", () => EditorBeatmap.HitObjects.Count == 2); + AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); AddStep("save beatmap", () => Editor.Save()); AddAssert("new beatmap persisted", () => From fd1c8c361444f1bd7077379d64a1c03e5576c0f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 18:26:19 +0100 Subject: [PATCH 07/38] Add failing test coverage for correct beatmap difficulty copy --- osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 91f667d8b0..672e643e60 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -187,6 +187,7 @@ namespace osu.Game.Tests.Visual.Editing StartTime = 1000 } })); + AddStep("set approach rate", () => EditorBeatmap.Difficulty.ApproachRate = 4); AddStep("save beatmap", () => Editor.Save()); AddAssert("new beatmap persisted", () => @@ -218,6 +219,7 @@ namespace osu.Game.Tests.Visual.Editing return timingPoint.Time == 0 && timingPoint.BeatLength == 1000; }); AddAssert("created difficulty has objects", () => EditorBeatmap.HitObjects.Count == 2); + AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4); AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); AddStep("save beatmap", () => Editor.Save()); From 1bf5375e746f6be78a992594fda76b821b72cb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 18:40:51 +0100 Subject: [PATCH 08/38] Fix `BeatmapInfo`-associated member not copying --- osu.Game/Beatmaps/BeatmapManager.cs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index bd9cdba9fb..c350cfc111 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -118,18 +118,12 @@ namespace osu.Game.Beatmaps var referenceBeatmap = creationParameters.ReferenceBeatmap; var targetBeatmapSet = creationParameters.BeatmapSet; - var newBeatmapInfo = new BeatmapInfo(creationParameters.Ruleset, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone()); - - // populate circular beatmap set info <-> beatmap info references manually. - // several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()` - // rely on them being freely traversable in both directions for correct operation. - targetBeatmapSet.Beatmaps.Add(newBeatmapInfo); - newBeatmapInfo.BeatmapSet = targetBeatmapSet; - + BeatmapInfo newBeatmapInfo; IBeatmap newBeatmap; if (creationParameters.ClearAllObjects) { + newBeatmapInfo = new BeatmapInfo(creationParameters.Ruleset, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone()); newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; foreach (var timingPoint in referenceBeatmap.ControlPointInfo.TimingPoints) newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone()); @@ -137,9 +131,19 @@ namespace osu.Game.Beatmaps else { newBeatmap = referenceBeatmap.Clone(); - newBeatmap.BeatmapInfo = newBeatmapInfo; + newBeatmap.BeatmapInfo = newBeatmapInfo = referenceBeatmap.BeatmapInfo.Clone(); + // assign a new ID to the clone. + newBeatmapInfo.ID = Guid.NewGuid(); + // clear difficulty name to avoid clashes on save. + newBeatmapInfo.DifficultyName = string.Empty; } + // populate circular beatmap set info <-> beatmap info references manually. + // several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()` + // rely on them being freely traversable in both directions for correct operation. + targetBeatmapSet.Beatmaps.Add(newBeatmapInfo); + newBeatmapInfo.BeatmapSet = targetBeatmapSet; + beatmapModelManager.Save(newBeatmapInfo, newBeatmap); workingBeatmapCache.Invalidate(targetBeatmapSet); From 1292722a00e331933852f1842455a3e25108c4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 18:44:12 +0100 Subject: [PATCH 09/38] Add failing test coverage for correct combo colour copy --- .../Editing/TestSceneEditorBeatmapCreation.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 672e643e60..90b1d3a6f9 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -6,6 +6,8 @@ using System.IO; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; +using osu.Framework.Graphics; using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; @@ -188,6 +190,16 @@ namespace osu.Game.Tests.Visual.Editing } })); AddStep("set approach rate", () => EditorBeatmap.Difficulty.ApproachRate = 4); + AddStep("set combo colours", () => + { + var beatmapSkin = EditorBeatmap.BeatmapSkin.AsNonNull(); + beatmapSkin.ComboColours.Clear(); + beatmapSkin.ComboColours.AddRange(new[] + { + new Colour4(255, 0, 0, 255), + new Colour4(0, 0, 255, 255) + }); + }); AddStep("save beatmap", () => Editor.Save()); AddAssert("new beatmap persisted", () => @@ -220,6 +232,7 @@ namespace osu.Game.Tests.Visual.Editing }); AddAssert("created difficulty has objects", () => EditorBeatmap.HitObjects.Count == 2); AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4); + AddAssert("combo colours correctly copied", () => EditorBeatmap.BeatmapSkin.AsNonNull().ComboColours.Count == 2); AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); AddStep("save beatmap", () => Editor.Save()); From a144d6f8d67b0fe6c90021b3309682f323da9322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 18:50:11 +0100 Subject: [PATCH 10/38] Fix beatmap skin properties not copying --- osu.Game/Beatmaps/BeatmapManager.cs | 2 +- osu.Game/Screens/Edit/Editor.cs | 16 +++++---- .../Edit/NewDifficultyCreationParameters.cs | 34 ++++++++++++++++--- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index c350cfc111..a9d0576696 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -144,7 +144,7 @@ namespace osu.Game.Beatmaps targetBeatmapSet.Beatmaps.Add(newBeatmapInfo); newBeatmapInfo.BeatmapSet = targetBeatmapSet; - beatmapModelManager.Save(newBeatmapInfo, newBeatmap); + beatmapModelManager.Save(newBeatmapInfo, newBeatmap, creationParameters.ReferenceBeatmapSkin); workingBeatmapCache.Invalidate(targetBeatmapSet); return GetWorkingBeatmap(newBeatmap.BeatmapInfo); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c5578287e3..37d4dce60e 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -9,6 +9,7 @@ using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -853,13 +854,14 @@ namespace osu.Game.Screens.Edit private void switchToNewDifficulty(RulesetInfo rulesetInfo, bool clearAllObjects) => loader?.ScheduleSwitchToNewDifficulty(new NewDifficultyCreationParameters - { - BeatmapSet = editorBeatmap.BeatmapInfo.BeatmapSet, - Ruleset = rulesetInfo, - ReferenceBeatmap = playableBeatmap, - ClearAllObjects = clearAllObjects, - EditorState = GetState() - }); + ( + editorBeatmap.BeatmapInfo.BeatmapSet.AsNonNull(), + rulesetInfo, + playableBeatmap, + editorBeatmap.BeatmapSkin, + clearAllObjects, + GetState() + )); private EditorMenuItem createDifficultySwitchMenu() { diff --git a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs index dd03fd3644..aa7dac609b 100644 --- a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs +++ b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs @@ -1,8 +1,11 @@ // 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 osu.Game.Beatmaps; using osu.Game.Rulesets; +using osu.Game.Skinning; namespace osu.Game.Screens.Edit { @@ -11,26 +14,47 @@ namespace osu.Game.Screens.Edit /// /// The that should contain the newly-created difficulty. /// - public BeatmapSetInfo BeatmapSet { get; set; } + public BeatmapSetInfo BeatmapSet { get; } /// /// The that the new difficulty should be playable for. /// - public RulesetInfo Ruleset { get; set; } + public RulesetInfo Ruleset { get; } /// /// A reference upon which the new difficulty should be based. /// - public IBeatmap ReferenceBeatmap { get; set; } + public IBeatmap ReferenceBeatmap { get; } + + /// + /// A reference that the new difficulty should base its own skin upon. + /// + public ISkin? ReferenceBeatmapSkin { get; } /// /// Whether all objects should be cleared from the new difficulty. /// - public bool ClearAllObjects { get; set; } + public bool ClearAllObjects { get; } /// /// The saved state of the previous which should be restored upon opening the newly-created difficulty. /// - public EditorState EditorState { get; set; } + public EditorState EditorState { get; } + + public NewDifficultyCreationParameters( + BeatmapSetInfo beatmapSet, + RulesetInfo ruleset, + IBeatmap referenceBeatmap, + ISkin? referenceBeatmapSkin, + bool clearAllObjects, + EditorState editorState) + { + BeatmapSet = beatmapSet; + Ruleset = ruleset; + ReferenceBeatmap = referenceBeatmap; + ReferenceBeatmapSkin = referenceBeatmapSkin; + ClearAllObjects = clearAllObjects; + EditorState = editorState; + } } } From 6fd663a718b30de3b3064edc4a986d4cc61dfa2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 19:51:02 +0100 Subject: [PATCH 11/38] Apply some renames to convey difference between creation options better --- osu.Game/Beatmaps/BeatmapManager.cs | 4 ++-- osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs | 2 +- osu.Game/Screens/Edit/EditorLoader.cs | 2 +- .../Screens/Edit/NewDifficultyCreationParameters.cs | 13 +++++++++---- osu.Game/Tests/Visual/EditorTestScene.cs | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index a9d0576696..87051ef650 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -113,7 +113,7 @@ namespace osu.Game.Beatmaps /// The new difficulty will be backed by a model /// and represented by the returned . /// - public virtual WorkingBeatmap CreateNewBlankDifficulty(NewDifficultyCreationParameters creationParameters) + public virtual WorkingBeatmap CreateNewDifficulty(NewDifficultyCreationParameters creationParameters) { var referenceBeatmap = creationParameters.ReferenceBeatmap; var targetBeatmapSet = creationParameters.BeatmapSet; @@ -121,7 +121,7 @@ namespace osu.Game.Beatmaps BeatmapInfo newBeatmapInfo; IBeatmap newBeatmap; - if (creationParameters.ClearAllObjects) + if (creationParameters.CreateBlank) { newBeatmapInfo = new BeatmapInfo(creationParameters.Ruleset, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone()); newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; diff --git a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs index 472f0e8948..138e13bda1 100644 --- a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs +++ b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Edit public CreateNewDifficultyDialog(CreateNewDifficulty createNewDifficulty) { - HeaderText = "Would you like to clear all objects?"; + HeaderText = "Would you like to create a blank difficulty?"; Icon = FontAwesome.Regular.Clone; diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index 169b601a94..be3e68c857 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -84,7 +84,7 @@ namespace osu.Game.Screens.Edit { try { - return beatmapManager.CreateNewBlankDifficulty(creationParameters); + return beatmapManager.CreateNewDifficulty(creationParameters); } catch (Exception ex) { diff --git a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs index aa7dac609b..a6458a9456 100644 --- a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs +++ b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs @@ -32,9 +32,14 @@ namespace osu.Game.Screens.Edit public ISkin? ReferenceBeatmapSkin { get; } /// - /// Whether all objects should be cleared from the new difficulty. + /// Whether the new difficulty should be blank. /// - public bool ClearAllObjects { get; } + /// + /// A blank difficulty will have no objects, no control points other than timing points taken from + /// and will not share values with , + /// but it will share metadata and timing information with . + /// + public bool CreateBlank { get; } /// /// The saved state of the previous which should be restored upon opening the newly-created difficulty. @@ -46,14 +51,14 @@ namespace osu.Game.Screens.Edit RulesetInfo ruleset, IBeatmap referenceBeatmap, ISkin? referenceBeatmapSkin, - bool clearAllObjects, + bool createBlank, EditorState editorState) { BeatmapSet = beatmapSet; Ruleset = ruleset; ReferenceBeatmap = referenceBeatmap; ReferenceBeatmapSkin = referenceBeatmapSkin; - ClearAllObjects = clearAllObjects; + CreateBlank = createBlank; EditorState = editorState; } } diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index ff09598eef..8c8a106791 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual return new TestWorkingBeatmapCache(this, audioManager, resources, storage, defaultBeatmap, host); } - public override WorkingBeatmap CreateNewBlankDifficulty(NewDifficultyCreationParameters creationParameters) + public override WorkingBeatmap CreateNewDifficulty(NewDifficultyCreationParameters creationParameters) { // don't actually care about properly creating a difficulty for this context. return TestBeatmap; From 90c48de9f8d68d2cdafcdde863ea671320449e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 20:01:47 +0100 Subject: [PATCH 12/38] Add failing test coverage for save of copied beatmap keeping old beatmap file --- .../Editing/TestSceneEditorBeatmapCreation.cs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 90b1d3a6f9..0025e88e62 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -12,6 +12,7 @@ using osu.Framework.Screens; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Osu; @@ -236,16 +237,24 @@ namespace osu.Game.Tests.Visual.Editing AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); AddStep("save beatmap", () => Editor.Save()); + + BeatmapInfo refetchedBeatmap = null; + Live refetchedBeatmapSet = null; + + AddStep("refetch from database", () => + { + refetchedBeatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == secondDifficultyName); + refetchedBeatmapSet = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); + }); + AddAssert("new beatmap persisted", () => { - var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == secondDifficultyName); - var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); - - return beatmap != null - && beatmap.DifficultyName == secondDifficultyName - && set != null - && set.PerformRead(s => s.Beatmaps.Count == 2 && s.Beatmaps.Any(b => b.DifficultyName == secondDifficultyName)); + return refetchedBeatmap != null + && refetchedBeatmap.DifficultyName == secondDifficultyName + && refetchedBeatmapSet != null + && refetchedBeatmapSet.PerformRead(s => s.Beatmaps.Count == 2 && s.Beatmaps.Any(b => b.DifficultyName == secondDifficultyName)); }); + AddAssert("old beatmap file not deleted", () => refetchedBeatmapSet.AsNonNull().PerformRead(s => s.Files.Count == 2)); } [Test] From ecd6a68c6f0814cbd9a646f4dca4abf758162276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 6 Feb 2022 20:05:32 +0100 Subject: [PATCH 13/38] Clear hash when creating copy of existing difficulty --- osu.Game/Beatmaps/BeatmapManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 87051ef650..4fa07ff518 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -136,6 +136,8 @@ namespace osu.Game.Beatmaps newBeatmapInfo.ID = Guid.NewGuid(); // clear difficulty name to avoid clashes on save. newBeatmapInfo.DifficultyName = string.Empty; + // also clear the hash, as that's what is used to match .osu files with their corresponding realm beatmaps. + newBeatmapInfo.Hash = string.Empty; } // populate circular beatmap set info <-> beatmap info references manually. From 13abc392bd139305ac876df335139580ce2f4035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 13 Feb 2022 18:54:52 +0100 Subject: [PATCH 14/38] Add failing test coverage for not copying online properties --- .../Visual/Editing/TestSceneEditorBeatmapCreation.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index 0025e88e62..b4559ac9fa 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -201,6 +201,11 @@ namespace osu.Game.Tests.Visual.Editing new Colour4(0, 0, 255, 255) }); }); + AddStep("set status & online ID", () => + { + EditorBeatmap.BeatmapInfo.OnlineID = 123456; + EditorBeatmap.BeatmapInfo.Status = BeatmapOnlineStatus.WIP; + }); AddStep("save beatmap", () => Editor.Save()); AddAssert("new beatmap persisted", () => @@ -235,6 +240,9 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4); AddAssert("combo colours correctly copied", () => EditorBeatmap.BeatmapSkin.AsNonNull().ComboColours.Count == 2); + AddAssert("status not copied", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.None); + AddAssert("online ID not copied", () => EditorBeatmap.BeatmapInfo.OnlineID == -1); + AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); AddStep("save beatmap", () => Editor.Save()); From 5dabc9282c0e1e3be5538cd4c7996d67eae6197e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 13 Feb 2022 19:04:11 +0100 Subject: [PATCH 15/38] Change `BeatmapInfo` copy logic to be opt-in rather than opt-out --- osu.Game/Beatmaps/BeatmapManager.cs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 4fa07ff518..4dd0e08dab 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -131,13 +131,28 @@ namespace osu.Game.Beatmaps else { newBeatmap = referenceBeatmap.Clone(); - newBeatmap.BeatmapInfo = newBeatmapInfo = referenceBeatmap.BeatmapInfo.Clone(); - // assign a new ID to the clone. - newBeatmapInfo.ID = Guid.NewGuid(); - // clear difficulty name to avoid clashes on save. - newBeatmapInfo.DifficultyName = string.Empty; - // also clear the hash, as that's what is used to match .osu files with their corresponding realm beatmaps. - newBeatmapInfo.Hash = string.Empty; + + var referenceBeatmapInfo = referenceBeatmap.BeatmapInfo; + newBeatmap.BeatmapInfo = newBeatmapInfo = new BeatmapInfo(referenceBeatmapInfo.Ruleset, referenceBeatmapInfo.Difficulty.Clone(), referenceBeatmapInfo.Metadata.DeepClone()) + { + // Only selected appropriate properties are copied over. + // Things like database ID, online status/ID, MD5 hash, star rating, etc. are omitted + // because they should not be copied over and/or they will be recomputed on save. + AudioLeadIn = referenceBeatmapInfo.AudioLeadIn, + StackLeniency = referenceBeatmapInfo.StackLeniency, + SpecialStyle = referenceBeatmapInfo.SpecialStyle, + LetterboxInBreaks = referenceBeatmapInfo.LetterboxInBreaks, + WidescreenStoryboard = referenceBeatmapInfo.WidescreenStoryboard, + EpilepsyWarning = referenceBeatmapInfo.EpilepsyWarning, + SamplesMatchPlaybackRate = referenceBeatmapInfo.SamplesMatchPlaybackRate, + DistanceSpacing = referenceBeatmapInfo.DistanceSpacing, + BeatDivisor = referenceBeatmapInfo.BeatDivisor, + GridSize = referenceBeatmapInfo.GridSize, + TimelineZoom = referenceBeatmapInfo.TimelineZoom, + Countdown = referenceBeatmapInfo.Countdown, + CountdownOffset = referenceBeatmapInfo.CountdownOffset, + Bookmarks = (int[])referenceBeatmapInfo.Bookmarks.Clone() + }; } // populate circular beatmap set info <-> beatmap info references manually. From e304c031dcdffdcbd66f0f896ee160f79ee7a86d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Feb 2022 21:53:56 +0900 Subject: [PATCH 16/38] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 1a2859c851..6b3142fbdc 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,7 +52,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a9c0226951..847832f8ac 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 4a1dc53281..00c9653146 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -60,7 +60,7 @@ - + @@ -83,7 +83,7 @@ - + From c5019fefb0c9ed0a212167851acc082fe5f4e618 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Feb 2022 22:35:08 +0900 Subject: [PATCH 17/38] Update CI runs to target net6.0 --- .github/workflows/ci.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c52802cf6..ec3816d541 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,10 +20,10 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Install .NET 5.0.x + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v1 with: - dotnet-version: "5.0.x" + dotnet-version: "6.0.x" # FIXME: libavformat is not included in Ubuntu. Let's fix that. # https://github.com/ppy/osu-framework/issues/4349 @@ -65,10 +65,10 @@ jobs: run: | $VM_ASSETS/select-xamarin-sdk-v2.sh --mono=6.12 --android=11.2 - - name: Install .NET 5.0.x + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v1 with: - dotnet-version: "5.0.x" + dotnet-version: "6.0.x" # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono # cannot accept .sln(f) files as arguments. @@ -84,10 +84,10 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Install .NET 5.0.x + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v1 with: - dotnet-version: "5.0.x" + dotnet-version: "6.0.x" # Contrary to seemingly any other msbuild, msbuild running on macOS/Mono # cannot accept .sln(f) files as arguments. @@ -102,17 +102,17 @@ jobs: - name: Checkout uses: actions/checkout@v2 - # FIXME: Tools won't run in .NET 5.0 unless you install 3.1.x LTS side by side. + # FIXME: Tools won't run in .NET 6.0 unless you install 3.1.x LTS side by side. # https://itnext.io/how-to-support-multiple-net-sdks-in-github-actions-workflows-b988daa884e - name: Install .NET 3.1.x LTS uses: actions/setup-dotnet@v1 with: dotnet-version: "3.1.x" - - name: Install .NET 5.0.x + - name: Install .NET 6.0.x uses: actions/setup-dotnet@v1 with: - dotnet-version: "5.0.x" + dotnet-version: "6.0.x" - name: Restore Tools run: dotnet tool restore From 70ba6fb7dc2e48712886a6ae3ad4eb22079e4136 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Feb 2022 22:35:30 +0900 Subject: [PATCH 18/38] Update .NET version in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1dfcab416..7ace47a74f 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ You can see some examples of custom rulesets by visiting the [custom ruleset dir Please make sure you have the following prerequisites: -- A desktop platform with the [.NET 5.0 SDK](https://dotnet.microsoft.com/download) installed. +- A desktop platform with the [.NET 6.0 SDK](https://dotnet.microsoft.com/download) installed. - When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). - When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/). - When running on Linux, please have a system-wide FFmpeg installation available to support video decoding. From 9b7d9d42bcd01f84375cc38d5f6bf4ab74f996a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Feb 2022 22:48:04 +0900 Subject: [PATCH 19/38] Update reference to `NetAnalyzers` --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 894ea25c8b..6e7015fa26 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,7 +18,7 @@ - + $(MSBuildThisFileDirectory)CodeAnalysis\osu.ruleset From 9ad7b5d51caab9433c2eaaecbce6a1e4dc687516 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Feb 2022 22:52:30 +0900 Subject: [PATCH 20/38] Remove no longer required `NoWarn` spec --- Directory.Build.props | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6e7015fa26..c1682638c2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -32,13 +32,8 @@ NU1701: DeepEqual is not netstandard-compatible. This is fine since we run tests with .NET Framework anyway. This is required due to https://github.com/NuGet/Home/issues/5740 - - CA9998: - Microsoft.CodeAnalysis.FxCopAnalyzers has been deprecated. - The entire package will be able to be removed after migrating to .NET 5, - as analysers are shipped as part of the .NET 5 SDK anyway. --> - $(NoWarn);NU1701;CA9998 + $(NoWarn);NU1701 false From b581ca14cca29e7c8fb28bcfbb55e0aec0ae7389 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 02:32:38 +0900 Subject: [PATCH 21/38] Update usages in line with `BorderColour` type change --- osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs index deb2e6baf6..c6477d1781 100644 --- a/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs +++ b/osu.Game/Graphics/UserInterfaceV2/SwitchButton.cs @@ -114,7 +114,7 @@ namespace osu.Game.Graphics.UserInterfaceV2 private class CircularBorderContainer : CircularContainer { - public void TransformBorderTo(SRGBColour colour) + public void TransformBorderTo(ColourInfo colour) => this.TransformTo(nameof(BorderColour), colour, 250, Easing.OutQuint); } } From 02f58a82fc4682df861a6069a12316d3bf474084 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 02:35:08 +0900 Subject: [PATCH 22/38] Use `WaitSafely()` in tests where it was not already being used --- .../Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs | 3 ++- .../Multiplayer/TestSceneMultiplayerPlaylist.cs | 10 +++++----- .../Multiplayer/TestSceneMultiplayerQueueList.cs | 12 ++++++------ .../Visual/Multiplayer/TestSceneTeamVersus.cs | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs index c7eeff81fe..cd14a98751 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using NUnit.Framework; +using osu.Framework.Extensions; using osu.Framework.Testing; using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; @@ -71,7 +72,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("change queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers - })); + }).WaitSafely()); AddUntilStep("api room updated", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs index 936798e6b4..5dd9fb9fe2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual.Multiplayer importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0); }); - AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers })); + AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); } [Test] @@ -97,19 +97,19 @@ namespace osu.Game.Tests.Visual.Multiplayer addItemStep(); addItemStep(); - AddStep("finish current item", () => Client.FinishCurrentItem()); + AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); assertItemInHistoryListStep(1, 0); assertItemInQueueListStep(2, 0); assertItemInQueueListStep(3, 1); - AddStep("finish current item", () => Client.FinishCurrentItem()); + AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); assertItemInHistoryListStep(2, 0); assertItemInHistoryListStep(1, 1); assertItemInQueueListStep(3, 0); - AddStep("finish current item", () => Client.FinishCurrentItem()); + AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); assertItemInHistoryListStep(3, 0); assertItemInHistoryListStep(2, 1); @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestListsClearedWhenRoomLeft() { addItemStep(); - AddStep("finish current item", () => Client.FinishCurrentItem()); + AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); AddStep("leave room", () => RoomManager.PartRoom()); AddUntilStep("wait for room part", () => !RoomJoined); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs index ddf794b437..80b20ed59f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs @@ -65,13 +65,13 @@ namespace osu.Game.Tests.Visual.Multiplayer importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0); }); - AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers })); + AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); } [Test] public void TestDeleteButtonAlwaysVisibleForHost() { - AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers })); + AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); addPlaylistItem(() => API.LocalUser.Value.OnlineID); @@ -83,7 +83,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDeleteButtonOnlyVisibleForItemOwnerIfNotHost() { - AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers })); + AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); AddStep("join other user", () => Client.AddUser(new APIUser { Id = 1234 })); @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestCurrentItemDoesNotHaveDeleteButton() { - AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers })); + AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); addPlaylistItem(() => API.LocalUser.Value.OnlineID); @@ -110,7 +110,7 @@ namespace osu.Game.Tests.Visual.Multiplayer assertDeleteButtonVisibility(0, false); assertDeleteButtonVisibility(1, true); - AddStep("finish current item", () => Client.FinishCurrentItem()); + AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); AddUntilStep("wait for next item to be selected", () => Client.Room?.Settings.PlaylistItemId == 2); AddUntilStep("wait for two items in playlist", () => playlist.ChildrenOfType().Count() == 2); @@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual.Multiplayer BeatmapID = importedBeatmap.OnlineID, }); - Client.AddUserPlaylistItem(userId(), item); + Client.AddUserPlaylistItem(userId(), item).WaitSafely(); itemId = item.ID; }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 781f0a1824..2837d75553 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -143,7 +143,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("change match type", () => client.ChangeSettings(new MultiplayerRoomSettings { MatchType = MatchType.TeamVersus - })); + }).WaitSafely()); AddUntilStep("api room updated to team versus", () => client.APIRoom?.Type.Value == MatchType.TeamVersus); } From 8da0800d7fc70d213ab5401e97d537f308d75cf5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 02:47:35 +0900 Subject: [PATCH 23/38] Update `ChangeFocus` usage in line with framework changes --- osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs index 3fd56ece58..27743e709f 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/DrawableLoungeRoom.cs @@ -246,7 +246,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge { base.LoadComplete(); - Schedule(() => GetContainingInputManager().ChangeFocus(passwordTextBox)); + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(passwordTextBox)); passwordTextBox.OnCommit += (_, __) => performJoin(); } From 4bd58cfde160398726aaffb80e93d630a34029f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Feb 2022 18:52:19 +0100 Subject: [PATCH 24/38] Update one more custom transform with `BorderColour` type change --- osu.Game/Overlays/Volume/MuteButton.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Volume/MuteButton.cs b/osu.Game/Overlays/Volume/MuteButton.cs index bcc9394aba..e9d3b31207 100644 --- a/osu.Game/Overlays/Volume/MuteButton.cs +++ b/osu.Game/Overlays/Volume/MuteButton.cs @@ -79,13 +79,13 @@ namespace osu.Game.Overlays.Volume protected override bool OnHover(HoverEvent e) { - Content.TransformTo, SRGBColour>("BorderColour", hoveredColour, 500, Easing.OutQuint); + Content.TransformTo, ColourInfo>("BorderColour", hoveredColour, 500, Easing.OutQuint); return false; } protected override void OnHoverLost(HoverLostEvent e) { - Content.TransformTo, SRGBColour>("BorderColour", unhoveredColour, 500, Easing.OutQuint); + Content.TransformTo, ColourInfo>("BorderColour", unhoveredColour, 500, Easing.OutQuint); } } } From 7e75fa7117ebabf0e5cb1c8ad1b5e5d79349047a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Feb 2022 19:52:08 +0100 Subject: [PATCH 25/38] Revert "Change `BeatmapInfo` copy logic to be opt-in rather than opt-out" This reverts commit 5dabc9282c0e1e3be5538cd4c7996d67eae6197e. --- osu.Game/Beatmaps/BeatmapManager.cs | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 4dd0e08dab..4fa07ff518 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -131,28 +131,13 @@ namespace osu.Game.Beatmaps else { newBeatmap = referenceBeatmap.Clone(); - - var referenceBeatmapInfo = referenceBeatmap.BeatmapInfo; - newBeatmap.BeatmapInfo = newBeatmapInfo = new BeatmapInfo(referenceBeatmapInfo.Ruleset, referenceBeatmapInfo.Difficulty.Clone(), referenceBeatmapInfo.Metadata.DeepClone()) - { - // Only selected appropriate properties are copied over. - // Things like database ID, online status/ID, MD5 hash, star rating, etc. are omitted - // because they should not be copied over and/or they will be recomputed on save. - AudioLeadIn = referenceBeatmapInfo.AudioLeadIn, - StackLeniency = referenceBeatmapInfo.StackLeniency, - SpecialStyle = referenceBeatmapInfo.SpecialStyle, - LetterboxInBreaks = referenceBeatmapInfo.LetterboxInBreaks, - WidescreenStoryboard = referenceBeatmapInfo.WidescreenStoryboard, - EpilepsyWarning = referenceBeatmapInfo.EpilepsyWarning, - SamplesMatchPlaybackRate = referenceBeatmapInfo.SamplesMatchPlaybackRate, - DistanceSpacing = referenceBeatmapInfo.DistanceSpacing, - BeatDivisor = referenceBeatmapInfo.BeatDivisor, - GridSize = referenceBeatmapInfo.GridSize, - TimelineZoom = referenceBeatmapInfo.TimelineZoom, - Countdown = referenceBeatmapInfo.Countdown, - CountdownOffset = referenceBeatmapInfo.CountdownOffset, - Bookmarks = (int[])referenceBeatmapInfo.Bookmarks.Clone() - }; + newBeatmap.BeatmapInfo = newBeatmapInfo = referenceBeatmap.BeatmapInfo.Clone(); + // assign a new ID to the clone. + newBeatmapInfo.ID = Guid.NewGuid(); + // clear difficulty name to avoid clashes on save. + newBeatmapInfo.DifficultyName = string.Empty; + // also clear the hash, as that's what is used to match .osu files with their corresponding realm beatmaps. + newBeatmapInfo.Hash = string.Empty; } // populate circular beatmap set info <-> beatmap info references manually. From 40cfee34211387866835612abf142b893b5498c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Feb 2022 19:54:40 +0100 Subject: [PATCH 26/38] Explicitly reset online ID and beatmap status on copy --- osu.Game/Beatmaps/BeatmapManager.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 4fa07ff518..884209ee56 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -136,8 +136,11 @@ namespace osu.Game.Beatmaps newBeatmapInfo.ID = Guid.NewGuid(); // clear difficulty name to avoid clashes on save. newBeatmapInfo.DifficultyName = string.Empty; - // also clear the hash, as that's what is used to match .osu files with their corresponding realm beatmaps. + // 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. + newBeatmapInfo.OnlineID = -1; + newBeatmapInfo.Status = BeatmapOnlineStatus.None; } // populate circular beatmap set info <-> beatmap info references manually. From 1685e214d36463e225971c6ffef3fad73aae0735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Feb 2022 19:59:54 +0100 Subject: [PATCH 27/38] Adjust test coverage to cover desired copy naming scheme --- .../Editing/TestSceneEditorBeatmapCreation.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs index b4559ac9fa..0a2f622da1 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs @@ -172,10 +172,10 @@ namespace osu.Game.Tests.Visual.Editing [Test] public void TestCopyDifficulty() { - string firstDifficultyName = Guid.NewGuid().ToString(); - string secondDifficultyName = Guid.NewGuid().ToString(); + string originalDifficultyName = Guid.NewGuid().ToString(); + string copyDifficultyName = $"{originalDifficultyName} (copy)"; - AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName); + AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = originalDifficultyName); AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 })); AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[] { @@ -210,11 +210,11 @@ namespace osu.Game.Tests.Visual.Editing AddStep("save beatmap", () => Editor.Save()); AddAssert("new beatmap persisted", () => { - var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == firstDifficultyName); + var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == originalDifficultyName); var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); return beatmap != null - && beatmap.DifficultyName == firstDifficultyName + && beatmap.DifficultyName == originalDifficultyName && set != null && set.PerformRead(s => s.Beatmaps.Single().ID == beatmap.ID); }); @@ -228,9 +228,10 @@ namespace osu.Game.Tests.Visual.Editing AddUntilStep("wait for created", () => { string difficultyName = Editor.ChildrenOfType().SingleOrDefault()?.BeatmapInfo.DifficultyName; - return difficultyName != null && difficultyName != firstDifficultyName; + return difficultyName != null && difficultyName != originalDifficultyName; }); + AddAssert("created difficulty has copy suffix in name", () => EditorBeatmap.BeatmapInfo.DifficultyName == copyDifficultyName); AddAssert("created difficulty has timing point", () => { var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single(); @@ -243,7 +244,6 @@ namespace osu.Game.Tests.Visual.Editing AddAssert("status not copied", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.None); AddAssert("online ID not copied", () => EditorBeatmap.BeatmapInfo.OnlineID == -1); - AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName); AddStep("save beatmap", () => Editor.Save()); BeatmapInfo refetchedBeatmap = null; @@ -251,16 +251,19 @@ namespace osu.Game.Tests.Visual.Editing AddStep("refetch from database", () => { - refetchedBeatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == secondDifficultyName); + refetchedBeatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == copyDifficultyName); refetchedBeatmapSet = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID); }); AddAssert("new beatmap persisted", () => { return refetchedBeatmap != null - && refetchedBeatmap.DifficultyName == secondDifficultyName + && refetchedBeatmap.DifficultyName == copyDifficultyName && refetchedBeatmapSet != null - && refetchedBeatmapSet.PerformRead(s => s.Beatmaps.Count == 2 && s.Beatmaps.Any(b => b.DifficultyName == secondDifficultyName)); + && refetchedBeatmapSet.PerformRead(s => + s.Beatmaps.Count == 2 + && s.Beatmaps.Any(b => b.DifficultyName == originalDifficultyName) + && s.Beatmaps.Any(b => b.DifficultyName == copyDifficultyName)); }); AddAssert("old beatmap file not deleted", () => refetchedBeatmapSet.AsNonNull().PerformRead(s => s.Files.Count == 2)); } From 62214471647382ff03bf1449db2c03bde8cfa9de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Feb 2022 20:19:12 +0100 Subject: [PATCH 28/38] Append copy suffix on creating copy of difficulty --- osu.Game/Beatmaps/BeatmapManager.cs | 4 ++-- osu.Game/Screens/Edit/Editor.cs | 2 +- osu.Game/Screens/Edit/EditorLoader.cs | 9 ++++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 884209ee56..d1b8e88743 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -134,8 +134,8 @@ namespace osu.Game.Beatmaps newBeatmap.BeatmapInfo = newBeatmapInfo = referenceBeatmap.BeatmapInfo.Clone(); // assign a new ID to the clone. newBeatmapInfo.ID = Guid.NewGuid(); - // clear difficulty name to avoid clashes on save. - newBeatmapInfo.DifficultyName = string.Empty; + // add "(copy)" suffix to difficulty name to avoid clashes on save. + 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/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 37d4dce60e..7a3c4f2a19 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -857,7 +857,7 @@ namespace osu.Game.Screens.Edit ( editorBeatmap.BeatmapInfo.BeatmapSet.AsNonNull(), rulesetInfo, - playableBeatmap, + editorBeatmap, editorBeatmap.BeatmapSkin, clearAllObjects, GetState() diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index be3e68c857..505a57f157 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -84,7 +84,14 @@ namespace osu.Game.Screens.Edit { try { - return beatmapManager.CreateNewDifficulty(creationParameters); + var refetchedBeatmap = beatmapManager.GetWorkingBeatmap(creationParameters.ReferenceBeatmap.BeatmapInfo); + return beatmapManager.CreateNewDifficulty(new NewDifficultyCreationParameters( + refetchedBeatmap.BeatmapSetInfo, + refetchedBeatmap.BeatmapInfo.Ruleset, + refetchedBeatmap.Beatmap, + refetchedBeatmap.Skin, + creationParameters.CreateBlank, + creationParameters.EditorState)); } catch (Exception ex) { From e45a2ae0fc9b24af51454589be31923cb80543ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 14 Feb 2022 20:56:05 +0100 Subject: [PATCH 29/38] Restructure difficulty copy flow to adapt to latest changes --- osu.Game/Beatmaps/BeatmapManager.cs | 83 +++++++++++-------- .../Screens/Edit/CreateNewDifficultyDialog.cs | 12 +-- osu.Game/Screens/Edit/Editor.cs | 27 ++---- osu.Game/Screens/Edit/EditorLoader.cs | 21 ++--- .../Edit/NewDifficultyCreationParameters.cs | 65 --------------- osu.Game/Tests/Visual/EditorTestScene.cs | 8 +- 6 files changed, 83 insertions(+), 133 deletions(-) delete mode 100644 osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index d1b8e88743..777d5db2ad 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -20,7 +20,6 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; -using osu.Game.Screens.Edit; using osu.Game.Skinning; using osu.Game.Stores; @@ -109,55 +108,73 @@ namespace osu.Game.Beatmaps } /// - /// Add a new difficulty to the beatmap set represented by the provided . + /// Add a new difficulty to the provided based on the provided . /// The new difficulty will be backed by a model /// and represented by the returned . /// - public virtual WorkingBeatmap CreateNewDifficulty(NewDifficultyCreationParameters creationParameters) + /// + /// Contrary to , this method does not preserve hitobjects and beatmap-level settings from . + /// The created beatmap will have zero hitobjects and will have default settings (including difficulty settings), but will preserve metadata and existing timing points. + /// + /// The to add the new difficulty to. + /// The to use as a baseline reference when creating the new difficulty. + /// The ruleset with which the new difficulty should be created. + public virtual WorkingBeatmap CreateNewDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap, RulesetInfo rulesetInfo) { - var referenceBeatmap = creationParameters.ReferenceBeatmap; - var targetBeatmapSet = creationParameters.BeatmapSet; + var playableBeatmap = referenceWorkingBeatmap.GetPlayableBeatmap(rulesetInfo); + var newBeatmapInfo = new BeatmapInfo(rulesetInfo, new BeatmapDifficulty(), playableBeatmap.Metadata.DeepClone()); + var newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; + foreach (var timingPoint in playableBeatmap.ControlPointInfo.TimingPoints) + newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone()); + + return addDifficultyToSet(targetBeatmapSet, newBeatmap, referenceWorkingBeatmap.Skin); + } + + /// + /// Add a copy of the provided to the provided . + /// The new difficulty will be backed by a model + /// and represented by the returned . + /// + /// + /// Contrary to , this method creates a nearly-exact copy of + /// (with the exception of a few key properties that cannot be copied under any circumstance, like difficulty name, beatmap hash, or online status). + /// + /// The to add the copy to. + /// The to be copied. + public virtual WorkingBeatmap CopyExistingDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap) + { + var newBeatmap = referenceWorkingBeatmap.GetPlayableBeatmap(referenceWorkingBeatmap.BeatmapInfo.Ruleset).Clone(); BeatmapInfo newBeatmapInfo; - IBeatmap newBeatmap; - if (creationParameters.CreateBlank) - { - newBeatmapInfo = new BeatmapInfo(creationParameters.Ruleset, new BeatmapDifficulty(), referenceBeatmap.Metadata.DeepClone()); - newBeatmap = new Beatmap { BeatmapInfo = newBeatmapInfo }; - foreach (var timingPoint in referenceBeatmap.ControlPointInfo.TimingPoints) - newBeatmap.ControlPointInfo.Add(timingPoint.Time, timingPoint.DeepClone()); - } - else - { - newBeatmap = referenceBeatmap.Clone(); - newBeatmap.BeatmapInfo = newBeatmapInfo = referenceBeatmap.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)"; - // 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. - newBeatmapInfo.OnlineID = -1; - newBeatmapInfo.Status = BeatmapOnlineStatus.None; - } + 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)"; + // 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. + newBeatmapInfo.OnlineID = -1; + newBeatmapInfo.Status = BeatmapOnlineStatus.None; + return addDifficultyToSet(targetBeatmapSet, newBeatmap, referenceWorkingBeatmap.Skin); + } + + private WorkingBeatmap addDifficultyToSet(BeatmapSetInfo targetBeatmapSet, IBeatmap newBeatmap, ISkin beatmapSkin) + { // populate circular beatmap set info <-> beatmap info references manually. // several places like `BeatmapModelManager.Save()` or `GetWorkingBeatmap()` // rely on them being freely traversable in both directions for correct operation. - targetBeatmapSet.Beatmaps.Add(newBeatmapInfo); - newBeatmapInfo.BeatmapSet = targetBeatmapSet; + targetBeatmapSet.Beatmaps.Add(newBeatmap.BeatmapInfo); + newBeatmap.BeatmapInfo.BeatmapSet = targetBeatmapSet; - beatmapModelManager.Save(newBeatmapInfo, newBeatmap, creationParameters.ReferenceBeatmapSkin); + beatmapModelManager.Save(newBeatmap.BeatmapInfo, newBeatmap, beatmapSkin); workingBeatmapCache.Invalidate(targetBeatmapSet); return GetWorkingBeatmap(newBeatmap.BeatmapInfo); } - // TODO: add back support for making a copy of another difficulty - // (likely via a separate `CopyDifficulty()` method). - /// /// Delete a beatmap difficulty. /// diff --git a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs index 138e13bda1..aa6ca280ee 100644 --- a/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs +++ b/osu.Game/Screens/Edit/CreateNewDifficultyDialog.cs @@ -10,11 +10,11 @@ namespace osu.Game.Screens.Edit { /// /// Delegate used to create new difficulties. - /// A value of in the clearAllObjects parameter - /// indicates that the new difficulty should have its hitobjects cleared; - /// otherwise, the new difficulty should be an exact copy of an existing one. + /// A value of in the createCopy parameter + /// indicates that the new difficulty should be an exact copy of an existing one; + /// otherwise, the new difficulty should have its hitobjects and beatmap-level settings cleared. /// - public delegate void CreateNewDifficulty(bool clearAllObjects); + public delegate void CreateNewDifficulty(bool createCopy); public CreateNewDifficultyDialog(CreateNewDifficulty createNewDifficulty) { @@ -27,12 +27,12 @@ namespace osu.Game.Screens.Edit new PopupDialogOkButton { Text = "Yeah, let's start from scratch!", - Action = () => createNewDifficulty.Invoke(true) + Action = () => createNewDifficulty.Invoke(false) }, new PopupDialogCancelButton { Text = "No, create an exact copy of this difficulty", - Action = () => createNewDifficulty.Invoke(false) + Action = () => createNewDifficulty.Invoke(true) }, new PopupDialogCancelButton { diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 7a3c4f2a19..c2775ae101 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -9,7 +9,6 @@ using JetBrains.Annotations; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -359,14 +358,14 @@ namespace osu.Game.Screens.Edit /// /// Creates an instance representing the current state of the editor. /// - /// - /// The next beatmap to be shown, in the case of difficulty switch. + /// + /// The ruleset of the next beatmap to be shown, in the case of difficulty switch. /// indicates that the beatmap will not be changing. /// - public EditorState GetState([CanBeNull] BeatmapInfo nextBeatmap = null) => new EditorState + public EditorState GetState([CanBeNull] RulesetInfo nextRuleset = null) => new EditorState { Time = clock.CurrentTimeAccurate, - ClipboardContent = nextBeatmap == null || editorBeatmap.BeatmapInfo.Ruleset.ShortName == nextBeatmap.Ruleset.ShortName ? Clipboard.Content.Value : string.Empty + ClipboardContent = nextRuleset == null || editorBeatmap.BeatmapInfo.Ruleset.ShortName == nextRuleset.ShortName ? Clipboard.Content.Value : string.Empty }; /// @@ -845,23 +844,15 @@ namespace osu.Game.Screens.Edit { if (!rulesetInfo.Equals(editorBeatmap.BeatmapInfo.Ruleset)) { - switchToNewDifficulty(rulesetInfo, true); + switchToNewDifficulty(rulesetInfo, false); return; } - dialogOverlay.Push(new CreateNewDifficultyDialog(clearAllObjects => switchToNewDifficulty(rulesetInfo, clearAllObjects))); + dialogOverlay.Push(new CreateNewDifficultyDialog(createCopy => switchToNewDifficulty(rulesetInfo, createCopy))); } - private void switchToNewDifficulty(RulesetInfo rulesetInfo, bool clearAllObjects) - => loader?.ScheduleSwitchToNewDifficulty(new NewDifficultyCreationParameters - ( - editorBeatmap.BeatmapInfo.BeatmapSet.AsNonNull(), - rulesetInfo, - editorBeatmap, - editorBeatmap.BeatmapSkin, - clearAllObjects, - GetState() - )); + private void switchToNewDifficulty(RulesetInfo rulesetInfo, bool createCopy) + => loader?.ScheduleSwitchToNewDifficulty(editorBeatmap.BeatmapInfo, rulesetInfo, createCopy, GetState(rulesetInfo)); private EditorMenuItem createDifficultySwitchMenu() { @@ -886,7 +877,7 @@ namespace osu.Game.Screens.Edit return new EditorMenuItem("Change difficulty") { Items = difficultyItems }; } - protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleSwitchToExistingDifficulty(nextBeatmap, GetState(nextBeatmap)); + protected void SwitchToDifficulty(BeatmapInfo nextBeatmap) => loader?.ScheduleSwitchToExistingDifficulty(nextBeatmap, GetState(nextBeatmap.Ruleset)); private void cancelExit() { diff --git a/osu.Game/Screens/Edit/EditorLoader.cs b/osu.Game/Screens/Edit/EditorLoader.cs index 505a57f157..0a2b8437fa 100644 --- a/osu.Game/Screens/Edit/EditorLoader.cs +++ b/osu.Game/Screens/Edit/EditorLoader.cs @@ -4,6 +4,7 @@ using System; using JetBrains.Annotations; using osu.Framework.Allocation; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Logging; @@ -11,6 +12,7 @@ using osu.Framework.Screens; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Menu; using osu.Game.Screens.Play; @@ -79,19 +81,18 @@ namespace osu.Game.Screens.Edit } } - public void ScheduleSwitchToNewDifficulty(NewDifficultyCreationParameters creationParameters) + public void ScheduleSwitchToNewDifficulty(BeatmapInfo referenceBeatmapInfo, RulesetInfo rulesetInfo, bool createCopy, EditorState editorState) => scheduleDifficultySwitch(() => { try { - var refetchedBeatmap = beatmapManager.GetWorkingBeatmap(creationParameters.ReferenceBeatmap.BeatmapInfo); - return beatmapManager.CreateNewDifficulty(new NewDifficultyCreationParameters( - refetchedBeatmap.BeatmapSetInfo, - refetchedBeatmap.BeatmapInfo.Ruleset, - refetchedBeatmap.Beatmap, - refetchedBeatmap.Skin, - creationParameters.CreateBlank, - creationParameters.EditorState)); + // fetch a fresh detached reference from database to avoid polluting model instances attached to cached working beatmaps. + var targetBeatmapSet = beatmapManager.QueryBeatmap(b => b.ID == referenceBeatmapInfo.ID).AsNonNull().BeatmapSet.AsNonNull(); + var referenceWorkingBeatmap = beatmapManager.GetWorkingBeatmap(referenceBeatmapInfo); + + return createCopy + ? beatmapManager.CopyExistingDifficulty(targetBeatmapSet, referenceWorkingBeatmap) + : beatmapManager.CreateNewDifficulty(targetBeatmapSet, referenceWorkingBeatmap, rulesetInfo); } catch (Exception ex) { @@ -100,7 +101,7 @@ namespace osu.Game.Screens.Edit Logger.Error(ex, ex.Message); return Beatmap.Value; } - }, creationParameters.EditorState); + }, editorState); public void ScheduleSwitchToExistingDifficulty(BeatmapInfo beatmapInfo, EditorState editorState) => scheduleDifficultySwitch(() => beatmapManager.GetWorkingBeatmap(beatmapInfo), editorState); diff --git a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs b/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs deleted file mode 100644 index a6458a9456..0000000000 --- a/osu.Game/Screens/Edit/NewDifficultyCreationParameters.cs +++ /dev/null @@ -1,65 +0,0 @@ -// 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 osu.Game.Beatmaps; -using osu.Game.Rulesets; -using osu.Game.Skinning; - -namespace osu.Game.Screens.Edit -{ - public class NewDifficultyCreationParameters - { - /// - /// The that should contain the newly-created difficulty. - /// - public BeatmapSetInfo BeatmapSet { get; } - - /// - /// The that the new difficulty should be playable for. - /// - public RulesetInfo Ruleset { get; } - - /// - /// A reference upon which the new difficulty should be based. - /// - public IBeatmap ReferenceBeatmap { get; } - - /// - /// A reference that the new difficulty should base its own skin upon. - /// - public ISkin? ReferenceBeatmapSkin { get; } - - /// - /// Whether the new difficulty should be blank. - /// - /// - /// A blank difficulty will have no objects, no control points other than timing points taken from - /// and will not share values with , - /// but it will share metadata and timing information with . - /// - public bool CreateBlank { get; } - - /// - /// The saved state of the previous which should be restored upon opening the newly-created difficulty. - /// - public EditorState EditorState { get; } - - public NewDifficultyCreationParameters( - BeatmapSetInfo beatmapSet, - RulesetInfo ruleset, - IBeatmap referenceBeatmap, - ISkin? referenceBeatmapSkin, - bool createBlank, - EditorState editorState) - { - BeatmapSet = beatmapSet; - Ruleset = ruleset; - ReferenceBeatmap = referenceBeatmap; - ReferenceBeatmapSkin = referenceBeatmapSkin; - CreateBlank = createBlank; - EditorState = editorState; - } - } -} diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 8c8a106791..24015590e2 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -136,7 +136,13 @@ namespace osu.Game.Tests.Visual return new TestWorkingBeatmapCache(this, audioManager, resources, storage, defaultBeatmap, host); } - public override WorkingBeatmap CreateNewDifficulty(NewDifficultyCreationParameters creationParameters) + public override WorkingBeatmap CreateNewDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap, RulesetInfo rulesetInfo) + { + // don't actually care about properly creating a difficulty for this context. + return TestBeatmap; + } + + public override WorkingBeatmap CopyExistingDifficulty(BeatmapSetInfo targetBeatmapSet, WorkingBeatmap referenceWorkingBeatmap) { // don't actually care about properly creating a difficulty for this context. return TestBeatmap; From f5d0eb41cb1041c999921ada5c271411de00513f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 15 Feb 2022 02:42:37 +0300 Subject: [PATCH 30/38] Update further `ChangeFocus` usages --- osu.Game/Overlays/Login/LoginPanel.cs | 3 ++- osu.Game/Overlays/LoginOverlay.cs | 2 +- osu.Game/Screens/Edit/Setup/MetadataSection.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index d1e5bfe809..481abd48ab 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -183,7 +183,8 @@ namespace osu.Game.Overlays.Login break; } - if (form != null) GetContainingInputManager()?.ChangeFocus(form); + if (form != null) + ScheduleAfterChildren(() => GetContainingInputManager()?.ChangeFocus(form)); }); public override bool AcceptsFocus => true; diff --git a/osu.Game/Overlays/LoginOverlay.cs b/osu.Game/Overlays/LoginOverlay.cs index f3562aa6d9..9b2d7ca1ee 100644 --- a/osu.Game/Overlays/LoginOverlay.cs +++ b/osu.Game/Overlays/LoginOverlay.cs @@ -78,7 +78,7 @@ namespace osu.Game.Overlays panel.Bounding = true; this.FadeIn(transition_time, Easing.OutQuint); - GetContainingInputManager().ChangeFocus(panel); + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(panel)); } protected override void PopOut() diff --git a/osu.Game/Screens/Edit/Setup/MetadataSection.cs b/osu.Game/Screens/Edit/Setup/MetadataSection.cs index f0ca3e1bbc..571dfb3f6f 100644 --- a/osu.Game/Screens/Edit/Setup/MetadataSection.cs +++ b/osu.Game/Screens/Edit/Setup/MetadataSection.cs @@ -71,7 +71,7 @@ namespace osu.Game.Screens.Edit.Setup base.LoadComplete(); if (string.IsNullOrEmpty(ArtistTextBox.Current.Value)) - GetContainingInputManager().ChangeFocus(ArtistTextBox); + ScheduleAfterChildren(() => GetContainingInputManager().ChangeFocus(ArtistTextBox)); ArtistTextBox.Current.BindValueChanged(artist => transferIfRomanised(artist.NewValue, RomanisedArtistTextBox)); TitleTextBox.Current.BindValueChanged(title => transferIfRomanised(title.NewValue, RomanisedTitleTextBox)); From 60153bb69df75819e7e2830596884bbab8b04624 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 13:22:14 +0900 Subject: [PATCH 31/38] Update nuget packages to highest usable versions EF packages are intentionally pinned to 5.0.14 as higher versions no longer support `netstandard2.1`, which we require for xamarin projects. --- ...u.Game.Rulesets.EmptyFreeform.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- ....Game.Rulesets.EmptyScrolling.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- osu.Desktop/osu.Desktop.csproj | 9 +++++--- .../osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- .../osu.Game.Tournament.Tests.csproj | 2 +- osu.Game/osu.Game.csproj | 22 +++++++++---------- 13 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index cb922c5a58..c305872288 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 5ecd9cc675..ec90885cd9 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index 33ad0ac4f7..f2e143a9c5 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 5ecd9cc675..ec90885cd9 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 5e203af1f2..b1117bf796 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -26,10 +26,13 @@ - + - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 434c0e0367..2bdb6a650c 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -9,7 +9,7 @@ - + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index fc6d900567..a6c614f22f 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index ddad2adfea..ff49d6d4dd 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index bd4c3d3345..a2e54f5cdc 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index a6b8eb8651..debddae037 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index acf1e8470b..40969c8b29 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -6,7 +6,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index c7314a4969..9fd73f2c1b 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 847832f8ac..7b50c804ff 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -18,27 +18,27 @@ - + - - + + - - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + From 28b45fa8999ba897fa93c0f4a4a5fc1e3700a71e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 13:40:58 +0900 Subject: [PATCH 32/38] Add assertions against null reference for connection usages --- .../Multiplayer/OnlineMultiplayerClient.cs | 29 +++++++++++++++++++ .../Online/Spectator/OnlineSpectatorClient.cs | 11 +++++++ 2 files changed, 40 insertions(+) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 3794bec228..ad898759ff 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -4,6 +4,7 @@ #nullable enable using System.Collections.Generic; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; @@ -79,6 +80,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.FromCanceled(new CancellationToken(true)); + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.JoinRoomWithPassword), roomId, password ?? string.Empty); } @@ -87,6 +90,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.FromCanceled(new CancellationToken(true)); + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.LeaveRoom)); } @@ -95,6 +100,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.TransferHost), userId); } @@ -103,6 +110,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.KickUser), userId); } @@ -111,6 +120,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeSettings), settings); } @@ -119,6 +130,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeState), newState); } @@ -127,6 +140,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeBeatmapAvailability), newBeatmapAvailability); } @@ -135,6 +150,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.ChangeUserMods), newMods); } @@ -143,6 +160,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.SendMatchRequest), request); } @@ -151,6 +170,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.StartMatch)); } @@ -159,6 +180,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.AbortGameplay)); } @@ -167,6 +190,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.AddPlaylistItem), item); } @@ -175,6 +200,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.EditPlaylistItem), item); } @@ -183,6 +210,8 @@ namespace osu.Game.Online.Multiplayer if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.InvokeAsync(nameof(IMultiplayerServer.RemovePlaylistItem), playlistItemId); } diff --git a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs index 753796158e..ddde69c627 100644 --- a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs +++ b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs @@ -3,6 +3,7 @@ #nullable enable +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; using osu.Framework.Allocation; @@ -51,6 +52,8 @@ namespace osu.Game.Online.Spectator if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.SendAsync(nameof(ISpectatorServer.BeginPlaySession), state); } @@ -59,6 +62,8 @@ namespace osu.Game.Online.Spectator if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.SendAsync(nameof(ISpectatorServer.SendFrameData), data); } @@ -67,6 +72,8 @@ namespace osu.Game.Online.Spectator if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.SendAsync(nameof(ISpectatorServer.EndPlaySession), state); } @@ -75,6 +82,8 @@ namespace osu.Game.Online.Spectator if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.SendAsync(nameof(ISpectatorServer.StartWatchingUser), userId); } @@ -83,6 +92,8 @@ namespace osu.Game.Online.Spectator if (!IsConnected.Value) return Task.CompletedTask; + Debug.Assert(connection != null); + return connection.SendAsync(nameof(ISpectatorServer.EndWatchingUser), userId); } } From 8ec28dc8bcc1ab691af17e3124b046a6a27a1037 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 13:41:10 +0900 Subject: [PATCH 33/38] Update `OsuDbContext` in line with EF changes --- osu.Game/Database/OsuDbContext.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 441b090a6e..79183b6f0e 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -3,7 +3,6 @@ using System; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.Extensions.Logging; using osu.Framework.Logging; using osu.Framework.Statistics; @@ -12,8 +11,9 @@ using osu.Game.Configuration; using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Scoring; -using LogLevel = Microsoft.Extensions.Logging.LogLevel; using osu.Game.Skinning; +using SQLitePCL; +using LogLevel = Microsoft.Extensions.Logging.LogLevel; namespace osu.Game.Database { @@ -40,10 +40,10 @@ namespace osu.Game.Database static OsuDbContext() { // required to initialise native SQLite libraries on some platforms. - SQLitePCL.Batteries_V2.Init(); + Batteries_V2.Init(); // https://github.com/aspnet/EntityFrameworkCore/issues/9994#issuecomment-508588678 - SQLitePCL.raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/); + raw.sqlite3_config(2 /*SQLITE_CONFIG_MULTITHREAD*/); } /// @@ -116,7 +116,6 @@ namespace osu.Game.Database optionsBuilder // this is required for the time being due to the way we are querying in places like BeatmapStore. // if we ever move to having consumers file their own .Includes, or get eager loading support, this could be re-enabled. - .ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.IncludeIgnoredWarning)) .UseSqlite(connectionString, sqliteOptions => sqliteOptions.CommandTimeout(10)) .UseLoggerFactory(logger.Value); } From 334fe1f1203ac02f507132bd1d64f00139dfb81d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 15:23:14 +0900 Subject: [PATCH 34/38] Add `AsSplitQuery` specification to avoid optimisation recommendation log messages --- osu.Game/Database/EFToRealmMigrator.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/EFToRealmMigrator.cs b/osu.Game/Database/EFToRealmMigrator.cs index 0bb5388d55..c9deee19fe 100644 --- a/osu.Game/Database/EFToRealmMigrator.cs +++ b/osu.Game/Database/EFToRealmMigrator.cs @@ -215,7 +215,8 @@ namespace osu.Game.Database .Include(s => s.Beatmaps).ThenInclude(b => b.Metadata) .Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty) .Include(s => s.Files).ThenInclude(f => f.FileInfo) - .Include(s => s.Metadata); + .Include(s => s.Metadata) + .AsSplitQuery(); log("Beginning beatmaps migration to realm"); @@ -344,7 +345,8 @@ namespace osu.Game.Database .Include(s => s.Ruleset) .Include(s => s.BeatmapInfo) .Include(s => s.Files) - .ThenInclude(f => f.FileInfo); + .ThenInclude(f => f.FileInfo) + .AsSplitQuery(); log("Beginning scores migration to realm"); @@ -434,6 +436,7 @@ namespace osu.Game.Database var existingSkins = db.SkinInfo .Include(s => s.Files) .ThenInclude(f => f.FileInfo) + .AsSplitQuery() .ToList(); // previous entries in EF are removed post migration. From 2c3e50a450359d76c95fc4628b391733dc354f4c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 15:46:25 +0900 Subject: [PATCH 35/38] Update package references in xamarin `props` files --- osu.Android.props | 2 +- osu.iOS.props | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 6b3142fbdc..eab2be1b72 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -56,6 +56,6 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 00c9653146..03a105673c 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -79,15 +79,15 @@ - - - + + + - + - - + + From d79845fb1df28e63545aa0f4bf9552e16965d9bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 15 Feb 2022 17:06:33 +0900 Subject: [PATCH 36/38] Revert `NUnit3TestAdaptor` (again) Console output is still broken. See https://github.com/ppy/osu/runs/5196023462?check_suite_focus=true. --- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index 2bdb6a650c..434c0e0367 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -9,7 +9,7 @@ - + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index a6c614f22f..fc6d900567 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index ff49d6d4dd..ddad2adfea 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index a2e54f5cdc..bd4c3d3345 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -5,7 +5,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index debddae037..a6b8eb8651 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -4,7 +4,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 40969c8b29..acf1e8470b 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -6,7 +6,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 9fd73f2c1b..c7314a4969 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -7,7 +7,7 @@ - + WinExe From 6e99fe04c3b71ce5a36609062ceb08bd6fb1e400 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 16 Feb 2022 00:39:43 +0900 Subject: [PATCH 37/38] Revert more NUnit test adapter bumps --- .../osu.Game.Rulesets.EmptyFreeform.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- .../osu.Game.Rulesets.EmptyScrolling.Tests.csproj | 2 +- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index c305872288..cb922c5a58 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index ec90885cd9..5ecd9cc675 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index f2e143a9c5..33ad0ac4f7 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index ec90885cd9..5ecd9cc675 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -12,7 +12,7 @@ - + From 6a08fd57efb0012a723d658bc279d88292f3754e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 16 Feb 2022 09:43:28 +0900 Subject: [PATCH 38/38] Rename "client" fields in tests to specify whether spectator or multiplayer --- .../StatefulMultiplayerClientTest.cs | 28 +-- .../Visual/Gameplay/TestSceneSpectator.cs | 6 +- .../Visual/Multiplayer/QueueModeTestScene.cs | 10 +- .../TestSceneAllPlayersQueueMode.cs | 38 ++-- .../TestSceneCreateMultiplayerMatchButton.cs | 4 +- .../Multiplayer/TestSceneHostOnlyQueueMode.cs | 26 +-- .../TestSceneMultiSpectatorLeaderboard.cs | 2 +- .../TestSceneMultiSpectatorScreen.cs | 12 +- .../Multiplayer/TestSceneMultiplayer.cs | 180 +++++++++--------- ...TestSceneMultiplayerGameplayLeaderboard.cs | 6 +- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 4 +- .../TestSceneMultiplayerMatchSubScreen.cs | 10 +- .../TestSceneMultiplayerParticipantsList.cs | 98 +++++----- .../Multiplayer/TestSceneMultiplayerPlayer.cs | 6 +- .../TestSceneMultiplayerPlaylist.cs | 12 +- .../TestSceneMultiplayerQueueList.cs | 28 +-- .../TestSceneMultiplayerReadyButton.cs | 56 +++--- .../TestSceneMultiplayerSpectateButton.cs | 26 +-- .../Multiplayer/TestSceneRankRangePill.cs | 18 +- .../Visual/Multiplayer/TestSceneTeamVersus.cs | 30 +-- .../Visual/TestMultiplayerComponents.cs | 4 +- .../IMultiplayerTestSceneDependencies.cs | 5 +- .../Multiplayer/MultiplayerTestScene.cs | 4 +- .../MultiplayerTestSceneDependencies.cs | 6 +- 24 files changed, 309 insertions(+), 310 deletions(-) diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index 0c49a18c8f..4adb7002a0 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -21,8 +21,8 @@ namespace osu.Game.Tests.NonVisual.Multiplayer { var user = new APIUser { Id = 33 }; - AddRepeatStep("add user multiple times", () => Client.AddUser(user), 3); - AddAssert("room has 2 users", () => Client.Room?.Users.Count == 2); + AddRepeatStep("add user multiple times", () => MultiplayerClient.AddUser(user), 3); + AddAssert("room has 2 users", () => MultiplayerClient.Room?.Users.Count == 2); } [Test] @@ -30,11 +30,11 @@ namespace osu.Game.Tests.NonVisual.Multiplayer { var user = new APIUser { Id = 44 }; - AddStep("add user", () => Client.AddUser(user)); - AddAssert("room has 2 users", () => Client.Room?.Users.Count == 2); + AddStep("add user", () => MultiplayerClient.AddUser(user)); + AddAssert("room has 2 users", () => MultiplayerClient.Room?.Users.Count == 2); - AddRepeatStep("remove user multiple times", () => Client.RemoveUser(user), 3); - AddAssert("room has 1 user", () => Client.Room?.Users.Count == 1); + AddRepeatStep("remove user multiple times", () => MultiplayerClient.RemoveUser(user), 3); + AddAssert("room has 1 user", () => MultiplayerClient.Room?.Users.Count == 1); } [Test] @@ -42,7 +42,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer { int id = 2000; - AddRepeatStep("add some users", () => Client.AddUser(new APIUser { Id = id++ }), 5); + AddRepeatStep("add some users", () => MultiplayerClient.AddUser(new APIUser { Id = id++ }), 5); checkPlayingUserCount(0); changeState(3, MultiplayerUserState.WaitingForLoad); @@ -57,17 +57,17 @@ namespace osu.Game.Tests.NonVisual.Multiplayer changeState(6, MultiplayerUserState.WaitingForLoad); checkPlayingUserCount(6); - AddStep("another user left", () => Client.RemoveUser((Client.Room?.Users.Last().User).AsNonNull())); + AddStep("another user left", () => MultiplayerClient.RemoveUser((MultiplayerClient.Room?.Users.Last().User).AsNonNull())); checkPlayingUserCount(5); - AddStep("leave room", () => Client.LeaveRoom()); + AddStep("leave room", () => MultiplayerClient.LeaveRoom()); checkPlayingUserCount(0); } [Test] public void TestPlayingUsersUpdatedOnJoin() { - AddStep("leave room", () => Client.LeaveRoom()); + AddStep("leave room", () => MultiplayerClient.LeaveRoom()); AddUntilStep("wait for room part", () => !RoomJoined); AddStep("create room initially in gameplay", () => @@ -76,7 +76,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer newRoom.CopyFrom(SelectedRoom.Value); newRoom.RoomID.Value = null; - Client.RoomSetupAction = room => + MultiplayerClient.RoomSetupAction = room => { room.State = MultiplayerRoomState.Playing; room.Users.Add(new MultiplayerRoomUser(PLAYER_1_ID) @@ -94,15 +94,15 @@ namespace osu.Game.Tests.NonVisual.Multiplayer } private void checkPlayingUserCount(int expectedCount) - => AddAssert($"{"user".ToQuantity(expectedCount)} playing", () => Client.CurrentMatchPlayingUserIds.Count == expectedCount); + => AddAssert($"{"user".ToQuantity(expectedCount)} playing", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count == expectedCount); private void changeState(int userCount, MultiplayerUserState state) => AddStep($"{"user".ToQuantity(userCount)} in {state}", () => { for (int i = 0; i < userCount; ++i) { - int userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); - Client.ChangeUserState(userId, state); + int userId = MultiplayerClient.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!"); + MultiplayerClient.ChangeUserState(userId, state); } }); } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 6dca256d31..d47ebf9f0d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private OsuGameBase game { get; set; } - private TestSpectatorClient spectatorClient => dependenciesScreen.Client; + private TestSpectatorClient spectatorClient => dependenciesScreen.SpectatorClient; private DependenciesScreen dependenciesScreen; private SoloSpectator spectatorScreen; @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay Children = new Drawable[] { dependenciesScreen.UserLookupCache, - dependenciesScreen.Client, + dependenciesScreen.SpectatorClient, }; }); @@ -336,7 +336,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class DependenciesScreen : OsuScreen { [Cached(typeof(SpectatorClient))] - public readonly TestSpectatorClient Client = new TestSpectatorClient(); + public readonly TestSpectatorClient SpectatorClient = new TestSpectatorClient(); [Cached(typeof(UserLookupCache))] public readonly TestUserLookupCache UserLookupCache = new TestUserLookupCache(); diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs index 52801dd57a..2a3b44d619 100644 --- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestMultiplayerComponents multiplayerComponents; - protected TestMultiplayerClient Client => multiplayerComponents.Client; + protected TestMultiplayerClient MultiplayerClient => multiplayerComponents.MultiplayerClient; [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) @@ -84,21 +84,21 @@ namespace osu.Game.Tests.Visual.Multiplayer ClickButtonWhenEnabled(); - AddUntilStep("wait for join", () => Client.RoomJoined); + AddUntilStep("wait for join", () => MultiplayerClient.RoomJoined); } [Test] public void TestCreatedWithCorrectMode() { - AddAssert("room created with correct mode", () => Client.APIRoom?.QueueMode.Value == Mode); + AddAssert("room created with correct mode", () => MultiplayerClient.APIRoom?.QueueMode.Value == Mode); } protected void RunGameplay() { - AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle); + AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); ClickButtonWhenEnabled(); - AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready); + AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs index ad60ac824d..0785315b26 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneAllPlayersQueueMode.cs @@ -31,19 +31,19 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestFirstItemSelectedByDefault() { - AddAssert("first item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID); + AddAssert("first item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); } [Test] public void TestItemAddedToTheEndOfQueue() { addItem(() => OtherBeatmap); - AddAssert("playlist has 2 items", () => Client.APIRoom?.Playlist.Count == 2); + AddAssert("playlist has 2 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2); addItem(() => InitialBeatmap); - AddAssert("playlist has 3 items", () => Client.APIRoom?.Playlist.Count == 3); + AddAssert("playlist has 3 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 3); - AddAssert("first item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID); + AddAssert("first item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); } [Test] @@ -51,9 +51,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { RunGameplay(); - AddAssert("playlist has only one item", () => Client.APIRoom?.Playlist.Count == 1); - AddAssert("playlist item is expired", () => Client.APIRoom?.Playlist[0].Expired == true); - AddAssert("last item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID); + AddAssert("playlist has only one item", () => MultiplayerClient.APIRoom?.Playlist.Count == 1); + AddAssert("playlist item is expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true); + AddAssert("last item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); } [Test] @@ -64,13 +64,13 @@ namespace osu.Game.Tests.Visual.Multiplayer RunGameplay(); - AddAssert("first item expired", () => Client.APIRoom?.Playlist[0].Expired == true); - AddAssert("next item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[1].ID); + AddAssert("first item expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true); + AddAssert("next item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[1].ID); RunGameplay(); - AddAssert("second item expired", () => Client.APIRoom?.Playlist[1].Expired == true); - AddAssert("next item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[2].ID); + AddAssert("second item expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == true); + AddAssert("next item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[2].ID); } [Test] @@ -82,10 +82,10 @@ namespace osu.Game.Tests.Visual.Multiplayer // Move to the "other" beatmap. RunGameplay(); - AddStep("change queue mode", () => Client.ChangeSettings(queueMode: QueueMode.HostOnly)); - AddAssert("playlist has 3 items", () => Client.APIRoom?.Playlist.Count == 3); - AddAssert("item 2 is not expired", () => Client.APIRoom?.Playlist[1].Expired == false); - AddAssert("current item is the other beatmap", () => Client.Room?.Settings.PlaylistItemId == 2); + AddStep("change queue mode", () => MultiplayerClient.ChangeSettings(queueMode: QueueMode.HostOnly)); + AddAssert("playlist has 3 items", () => MultiplayerClient.APIRoom?.Playlist.Count == 3); + AddAssert("item 2 is not expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == false); + AddAssert("current item is the other beatmap", () => MultiplayerClient.Room?.Settings.PlaylistItemId == 2); } [Test] @@ -101,10 +101,10 @@ namespace osu.Game.Tests.Visual.Multiplayer addItem(() => OtherBeatmap, new CatchRuleset().RulesetInfo); AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID); - AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle); + AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); ClickButtonWhenEnabled(); - AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready); + AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded); @@ -118,10 +118,10 @@ namespace osu.Game.Tests.Visual.Multiplayer addItem(() => OtherBeatmap, mods: new Mod[] { new OsuModDoubleTime() }); AddUntilStep("selected beatmap is initial beatmap", () => Beatmap.Value.BeatmapInfo.OnlineID == InitialBeatmap.OnlineID); - AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle); + AddUntilStep("wait for idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); ClickButtonWhenEnabled(); - AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready); + AddUntilStep("wait for ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); AddUntilStep("wait for player", () => CurrentScreen is Player player && player.IsLoaded); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs index 2f0398c6ef..0674fc7a39 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneCreateMultiplayerMatchButton.cs @@ -37,10 +37,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("end joining room", () => joiningRoomOperation.Dispose()); assertButtonEnableState(true); - AddStep("disconnect client", () => Client.Disconnect()); + AddStep("disconnect client", () => MultiplayerClient.Disconnect()); assertButtonEnableState(false); - AddStep("re-connect client", () => Client.Connect()); + AddStep("re-connect client", () => MultiplayerClient.Connect()); assertButtonEnableState(true); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs index cd14a98751..a308d60cf1 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneHostOnlyQueueMode.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestFirstItemSelectedByDefault() { - AddAssert("first item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID); + AddAssert("first item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); } [Test] @@ -30,7 +30,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { selectNewItem(() => InitialBeatmap); - AddAssert("playlist item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID); + AddAssert("playlist item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); } [Test] @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { selectNewItem(() => OtherBeatmap); - AddAssert("playlist item still selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[0].ID); + AddAssert("playlist item still selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[0].ID); } [Test] @@ -46,10 +46,10 @@ namespace osu.Game.Tests.Visual.Multiplayer { RunGameplay(); - AddAssert("playlist contains two items", () => Client.APIRoom?.Playlist.Count == 2); - AddAssert("first playlist item expired", () => Client.APIRoom?.Playlist[0].Expired == true); - AddAssert("second playlist item not expired", () => Client.APIRoom?.Playlist[1].Expired == false); - AddAssert("second playlist item selected", () => Client.Room?.Settings.PlaylistItemId == Client.APIRoom?.Playlist[1].ID); + AddAssert("playlist contains two items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2); + AddAssert("first playlist item expired", () => MultiplayerClient.APIRoom?.Playlist[0].Expired == true); + AddAssert("second playlist item not expired", () => MultiplayerClient.APIRoom?.Playlist[1].Expired == false); + AddAssert("second playlist item selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == MultiplayerClient.APIRoom?.Playlist[1].ID); } [Test] @@ -58,23 +58,23 @@ namespace osu.Game.Tests.Visual.Multiplayer RunGameplay(); IBeatmapInfo firstBeatmap = null; - AddStep("get first playlist item beatmap", () => firstBeatmap = Client.APIRoom?.Playlist[0].Beatmap.Value); + AddStep("get first playlist item beatmap", () => firstBeatmap = MultiplayerClient.APIRoom?.Playlist[0].Beatmap.Value); selectNewItem(() => OtherBeatmap); - AddAssert("first playlist item hasn't changed", () => Client.APIRoom?.Playlist[0].Beatmap.Value == firstBeatmap); - AddAssert("second playlist item changed", () => Client.APIRoom?.Playlist[1].Beatmap.Value != firstBeatmap); + 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); } [Test] public void TestSettingsUpdatedWhenChangingQueueMode() { - AddStep("change queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings + AddStep("change queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("api room updated", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddUntilStep("api room updated", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); } [Test] @@ -82,7 +82,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { addItem(() => OtherBeatmap); - AddAssert("playlist contains two items", () => Client.APIRoom?.Playlist.Count == 2); + AddAssert("playlist contains two items", () => MultiplayerClient.APIRoom?.Playlist.Count == 2); } private void selectNewItem(Func beatmap) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs index 543e6a91d0..6b3573b3cb 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorLeaderboard.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach ((int userId, var _) in clocks) { SpectatorClient.StartPlay(userId, 0); - OnlinePlayDependencies.Client.AddUser(new APIUser { Id = userId }); + OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = userId }); } }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs index 56cb6036c7..7ce0c6a94d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiSpectatorScreen.cs @@ -60,8 +60,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start players silently", () => { - OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_1_ID }, true); - OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_2_ID }, true); + OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }, true); + OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_2_ID }, true); playingUsers.Add(new MultiplayerRoomUser(PLAYER_1_ID)); playingUsers.Add(new MultiplayerRoomUser(PLAYER_2_ID)); @@ -121,13 +121,13 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start players", () => { - var player1 = OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_1_ID }, true); + var player1 = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }, true); player1.MatchState = new TeamVersusUserState { TeamID = 0, }; - var player2 = OnlinePlayDependencies.Client.AddUser(new APIUser { Id = PLAYER_2_ID }, true); + var player2 = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = PLAYER_2_ID }, true); player2.MatchState = new TeamVersusUserState { TeamID = 1, @@ -396,7 +396,7 @@ namespace osu.Game.Tests.Visual.Multiplayer User = new APIUser { Id = id }, }; - OnlinePlayDependencies.Client.AddUser(user.User, true); + OnlinePlayDependencies.MultiplayerClient.AddUser(user.User, true); SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId); playingUsers.Add(user); @@ -410,7 +410,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { var user = playingUsers.Single(u => u.UserID == userId); - OnlinePlayDependencies.Client.RemoveUser(user.User.AsNonNull()); + OnlinePlayDependencies.MultiplayerClient.RemoveUser(user.User.AsNonNull()); SpectatorClient.EndPlay(userId); playingUsers.Remove(user); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index 5439b3eeea..3f9aec3a42 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestMultiplayerComponents multiplayerComponents; - private TestMultiplayerClient client => multiplayerComponents.Client; + private TestMultiplayerClient multiplayerClient => multiplayerComponents.MultiplayerClient; private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager; [BackgroundDependencyLoader] @@ -109,66 +109,66 @@ namespace osu.Game.Tests.Visual.Multiplayer // all ready AddUntilStep("all players ready", () => { - var nextUnready = client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); + var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); if (nextUnready != null) - client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); + multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); - return client.Room?.Users.All(u => u.State == MultiplayerUserState.Ready) == true; + return multiplayerClient.Room?.Users.All(u => u.State == MultiplayerUserState.Ready) == true; }); AddStep("unready all players at once", () => { - Debug.Assert(client.Room != null); + Debug.Assert(multiplayerClient.Room != null); - foreach (var u in client.Room.Users) client.ChangeUserState(u.UserID, MultiplayerUserState.Idle); + foreach (var u in multiplayerClient.Room.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Idle); }); AddStep("ready all players at once", () => { - Debug.Assert(client.Room != null); + Debug.Assert(multiplayerClient.Room != null); - foreach (var u in client.Room.Users) client.ChangeUserState(u.UserID, MultiplayerUserState.Ready); + foreach (var u in multiplayerClient.Room.Users) multiplayerClient.ChangeUserState(u.UserID, MultiplayerUserState.Ready); }); } private void addRandomPlayer() { int randomUser = RNG.Next(200000, 500000); - client.AddUser(new APIUser { Id = randomUser, Username = $"user {randomUser}" }); + multiplayerClient.AddUser(new APIUser { Id = randomUser, Username = $"user {randomUser}" }); } private void removeLastUser() { - APIUser lastUser = client.Room?.Users.Last().User; + APIUser lastUser = multiplayerClient.Room?.Users.Last().User; - if (lastUser == null || lastUser == client.LocalUser?.User) + if (lastUser == null || lastUser == multiplayerClient.LocalUser?.User) return; - client.RemoveUser(lastUser); + multiplayerClient.RemoveUser(lastUser); } private void kickLastUser() { - APIUser lastUser = client.Room?.Users.Last().User; + APIUser lastUser = multiplayerClient.Room?.Users.Last().User; - if (lastUser == null || lastUser == client.LocalUser?.User) + if (lastUser == null || lastUser == multiplayerClient.LocalUser?.User) return; - client.KickUser(lastUser.Id); + multiplayerClient.KickUser(lastUser.Id); } private void markNextPlayerReady() { - var nextUnready = client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); + var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); if (nextUnready != null) - client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); + multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); } private void markNextPlayerIdle() { - var nextUnready = client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Ready); + var nextUnready = multiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Ready); if (nextUnready != null) - client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Idle); + multiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Idle); } private void performRandomAction() @@ -218,7 +218,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Press select", () => InputManager.Key(Key.Enter)); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); - AddUntilStep("wait for join", () => client.RoomJoined); + AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); } [Test] @@ -237,8 +237,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddAssert("Check participant count correct", () => client.APIRoom?.ParticipantCount.Value == 1); - AddAssert("Check participant list contains user", () => client.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); + AddAssert("Check participant count correct", () => multiplayerClient.APIRoom?.ParticipantCount.Value == 1); + AddAssert("Check participant list contains user", () => multiplayerClient.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); } [Test] @@ -297,10 +297,10 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("join room", () => InputManager.Key(Key.Enter)); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); - AddUntilStep("wait for join", () => client.RoomJoined); + AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); - AddAssert("Check participant count correct", () => client.APIRoom?.ParticipantCount.Value == 1); - AddAssert("Check participant list contains user", () => client.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); + AddAssert("Check participant count correct", () => multiplayerClient.APIRoom?.ParticipantCount.Value == 1); + AddAssert("Check participant list contains user", () => multiplayerClient.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); } [Test] @@ -320,7 +320,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddAssert("room has password", () => client.APIRoom?.Password.Value == "password"); + AddAssert("room has password", () => multiplayerClient.APIRoom?.Password.Value == "password"); } [Test] @@ -355,7 +355,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick()); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); - AddUntilStep("wait for join", () => client.RoomJoined); + AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); } [Test] @@ -375,8 +375,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddStep("change password", () => client.ChangeSettings(password: "password2")); - AddUntilStep("local password changed", () => client.APIRoom?.Password.Value == "password2"); + AddStep("change password", () => multiplayerClient.ChangeSettings(password: "password2")); + AddUntilStep("local password changed", () => multiplayerClient.APIRoom?.Password.Value == "password2"); } [Test] @@ -398,7 +398,7 @@ namespace osu.Game.Tests.Visual.Multiplayer pressReadyButton(); AddStep("delete beatmap", () => beatmaps.Delete(importedSet)); - AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle); + AddUntilStep("user state is idle", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); } [Test] @@ -422,22 +422,22 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Enter song select", () => { var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen; - ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId); + ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId); }); AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true); - AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == client.Room?.Playlist.First().BeatmapID); + AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.Room?.Playlist.First().BeatmapID); AddStep("Select next beatmap", () => InputManager.Key(Key.Down)); - AddUntilStep("Beatmap doesn't match current item", () => Beatmap.Value.BeatmapInfo.OnlineID != client.Room?.Playlist.First().BeatmapID); + AddUntilStep("Beatmap doesn't match current item", () => Beatmap.Value.BeatmapInfo.OnlineID != multiplayerClient.Room?.Playlist.First().BeatmapID); - AddStep("start match externally", () => client.StartMatch()); + AddStep("start match externally", () => multiplayerClient.StartMatch()); AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player); - AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == client.Room?.Playlist.First().BeatmapID); + AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == multiplayerClient.Room?.Playlist.First().BeatmapID); } [Test] @@ -461,22 +461,22 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Enter song select", () => { var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen; - ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId); + ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId); }); AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true); - AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == client.Room?.Playlist.First().RulesetID); + AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.Room?.Playlist.First().RulesetID); AddStep("Switch ruleset", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Ruleset.Value = new CatchRuleset().RulesetInfo); - AddUntilStep("Ruleset doesn't match current item", () => Ruleset.Value.OnlineID != client.Room?.Playlist.First().RulesetID); + AddUntilStep("Ruleset doesn't match current item", () => Ruleset.Value.OnlineID != multiplayerClient.Room?.Playlist.First().RulesetID); - AddStep("start match externally", () => client.StartMatch()); + AddStep("start match externally", () => multiplayerClient.StartMatch()); AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player); - AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == client.Room?.Playlist.First().RulesetID); + AddAssert("Ruleset matches current item", () => Ruleset.Value.OnlineID == multiplayerClient.Room?.Playlist.First().RulesetID); } [Test] @@ -500,22 +500,22 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("Enter song select", () => { var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen; - ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId); + ((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(multiplayerClient.Room?.Settings.PlaylistItemId); }); AddUntilStep("wait for song select", () => this.ChildrenOfType().FirstOrDefault()?.BeatmapSetsLoaded == true); - AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(client.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); + AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); AddStep("Switch required mods", () => ((MultiplayerMatchSongSelect)multiplayerComponents.MultiplayerScreen.CurrentSubScreen).Mods.Value = new Mod[] { new OsuModDoubleTime() }); - AddAssert("Mods don't match current item", () => !SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(client.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); + AddAssert("Mods don't match current item", () => !SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); - AddStep("start match externally", () => client.StartMatch()); + AddStep("start match externally", () => multiplayerClient.StartMatch()); AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player); - AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(client.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); + AddAssert("Mods match current item", () => SelectedMods.Value.Select(m => m.Acronym).SequenceEqual(multiplayerClient.Room.AsNonNull().Playlist.First().RequiredMods.Select(m => m.Acronym))); } [Test] @@ -536,18 +536,18 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("join other user (ready, host)", () => { - client.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" }); - client.TransferHost(MultiplayerTestScene.PLAYER_1_ID); - client.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready); + multiplayerClient.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" }); + multiplayerClient.TransferHost(MultiplayerTestScene.PLAYER_1_ID); + multiplayerClient.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready); }); AddStep("delete beatmap", () => beatmaps.Delete(importedSet)); ClickButtonWhenEnabled(); - AddUntilStep("wait for spectating user state", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddUntilStep("wait for spectating user state", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); - AddStep("start match externally", () => client.StartMatch()); + AddStep("start match externally", () => multiplayerClient.StartMatch()); AddAssert("play not started", () => multiplayerComponents.IsCurrentScreen()); } @@ -572,16 +572,16 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("join other user (ready, host)", () => { - client.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" }); - client.TransferHost(MultiplayerTestScene.PLAYER_1_ID); - client.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready); + multiplayerClient.AddUser(new APIUser { Id = MultiplayerTestScene.PLAYER_1_ID, Username = "Other" }); + multiplayerClient.TransferHost(MultiplayerTestScene.PLAYER_1_ID); + multiplayerClient.ChangeUserState(MultiplayerTestScene.PLAYER_1_ID, MultiplayerUserState.Ready); }); ClickButtonWhenEnabled(); - AddUntilStep("wait for spectating user state", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddUntilStep("wait for spectating user state", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); - AddStep("start match externally", () => client.StartMatch()); + AddStep("start match externally", () => multiplayerClient.StartMatch()); AddStep("restore beatmap", () => { @@ -608,7 +608,7 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddStep("disconnect", () => client.Disconnect()); + AddStep("disconnect", () => multiplayerClient.Disconnect()); AddUntilStep("back in lounge", () => this.ChildrenOfType().FirstOrDefault()?.IsCurrentScreen() == true); } @@ -718,7 +718,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("join room", () => InputManager.Key(Key.Enter)); AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true); - AddUntilStep("wait for join", () => client.RoomJoined); + AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); AddAssert("local room has correct settings", () => { @@ -745,11 +745,11 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddStep("set spectating state", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); - AddUntilStep("state set to spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddStep("set spectating state", () => multiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); + AddUntilStep("state set to spectating", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); - AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 })); - AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready)); + AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 })); + AddStep("set other user ready", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Ready)); pressReadyButton(1234); AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true); @@ -761,7 +761,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen()); - AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle); + AddUntilStep("user state is idle", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); } [Test] @@ -781,16 +781,16 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddStep("set spectating state", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); - AddUntilStep("state set to spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddStep("set spectating state", () => multiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); + AddUntilStep("state set to spectating", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); - AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 })); - AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready)); + AddStep("join other user", () => multiplayerClient.AddUser(new APIUser { Id = 1234 })); + AddStep("set other user ready", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Ready)); pressReadyButton(1234); AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true); - AddStep("set other user loaded", () => client.ChangeUserState(1234, MultiplayerUserState.Loaded)); - AddStep("set other user finished play", () => client.ChangeUserState(1234, MultiplayerUserState.FinishedPlay)); + AddStep("set other user loaded", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Loaded)); + AddStep("set other user finished play", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.FinishedPlay)); AddStep("press back button and exit", () => { @@ -800,7 +800,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen()); AddWaitStep("wait for possible state change", 5); - AddUntilStep("user state is spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddUntilStep("user state is spectating", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); } [Test] @@ -822,13 +822,13 @@ namespace osu.Game.Tests.Visual.Multiplayer enterGameplay(); - AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 })); - AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem + 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()); - AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2); + AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2); AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent()); AddUntilStep("queue contains item", () => this.ChildrenOfType().Single().Items.Single().ID == 2); @@ -853,16 +853,16 @@ namespace osu.Game.Tests.Visual.Multiplayer enterGameplay(); - AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 })); - AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem + 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()); - AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2); + AddUntilStep("item arrived in playlist", () => multiplayerClient.Room?.Playlist.Count == 2); - AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2).WaitSafely()); - AddUntilStep("item removed from playlist", () => client.Room?.Playlist.Count == 1); + AddStep("delete item as other user", () => multiplayerClient.RemoveUserPlaylistItem(1234, 2).WaitSafely()); + AddUntilStep("item removed from playlist", () => multiplayerClient.Room?.Playlist.Count == 1); AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent()); AddUntilStep("queue is empty", () => this.ChildrenOfType().Single().Items.Count == 0); @@ -886,17 +886,17 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("join other user and make host", () => { - client.AddUser(new APIUser { Id = 1234 }); - client.TransferHost(1234); + multiplayerClient.AddUser(new APIUser { Id = 1234 }); + multiplayerClient.TransferHost(1234); }); - AddStep("set local user spectating", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); - AddUntilStep("wait for spectating state", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + AddStep("set local user spectating", () => multiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); + AddUntilStep("wait for spectating state", () => multiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); runGameplay(); - AddStep("exit gameplay for other user", () => client.ChangeUserState(1234, MultiplayerUserState.Idle)); - AddUntilStep("wait for room to be idle", () => client.Room?.State == MultiplayerRoomState.Open); + AddStep("exit gameplay for other user", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Idle)); + AddUntilStep("wait for room to be idle", () => multiplayerClient.Room?.State == MultiplayerRoomState.Open); runGameplay(); @@ -904,13 +904,13 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("start match by other user", () => { - client.ChangeUserState(1234, MultiplayerUserState.Ready); - client.StartMatch(); + multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Ready); + multiplayerClient.StartMatch(); }); - AddUntilStep("wait for loading", () => client.Room?.State == MultiplayerRoomState.WaitingForLoad); - AddStep("set player loaded", () => client.ChangeUserState(1234, MultiplayerUserState.Loaded)); - AddUntilStep("wait for gameplay to start", () => client.Room?.State == MultiplayerRoomState.Playing); + AddUntilStep("wait for loading", () => multiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad); + AddStep("set player loaded", () => multiplayerClient.ChangeUserState(1234, MultiplayerUserState.Loaded)); + AddUntilStep("wait for gameplay to start", () => multiplayerClient.Room?.State == MultiplayerRoomState.Playing); AddUntilStep("wait for local user to enter spectator", () => multiplayerComponents.CurrentScreen is MultiSpectatorScreen); } } @@ -935,7 +935,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("click ready button", () => { - user = playingUserId == null ? client.LocalUser : client.Room?.Users.Single(u => u.UserID == playingUserId); + user = playingUserId == null ? multiplayerClient.LocalUser : multiplayerClient.Room?.Users.Single(u => u.UserID == playingUserId); lastState = user?.State ?? MultiplayerUserState.Idle; InputManager.MoveMouseTo(readyButton); @@ -955,7 +955,7 @@ namespace osu.Game.Tests.Visual.Multiplayer ClickButtonWhenEnabled(); - AddUntilStep("wait for join", () => client.RoomJoined); + AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index 437f4e3308..6605f82d5c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (int user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID); - multiplayerUsers.Add(OnlinePlayDependencies.Client.AddUser(new APIUser { Id = user }, true)); + multiplayerUsers.Add(OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = user }, true)); } Children = new Drawable[] @@ -77,7 +77,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); - AddUntilStep("wait for user population", () => Client.CurrentMatchPlayingUserIds.Count > 0); + AddUntilStep("wait for user population", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count > 0); } [Test] @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestUserQuit() { foreach (int user in users) - AddStep($"mark user {user} quit", () => Client.RemoveUser(UserLookupCache.GetUserAsync(user).GetResultSafely().AsNonNull())); + AddStep($"mark user {user} quit", () => MultiplayerClient.RemoveUser(UserLookupCache.GetUserAsync(user).GetResultSafely().AsNonNull())); } [Test] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index cd3ae50dab..dabc1c1e5a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.Multiplayer foreach (int user in users) { SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID); - var roomUser = OnlinePlayDependencies.Client.AddUser(new APIUser { Id = user }, true); + var roomUser = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = user }, true); roomUser.MatchState = new TeamVersusUserState { @@ -105,7 +105,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddUntilStep("wait for load", () => leaderboard.IsLoaded); - AddUntilStep("wait for user population", () => Client.CurrentMatchPlayingUserIds.Count > 0); + AddUntilStep("wait for user population", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count > 0); } [Test] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs index 7c18ed2572..7d2ef8276d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerMatchSubScreen.cs @@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for join", () => RoomJoined); - AddStep("select swap mod", () => Client.ChangeUserMods(API.LocalUser.Value.OnlineID, new[] { new TaikoModSwap() })); + AddStep("select swap mod", () => MultiplayerClient.ChangeUserMods(API.LocalUser.Value.OnlineID, new[] { new TaikoModSwap() })); AddUntilStep("participant panel has mod", () => this.ChildrenOfType().Any(p => p.ChildrenOfType().Any(m => m.Mod is TaikoModSwap))); } @@ -141,17 +141,17 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("join other user (ready)", () => { - Client.AddUser(new APIUser { Id = PLAYER_1_ID }); - Client.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready); + MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }); + MultiplayerClient.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready); }); ClickButtonWhenEnabled(); - AddUntilStep("wait for spectating user state", () => Client.LocalUser?.State == MultiplayerUserState.Spectating); + AddUntilStep("wait for spectating user state", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); ClickButtonWhenEnabled(); - AddUntilStep("match started", () => Client.Room?.State == MultiplayerRoomState.WaitingForLoad); + AddUntilStep("match started", () => MultiplayerClient.Room?.State == MultiplayerRoomState.WaitingForLoad); } [Test] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs index 671b85164b..292319171d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerParticipantsList.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddAssert("one unique panel", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 1); - AddStep("add user", () => Client.AddUser(new APIUser + AddStep("add user", () => MultiplayerClient.AddUser(new APIUser { Id = 3, Username = "Second", @@ -50,15 +50,15 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddAssert("one unique panel", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 1); - AddStep("add non-resolvable user", () => Client.TestAddUnresolvedUser()); - AddAssert("null user added", () => Client.Room.AsNonNull().Users.Count(u => u.User == null) == 1); + AddStep("add non-resolvable user", () => MultiplayerClient.TestAddUnresolvedUser()); + AddAssert("null user added", () => MultiplayerClient.Room.AsNonNull().Users.Count(u => u.User == null) == 1); AddUntilStep("two unique panels", () => this.ChildrenOfType().Select(p => p.User).Distinct().Count() == 2); AddStep("kick null user", () => this.ChildrenOfType().Single(p => p.User.User == null) .ChildrenOfType().Single().TriggerClick()); - AddAssert("null user kicked", () => Client.Room.AsNonNull().Users.Count == 1); + AddAssert("null user kicked", () => MultiplayerClient.Room.AsNonNull().Users.Count == 1); } [Test] @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add a user", () => { - Client.AddUser(secondUser = new APIUser + MultiplayerClient.AddUser(secondUser = new APIUser { Id = 3, Username = "Second", @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Multiplayer }); }); - AddStep("remove host", () => Client.RemoveUser(API.LocalUser.Value)); + AddStep("remove host", () => MultiplayerClient.RemoveUser(API.LocalUser.Value)); AddAssert("single panel is for second user", () => this.ChildrenOfType().Single().User.User == secondUser); } @@ -84,21 +84,21 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestGameStateHasPriorityOverDownloadState() { - AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); + AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); checkProgressBarVisibility(true); - AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Results)); + AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Results)); checkProgressBarVisibility(false); AddUntilStep("ready mark visible", () => this.ChildrenOfType().Single().IsPresent); - AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Idle)); + AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle)); checkProgressBarVisibility(true); } [Test] public void TestCorrectInitialState() { - AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); + AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); createNewParticipantsList(); checkProgressBarVisibility(true); } @@ -106,23 +106,23 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestBeatmapDownloadingStates() { - AddStep("set to no map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded())); - AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); + AddStep("set to no map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded())); + AddStep("set to downloading map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); checkProgressBarVisibility(true); AddRepeatStep("increment progress", () => { float progress = this.ChildrenOfType().Single().User.BeatmapAvailability.DownloadProgress ?? 0; - Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f))); + MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(progress + RNG.NextSingle(0.1f))); }, 25); AddAssert("progress bar increased", () => this.ChildrenOfType().Single().Current.Value > 0); - AddStep("set to importing map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Importing())); + AddStep("set to importing map", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Importing())); checkProgressBarVisibility(false); - AddStep("set to available", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable())); + AddStep("set to available", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable())); } [Test] @@ -130,24 +130,24 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddAssert("ready mark invisible", () => !this.ChildrenOfType().Single().IsPresent); - AddStep("make user ready", () => Client.ChangeState(MultiplayerUserState.Ready)); + AddStep("make user ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Ready)); AddUntilStep("ready mark visible", () => this.ChildrenOfType().Single().IsPresent); - AddStep("make user idle", () => Client.ChangeState(MultiplayerUserState.Idle)); + AddStep("make user idle", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle)); AddUntilStep("ready mark invisible", () => !this.ChildrenOfType().Single().IsPresent); } [Test] public void TestToggleSpectateState() { - AddStep("make user spectating", () => Client.ChangeState(MultiplayerUserState.Spectating)); - AddStep("make user idle", () => Client.ChangeState(MultiplayerUserState.Idle)); + AddStep("make user spectating", () => MultiplayerClient.ChangeState(MultiplayerUserState.Spectating)); + AddStep("make user idle", () => MultiplayerClient.ChangeState(MultiplayerUserState.Idle)); } [Test] public void TestCrownChangesStateWhenHostTransferred() { - AddStep("add user", () => Client.AddUser(new APIUser + AddStep("add user", () => MultiplayerClient.AddUser(new APIUser { Id = 3, Username = "Second", @@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("first user crown visible", () => this.ChildrenOfType().ElementAt(0).ChildrenOfType().First().Alpha == 1); AddUntilStep("second user crown hidden", () => this.ChildrenOfType().ElementAt(1).ChildrenOfType().First().Alpha == 0); - AddStep("make second user host", () => Client.TransferHost(3)); + AddStep("make second user host", () => MultiplayerClient.TransferHost(3)); AddUntilStep("first user crown hidden", () => this.ChildrenOfType().ElementAt(0).ChildrenOfType().First().Alpha == 0); AddUntilStep("second user crown visible", () => this.ChildrenOfType().ElementAt(1).ChildrenOfType().First().Alpha == 1); @@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestKickButtonOnlyPresentWhenHost() { - AddStep("add user", () => Client.AddUser(new APIUser + AddStep("add user", () => MultiplayerClient.AddUser(new APIUser { Id = 3, Username = "Second", @@ -175,11 +175,11 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 1); - AddStep("make second user host", () => Client.TransferHost(3)); + AddStep("make second user host", () => MultiplayerClient.TransferHost(3)); AddUntilStep("kick buttons not visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 0); - AddStep("make local user host again", () => Client.TransferHost(API.LocalUser.Value.Id)); + AddStep("make local user host again", () => MultiplayerClient.TransferHost(API.LocalUser.Value.Id)); AddUntilStep("kick buttons visible", () => this.ChildrenOfType().Count(d => d.IsPresent) == 1); } @@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestKickButtonKicks() { - AddStep("add user", () => Client.AddUser(new APIUser + AddStep("add user", () => MultiplayerClient.AddUser(new APIUser { Id = 3, Username = "Second", @@ -196,7 +196,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("kick second user", () => this.ChildrenOfType().Single(d => d.IsPresent).TriggerClick()); - AddAssert("second user kicked", () => Client.Room?.Users.Single().UserID == API.LocalUser.Value.Id); + AddAssert("second user kicked", () => MultiplayerClient.Room?.Users.Single().UserID == API.LocalUser.Value.Id); } [Test] @@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { for (int i = 0; i < 20; i++) { - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = i, Username = $"User {i}", @@ -220,7 +220,7 @@ namespace osu.Game.Tests.Visual.Multiplayer CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }); - Client.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1)); + MultiplayerClient.ChangeUserState(i, (MultiplayerUserState)RNG.Next(0, (int)MultiplayerUserState.Results + 1)); if (RNG.NextBool()) { @@ -229,15 +229,15 @@ namespace osu.Game.Tests.Visual.Multiplayer switch (beatmapState) { case DownloadState.NotDownloaded: - Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.NotDownloaded()); + MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.NotDownloaded()); break; case DownloadState.Downloading: - Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Downloading(RNG.NextSingle())); + MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Downloading(RNG.NextSingle())); break; case DownloadState.Importing: - Client.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Importing()); + MultiplayerClient.ChangeUserBeatmapAvailability(i, BeatmapAvailability.Importing()); break; } } @@ -250,7 +250,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add user", () => { - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 0, Username = "User 0", @@ -264,7 +264,7 @@ namespace osu.Game.Tests.Visual.Multiplayer CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }); - Client.ChangeUserMods(0, new Mod[] + MultiplayerClient.ChangeUserMods(0, new Mod[] { new OsuModHardRock(), new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } } @@ -274,12 +274,12 @@ namespace osu.Game.Tests.Visual.Multiplayer for (var i = MultiplayerUserState.Idle; i < MultiplayerUserState.Results; i++) { var state = i; - AddStep($"set state: {state}", () => Client.ChangeUserState(0, state)); + AddStep($"set state: {state}", () => MultiplayerClient.ChangeUserState(0, state)); } - AddStep("set state: downloading", () => Client.ChangeUserBeatmapAvailability(0, BeatmapAvailability.Downloading(0))); + AddStep("set state: downloading", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.Downloading(0))); - AddStep("set state: locally available", () => Client.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable())); + AddStep("set state: locally available", () => MultiplayerClient.ChangeUserBeatmapAvailability(0, BeatmapAvailability.LocallyAvailable())); } [Test] @@ -287,7 +287,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add dummy mods", () => { - Client.ChangeUserMods(new Mod[] + MultiplayerClient.ChangeUserMods(new Mod[] { new OsuModNoFail(), new OsuModDoubleTime() @@ -296,7 +296,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("add user with mods", () => { - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 0, Username = "Baka", @@ -309,34 +309,34 @@ namespace osu.Game.Tests.Visual.Multiplayer }, CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }); - Client.ChangeUserMods(0, new Mod[] + MultiplayerClient.ChangeUserMods(0, new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() }); }); - AddStep("set 0 ready", () => Client.ChangeState(MultiplayerUserState.Ready)); + AddStep("set 0 ready", () => MultiplayerClient.ChangeState(MultiplayerUserState.Ready)); - AddStep("set 1 spectate", () => Client.ChangeUserState(0, MultiplayerUserState.Spectating)); + AddStep("set 1 spectate", () => MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Spectating)); // Have to set back to idle due to status priority. AddStep("set 0 no map, 1 ready", () => { - Client.ChangeState(MultiplayerUserState.Idle); - Client.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded()); - Client.ChangeUserState(0, MultiplayerUserState.Ready); + MultiplayerClient.ChangeState(MultiplayerUserState.Idle); + MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.NotDownloaded()); + MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Ready); }); - AddStep("set 0 downloading", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); + AddStep("set 0 downloading", () => MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0))); - AddStep("set 0 spectate", () => Client.ChangeUserState(0, MultiplayerUserState.Spectating)); + AddStep("set 0 spectate", () => MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Spectating)); AddStep("make both default", () => { - Client.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()); - Client.ChangeUserState(0, MultiplayerUserState.Idle); - Client.ChangeState(MultiplayerUserState.Idle); + MultiplayerClient.ChangeBeatmapAvailability(BeatmapAvailability.LocallyAvailable()); + MultiplayerClient.ChangeUserState(0, MultiplayerUserState.Idle); + MultiplayerClient.ChangeState(MultiplayerUserState.Idle); }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs index 010e9dc078..d391fbcf8f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs @@ -28,15 +28,15 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("initialise gameplay", () => { - Stack.Push(player = new MultiplayerPlayer(Client.APIRoom, new PlaylistItem + Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.APIRoom, new PlaylistItem { Beatmap = { Value = Beatmap.Value.BeatmapInfo }, RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID, - }, Client.Room?.Users.ToArray())); + }, MultiplayerClient.Room?.Users.ToArray())); }); AddUntilStep("wait for player to be current", () => player.IsCurrentScreen() && player.IsLoaded); - AddStep("start gameplay", () => ((IMultiplayerClient)Client).MatchStarted()); + AddStep("start gameplay", () => ((IMultiplayerClient)MultiplayerClient).MatchStarted()); } [Test] diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs index 7bc5990c32..f84abc7443 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs @@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual.Multiplayer importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0); }); - AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); + AddStep("change to all players mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); } [Test] @@ -97,19 +97,19 @@ namespace osu.Game.Tests.Visual.Multiplayer addItemStep(); addItemStep(); - AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); + AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely()); assertItemInHistoryListStep(1, 0); assertItemInQueueListStep(2, 0); assertItemInQueueListStep(3, 1); - AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); + AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely()); assertItemInHistoryListStep(2, 0); assertItemInHistoryListStep(1, 1); assertItemInQueueListStep(3, 0); - AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); + AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely()); assertItemInHistoryListStep(3, 0); assertItemInHistoryListStep(2, 1); @@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestListsClearedWhenRoomLeft() { addItemStep(); - AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); + AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely()); AddStep("leave room", () => RoomManager.PartRoom()); AddUntilStep("wait for room part", () => !RoomJoined); @@ -167,7 +167,7 @@ namespace osu.Game.Tests.Visual.Multiplayer /// /// Adds a step to create a new playlist item. /// - private void addItemStep(bool expired = false) => AddStep("add item", () => Client.AddPlaylistItem(new MultiplayerPlaylistItem(new PlaylistItem + private void addItemStep(bool expired = false) => AddStep("add item", () => MultiplayerClient.AddPlaylistItem(new MultiplayerPlaylistItem(new PlaylistItem { Beatmap = { Value = importedBeatmap }, BeatmapID = importedBeatmap.OnlineID, diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs index 0b3e1ba20a..bf06b6ad73 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerQueueList.cs @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(500, 300), - Items = { BindTarget = Client.APIRoom!.Playlist } + Items = { BindTarget = MultiplayerClient.APIRoom!.Playlist } }; }); @@ -61,14 +61,14 @@ namespace osu.Game.Tests.Visual.Multiplayer importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0); }); - AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); + AddStep("change to all players mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); } [Test] public void TestDeleteButtonAlwaysVisibleForHost() { - AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); + AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); addPlaylistItem(() => API.LocalUser.Value.OnlineID); assertDeleteButtonVisibility(1, true); @@ -79,18 +79,18 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDeleteButtonOnlyVisibleForItemOwnerIfNotHost() { - AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); + AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); - AddStep("join other user", () => Client.AddUser(new APIUser { Id = 1234 })); - AddStep("set other user as host", () => Client.TransferHost(1234)); + AddStep("join other user", () => MultiplayerClient.AddUser(new APIUser { Id = 1234 })); + AddStep("set other user as host", () => MultiplayerClient.TransferHost(1234)); addPlaylistItem(() => API.LocalUser.Value.OnlineID); assertDeleteButtonVisibility(1, true); addPlaylistItem(() => 1234); assertDeleteButtonVisibility(2, false); - AddStep("set local user as host", () => Client.TransferHost(API.LocalUser.Value.OnlineID)); + AddStep("set local user as host", () => MultiplayerClient.TransferHost(API.LocalUser.Value.OnlineID)); assertDeleteButtonVisibility(1, true); assertDeleteButtonVisibility(2, true); } @@ -98,16 +98,16 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestCurrentItemDoesNotHaveDeleteButton() { - AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); - AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); + AddStep("set all players queue mode", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely()); + AddUntilStep("wait for queue mode change", () => MultiplayerClient.APIRoom?.QueueMode.Value == QueueMode.AllPlayers); addPlaylistItem(() => API.LocalUser.Value.OnlineID); assertDeleteButtonVisibility(0, false); assertDeleteButtonVisibility(1, true); - AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely()); - AddUntilStep("wait for next item to be selected", () => Client.Room?.Settings.PlaylistItemId == 2); + AddStep("finish current item", () => MultiplayerClient.FinishCurrentItem().WaitSafely()); + AddUntilStep("wait for next item to be selected", () => MultiplayerClient.Room?.Settings.PlaylistItemId == 2); AddUntilStep("wait for two items in playlist", () => playlist.ChildrenOfType().Count() == 2); assertDeleteButtonVisibility(0, false); @@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.Multiplayer BeatmapID = importedBeatmap.OnlineID, }); - Client.AddUserPlaylistItem(userId(), item).WaitSafely(); + MultiplayerClient.AddUserPlaylistItem(userId(), item).WaitSafely(); itemId = item.ID; }); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs index 7834226f15..609693e54b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs @@ -74,13 +74,13 @@ namespace osu.Game.Tests.Visual.Multiplayer Task.Run(async () => { - if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + if (MultiplayerClient.IsHost && MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready) { - await Client.StartMatch(); + await MultiplayerClient.StartMatch(); return; } - await Client.ToggleReady(); + await MultiplayerClient.ToggleReady(); readyClickOperation.Dispose(); }); @@ -110,15 +110,15 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add second user as host", () => { - Client.AddUser(new APIUser { Id = 2, Username = "Another user" }); - Client.TransferHost(2); + MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); + MultiplayerClient.TransferHost(2); }); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); - AddUntilStep("user is idle", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); } [TestCase(true)] @@ -127,14 +127,14 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("setup", () => { - Client.TransferHost(Client.Room?.Users[0].UserID ?? 0); + MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0); if (!allReady) - Client.AddUser(new APIUser { Id = 2, Username = "Another user" }); + MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); }); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); verifyGameplayStartFlow(); } @@ -144,12 +144,12 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add host", () => { - Client.AddUser(new APIUser { Id = 2, Username = "Another user" }); - Client.TransferHost(2); + MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); + MultiplayerClient.TransferHost(2); }); ClickButtonWhenEnabled(); - AddStep("make user host", () => Client.TransferHost(Client.Room?.Users[0].UserID ?? 0)); + AddStep("make user host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0)); verifyGameplayStartFlow(); } @@ -159,17 +159,17 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("setup", () => { - Client.TransferHost(Client.Room?.Users[0].UserID ?? 0); - Client.AddUser(new APIUser { Id = 2, Username = "Another user" }); + MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0); + MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); }); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); - AddStep("transfer host", () => Client.TransferHost(Client.Room?.Users[1].UserID ?? 0)); + AddStep("transfer host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[1].UserID ?? 0)); ClickButtonWhenEnabled(); - AddUntilStep("user is idle (match not started)", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle (match not started)", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); AddAssert("ready button enabled", () => button.ChildrenOfType().Single().Enabled.Value); } @@ -180,42 +180,42 @@ namespace osu.Game.Tests.Visual.Multiplayer const int users = 10; AddStep("setup", () => { - Client.TransferHost(Client.Room?.Users[0].UserID ?? 0); + MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0); for (int i = 0; i < users; i++) - Client.AddUser(new APIUser { Id = i, Username = "Another user" }); + MultiplayerClient.AddUser(new APIUser { Id = i, Username = "Another user" }); }); if (!isHost) - AddStep("transfer host", () => Client.TransferHost(2)); + AddStep("transfer host", () => MultiplayerClient.TransferHost(2)); ClickButtonWhenEnabled(); AddRepeatStep("change user ready state", () => { - Client.ChangeUserState(RNG.Next(0, users), RNG.NextBool() ? MultiplayerUserState.Ready : MultiplayerUserState.Idle); + MultiplayerClient.ChangeUserState(RNG.Next(0, users), RNG.NextBool() ? MultiplayerUserState.Ready : MultiplayerUserState.Idle); }, 20); AddRepeatStep("ready all users", () => { - var nextUnready = Client.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); + var nextUnready = MultiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); if (nextUnready != null) - Client.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); + MultiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); }, users); } private void verifyGameplayStartFlow() { - AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); - AddUntilStep("user waiting for load", () => Client.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad); + AddUntilStep("user waiting for load", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad); AddAssert("ready button disabled", () => !button.ChildrenOfType().Single().Enabled.Value); AddStep("transitioned to gameplay", () => readyClickOperation.Dispose()); AddStep("finish gameplay", () => { - Client.ChangeUserState(Client.Room?.Users[0].UserID ?? 0, MultiplayerUserState.Loaded); - Client.ChangeUserState(Client.Room?.Users[0].UserID ?? 0, MultiplayerUserState.FinishedPlay); + MultiplayerClient.ChangeUserState(MultiplayerClient.Room?.Users[0].UserID ?? 0, MultiplayerUserState.Loaded); + MultiplayerClient.ChangeUserState(MultiplayerClient.Room?.Users[0].UserID ?? 0, MultiplayerUserState.FinishedPlay); }); AddUntilStep("ready button enabled", () => button.ChildrenOfType().Single().Enabled.Value); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs index 70d4d9dd55..c4ea78116a 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerSpectateButton.cs @@ -78,7 +78,7 @@ namespace osu.Game.Tests.Visual.Multiplayer Task.Run(async () => { - await Client.ToggleSpectate(); + await MultiplayerClient.ToggleSpectate(); readyClickOperation.Dispose(); }); } @@ -94,13 +94,13 @@ namespace osu.Game.Tests.Visual.Multiplayer Task.Run(async () => { - if (Client.IsHost && Client.LocalUser?.State == MultiplayerUserState.Ready) + if (MultiplayerClient.IsHost && MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready) { - await Client.StartMatch(); + await MultiplayerClient.StartMatch(); return; } - await Client.ToggleReady(); + await MultiplayerClient.ToggleReady(); readyClickOperation.Dispose(); }); @@ -115,7 +115,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [TestCase(MultiplayerRoomState.Playing)] public void TestEnabledWhenRoomOpenOrInGameplay(MultiplayerRoomState roomState) { - AddStep($"change room to {roomState}", () => Client.ChangeRoomState(roomState)); + AddStep($"change room to {roomState}", () => MultiplayerClient.ChangeRoomState(roomState)); assertSpectateButtonEnablement(true); } @@ -124,16 +124,16 @@ namespace osu.Game.Tests.Visual.Multiplayer public void TestToggleWhenIdle(MultiplayerUserState initialState) { ClickButtonWhenEnabled(); - AddUntilStep("user is spectating", () => Client.Room?.Users[0].State == MultiplayerUserState.Spectating); + AddUntilStep("user is spectating", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Spectating); ClickButtonWhenEnabled(); - AddUntilStep("user is idle", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); } [TestCase(MultiplayerRoomState.Closed)] public void TestDisabledWhenClosed(MultiplayerRoomState roomState) { - AddStep($"change room to {roomState}", () => Client.ChangeRoomState(roomState)); + AddStep($"change room to {roomState}", () => MultiplayerClient.ChangeRoomState(roomState)); assertSpectateButtonEnablement(false); } @@ -147,8 +147,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestReadyButtonEnabledWhenHostAndUsersReady() { - AddStep("add user", () => Client.AddUser(new APIUser { Id = PLAYER_1_ID })); - AddStep("set user ready", () => Client.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready)); + AddStep("add user", () => MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID })); + AddStep("set user ready", () => MultiplayerClient.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready)); ClickButtonWhenEnabled(); assertReadyButtonEnablement(true); @@ -159,11 +159,11 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add user and transfer host", () => { - Client.AddUser(new APIUser { Id = PLAYER_1_ID }); - Client.TransferHost(PLAYER_1_ID); + MultiplayerClient.AddUser(new APIUser { Id = PLAYER_1_ID }); + MultiplayerClient.TransferHost(PLAYER_1_ID); }); - AddStep("set user ready", () => Client.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready)); + AddStep("set user ready", () => MultiplayerClient.ChangeUserState(PLAYER_1_ID, MultiplayerUserState.Ready)); ClickButtonWhenEnabled(); assertReadyButtonEnablement(false); diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs index 823ac07cf7..f95e73ff3c 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneRankRangePill.cs @@ -25,14 +25,14 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add user", () => { - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 2, Statistics = { GlobalRank = 1234 } }); // Remove the local user so only the one above is displayed. - Client.RemoveUser(API.LocalUser.Value); + MultiplayerClient.RemoveUser(API.LocalUser.Value); }); } @@ -41,26 +41,26 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add users", () => { - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 2, Statistics = { GlobalRank = 1234 } }); - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 3, Statistics = { GlobalRank = 3333 } }); - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 4, Statistics = { GlobalRank = 4321 } }); // Remove the local user so only the ones above are displayed. - Client.RemoveUser(API.LocalUser.Value); + MultiplayerClient.RemoveUser(API.LocalUser.Value); }); } @@ -75,20 +75,20 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add users", () => { - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 2, Statistics = { GlobalRank = min } }); - Client.AddUser(new APIUser + MultiplayerClient.AddUser(new APIUser { Id = 3, Statistics = { GlobalRank = max } }); // Remove the local user so only the ones above are displayed. - Client.RemoveUser(API.LocalUser.Value); + MultiplayerClient.RemoveUser(API.LocalUser.Value); }); } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs index 7a5bd0b8f4..50b3f52047 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs @@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Multiplayer private TestMultiplayerComponents multiplayerComponents; - private TestMultiplayerClient client => multiplayerComponents.Client; + private TestMultiplayerClient multiplayerClient => multiplayerComponents.MultiplayerClient; [BackgroundDependencyLoader] private void load(GameHost host, AudioManager audio) @@ -75,8 +75,8 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddUntilStep("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus); - AddAssert("user state arrived", () => client.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState); + AddUntilStep("room type is team vs", () => multiplayerClient.Room?.Settings.MatchType == MatchType.TeamVersus); + AddAssert("user state arrived", () => multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState); } [Test] @@ -96,25 +96,25 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); - AddStep("add another user", () => client.AddUser(new APIUser { Username = "otheruser", Id = 44 })); + AddAssert("user on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + AddStep("add another user", () => multiplayerClient.AddUser(new APIUser { Username = "otheruser", Id = 44 })); AddStep("press own button", () => { InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().First()); InputManager.Click(MouseButton.Left); }); - AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1); + AddAssert("user on team 1", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1); AddStep("press own button again", () => InputManager.Click(MouseButton.Left)); - AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + AddAssert("user on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); AddStep("press other user's button", () => { InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().ElementAt(1)); InputManager.Click(MouseButton.Left); }); - AddAssert("user still on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); + AddAssert("user still on team 0", () => (multiplayerClient.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0); } [Test] @@ -134,14 +134,14 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddUntilStep("match type head to head", () => client.APIRoom?.Type.Value == MatchType.HeadToHead); + AddUntilStep("match type head to head", () => multiplayerClient.APIRoom?.Type.Value == MatchType.HeadToHead); - AddStep("change match type", () => client.ChangeSettings(new MultiplayerRoomSettings + AddStep("change match type", () => multiplayerClient.ChangeSettings(new MultiplayerRoomSettings { MatchType = MatchType.TeamVersus }).WaitSafely()); - AddUntilStep("api room updated to team versus", () => client.APIRoom?.Type.Value == MatchType.TeamVersus); + AddUntilStep("api room updated to team versus", () => multiplayerClient.APIRoom?.Type.Value == MatchType.TeamVersus); } [Test] @@ -160,13 +160,13 @@ namespace osu.Game.Tests.Visual.Multiplayer } }); - AddUntilStep("room type is head to head", () => client.Room?.Settings.MatchType == MatchType.HeadToHead); + AddUntilStep("room type is head to head", () => multiplayerClient.Room?.Settings.MatchType == MatchType.HeadToHead); AddUntilStep("team displays are not displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam == null)); - AddStep("change to team vs", () => client.ChangeSettings(matchType: MatchType.TeamVersus)); + AddStep("change to team vs", () => multiplayerClient.ChangeSettings(matchType: MatchType.TeamVersus)); - AddUntilStep("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus); + AddUntilStep("room type is team vs", () => multiplayerClient.Room?.Settings.MatchType == MatchType.TeamVersus); AddUntilStep("team displays are displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam != null)); } @@ -185,7 +185,7 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.Click(MouseButton.Left); }); - AddUntilStep("wait for join", () => client.RoomJoined); + AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); } } } diff --git a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs index bd8fb8e58e..062aa33b99 100644 --- a/osu.Game.Tests/Visual/TestMultiplayerComponents.cs +++ b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual public new bool IsLoaded => base.IsLoaded && MultiplayerScreen.IsLoaded; [Cached(typeof(MultiplayerClient))] - public readonly TestMultiplayerClient Client; + public readonly TestMultiplayerClient MultiplayerClient; [Cached(typeof(UserLookupCache))] private readonly UserLookupCache userLookupCache = new TestUserLookupCache(); @@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual { userLookupCache, beatmapLookupCache, - Client = new TestMultiplayerClient(RoomManager), + MultiplayerClient = new TestMultiplayerClient(RoomManager), screenStack = new OsuScreenStack { Name = nameof(TestMultiplayerComponents), diff --git a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs index f166154103..62d1c9ceca 100644 --- a/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/IMultiplayerTestSceneDependencies.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Online.Multiplayer; using osu.Game.Screens.OnlinePlay; using osu.Game.Tests.Visual.OnlinePlay; using osu.Game.Tests.Visual.Spectator; @@ -14,9 +13,9 @@ namespace osu.Game.Tests.Visual.Multiplayer public interface IMultiplayerTestSceneDependencies : IOnlinePlayTestSceneDependencies { /// - /// The cached . + /// The cached . /// - TestMultiplayerClient Client { get; } + TestMultiplayerClient MultiplayerClient { get; } /// /// The cached . diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs index a9b3ca4991..19f9952d14 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs @@ -17,13 +17,13 @@ namespace osu.Game.Tests.Visual.Multiplayer public const int PLAYER_1_ID = 55; public const int PLAYER_2_ID = 56; - public TestMultiplayerClient Client => OnlinePlayDependencies.Client; + public TestMultiplayerClient MultiplayerClient => OnlinePlayDependencies.MultiplayerClient; public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager; public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient; protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies; - public bool RoomJoined => Client.RoomJoined; + public bool RoomJoined => MultiplayerClient.RoomJoined; private readonly bool joinRoom; diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs index d9fe77ae44..6b4e01b673 100644 --- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs +++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestSceneDependencies.cs @@ -14,16 +14,16 @@ namespace osu.Game.Tests.Visual.Multiplayer /// public class MultiplayerTestSceneDependencies : OnlinePlayTestSceneDependencies, IMultiplayerTestSceneDependencies { - public TestMultiplayerClient Client { get; } + public TestMultiplayerClient MultiplayerClient { get; } public TestSpectatorClient SpectatorClient { get; } public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager; public MultiplayerTestSceneDependencies() { - Client = new TestMultiplayerClient(RoomManager); + MultiplayerClient = new TestMultiplayerClient(RoomManager); SpectatorClient = CreateSpectatorClient(); - CacheAs(Client); + CacheAs(MultiplayerClient); CacheAs(SpectatorClient); }