diff --git a/README.md b/README.md
index 24b70b2de6..f18c5e76f9 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) or higher installed.
+- A desktop platform with the [.NET 5.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.
diff --git a/osu.Android.props b/osu.Android.props
index 563836d29b..1532d4ce23 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
index 3211405670..844fe7705a 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
@@ -85,6 +85,7 @@ namespace osu.Game.Tests.Visual.Background
// of note, this needs to be a type that doesn't match BackgroundScreenDefault else it is silently not pushed by the background stack.
AddStep("push new background to stack", () => stack.Push(nestedScreen = new BackgroundScreenBeatmap(Beatmap.Value)));
AddUntilStep("wait for screen to load", () => nestedScreen.IsLoaded && nestedScreen.IsCurrentScreen());
+ AddUntilStep("previous background hidden", () => !screen.IsAlive);
AddAssert("top level background hasn't changed yet", () => screen.CheckLastLoadChange() == null);
diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
index 357db16e2c..5acb44ac45 100644
--- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
@@ -31,17 +31,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
protected BeatmapInfo InitialBeatmap { get; private set; }
protected BeatmapInfo OtherBeatmap { get; private set; }
- protected IScreen CurrentScreen => multiplayerScreenStack.CurrentScreen;
- protected IScreen CurrentSubScreen => multiplayerScreenStack.MultiplayerScreen.CurrentSubScreen;
+ protected IScreen CurrentScreen => multiplayerComponents.CurrentScreen;
+ protected IScreen CurrentSubScreen => multiplayerComponents.MultiplayerScreen.CurrentSubScreen;
private BeatmapManager beatmaps;
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
- private TestMultiplayerScreenStack multiplayerScreenStack;
+ private TestMultiplayerComponents multiplayerComponents;
- protected TestMultiplayerClient Client => multiplayerScreenStack.Client;
- protected TestMultiplayerRoomManager RoomManager => multiplayerScreenStack.RoomManager;
+ protected TestMultiplayerClient Client => multiplayerComponents.Client;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -65,12 +64,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
OtherBeatmap = importedSet.Beatmaps.Last(b => b.RulesetID == 0);
});
- AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack()));
- AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded);
+ AddStep("load multiplayer", () => LoadScreen(multiplayerComponents = new TestMultiplayerComponents()));
+ AddUntilStep("wait for multiplayer to load", () => multiplayerComponents.IsLoaded);
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
- AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(new Room
+ AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open(new Room
{
Name = { Value = "Test Room" },
QueueMode = { Value = Mode },
@@ -93,7 +92,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("wait for join", () => RoomManager.RoomJoined);
+ AddUntilStep("wait for join", () => Client.RoomJoined);
}
[Test]
@@ -110,8 +109,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
clickReadyButton();
- AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player player && player.IsLoaded);
- AddStep("exit player", () => multiplayerScreenStack.MultiplayerScreen.MakeCurrent());
+ AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded);
+ AddStep("exit player", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
}
private void clickReadyButton()
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index 710855a605..bd0e5c4eb9 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -46,10 +46,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
- private TestMultiplayerScreenStack multiplayerScreenStack;
+ private TestMultiplayerComponents multiplayerComponents;
- private TestMultiplayerClient client => multiplayerScreenStack.Client;
- private TestMultiplayerRoomManager roomManager => multiplayerScreenStack.RoomManager;
+ private TestMultiplayerClient client => multiplayerComponents.Client;
+ private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -71,8 +71,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
});
- AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack()));
- AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded);
+ AddStep("load multiplayer", () => LoadScreen(multiplayerComponents = new TestMultiplayerComponents()));
+ AddUntilStep("wait for multiplayer to load", () => multiplayerComponents.IsLoaded);
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
}
@@ -216,7 +216,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", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
[Test]
@@ -295,7 +295,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", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.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);
@@ -353,7 +353,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", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
[Test]
@@ -419,7 +419,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("Enter song select", () =>
{
- var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerScreenStack.CurrentScreen).CurrentSubScreen;
+ var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId);
});
@@ -433,7 +433,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("start match externally", () => client.StartMatch());
- AddUntilStep("play started", () => multiplayerScreenStack.CurrentScreen is Player);
+ AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == client.Room?.Playlist.First().BeatmapID);
}
@@ -473,7 +473,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("start match externally", () => client.StartMatch());
- AddAssert("play not started", () => multiplayerScreenStack.IsCurrentScreen());
+ AddAssert("play not started", () => multiplayerComponents.IsCurrentScreen());
}
[Test]
@@ -517,7 +517,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
});
- AddUntilStep("play started", () => multiplayerScreenStack.CurrentScreen is SpectatorScreen);
+ AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is SpectatorScreen);
}
[Test]
@@ -559,16 +559,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("open mod overlay", () => this.ChildrenOfType().Single().TriggerClick());
- AddStep("invoke on back button", () => multiplayerScreenStack.OnBackButton());
+ AddStep("invoke on back button", () => multiplayerComponents.OnBackButton());
AddAssert("mod overlay is hidden", () => this.ChildrenOfType().Single().State.Value == Visibility.Hidden);
AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden);
- testLeave("back button", () => multiplayerScreenStack.OnBackButton());
+ testLeave("back button", () => multiplayerComponents.OnBackButton());
// mimics home button and OS window close
- testLeave("forced exit", () => multiplayerScreenStack.Exit());
+ testLeave("forced exit", () => multiplayerComponents.Exit());
void testLeave(string actionName, Action action)
{
@@ -605,7 +605,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep($"wait for time > {i}", () => this.ChildrenOfType().SingleOrDefault()?.GameplayClock.CurrentTime > time);
}
- AddUntilStep("wait for results", () => multiplayerScreenStack.CurrentScreen is ResultsScreen);
+ AddUntilStep("wait for results", () => multiplayerComponents.CurrentScreen is ResultsScreen);
}
[Test]
@@ -646,7 +646,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", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
AddAssert("local room has correct settings", () =>
{
@@ -680,15 +680,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready));
pressReadyButton(1234);
- AddUntilStep("wait for gameplay", () => (multiplayerScreenStack.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
+ AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
AddStep("press back button and exit", () =>
{
- multiplayerScreenStack.OnBackButton();
- multiplayerScreenStack.Exit();
+ multiplayerComponents.OnBackButton();
+ multiplayerComponents.Exit();
});
- AddUntilStep("wait for return to match subscreen", () => multiplayerScreenStack.MultiplayerScreen.IsCurrentScreen());
+ AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
}
@@ -716,17 +716,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready));
pressReadyButton(1234);
- AddUntilStep("wait for gameplay", () => (multiplayerScreenStack.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
+ 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("press back button and exit", () =>
{
- multiplayerScreenStack.OnBackButton();
- multiplayerScreenStack.Exit();
+ multiplayerComponents.OnBackButton();
+ multiplayerComponents.Exit();
});
- AddUntilStep("wait for return to match subscreen", () => multiplayerScreenStack.MultiplayerScreen.IsCurrentScreen());
+ 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);
}
@@ -758,7 +758,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2);
- AddStep("exit gameplay as initial user", () => multiplayerScreenStack.MultiplayerScreen.MakeCurrent());
+ AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
AddUntilStep("queue contains item", () => this.ChildrenOfType().Single().Items.Single().ID == 2);
}
@@ -792,7 +792,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2));
AddUntilStep("item removed from playlist", () => client.Room?.Playlist.Count == 1);
- AddStep("exit gameplay as initial user", () => multiplayerScreenStack.MultiplayerScreen.MakeCurrent());
+ AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
AddUntilStep("queue is empty", () => this.ChildrenOfType().Single().Items.Count == 0);
}
@@ -800,7 +800,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
pressReadyButton();
pressReadyButton();
- AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player);
+ AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player);
}
private ReadyButton readyButton => this.ChildrenOfType().Single();
@@ -826,8 +826,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createRoom(Func room)
{
- AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(room()));
+ AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open(room()));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
@@ -838,7 +838,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("wait for join", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
}
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
index 84b63a5733..81220e2527 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
@@ -163,10 +163,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
});
addClickButtonStep();
+ AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
+
AddStep("transfer host", () => Client.TransferHost(Client.Room?.Users[1].UserID ?? 0));
addClickButtonStep();
- AddAssert("match not started", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
+ AddUntilStep("user is idle (match not started)", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
+ AddAssert("ready button enabled", () => button.ChildrenOfType().Single().Enabled.Value);
}
[TestCase(true)]
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
index ccce26ad31..81c59b90f5 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
@@ -31,9 +31,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
- private TestMultiplayerScreenStack multiplayerScreenStack;
+ private TestMultiplayerComponents multiplayerComponents;
- private TestMultiplayerClient client => multiplayerScreenStack.Client;
+ private TestMultiplayerClient client => multiplayerComponents.Client;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -55,8 +55,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
});
- AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack()));
- AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded);
+ AddStep("load multiplayer", () => LoadScreen(multiplayerComponents = new TestMultiplayerComponents()));
+ AddUntilStep("wait for multiplayer to load", () => multiplayerComponents.IsLoaded);
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
}
@@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press own button", () =>
{
- InputManager.MoveMouseTo(multiplayerScreenStack.ChildrenOfType().First());
+ InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().First());
InputManager.Click(MouseButton.Left);
});
AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1);
@@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press other user's button", () =>
{
- InputManager.MoveMouseTo(multiplayerScreenStack.ChildrenOfType().ElementAt(1));
+ 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);
@@ -164,18 +164,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("room type is head to head", () => client.Room?.Settings.MatchType == MatchType.HeadToHead);
- AddUntilStep("team displays are not displaying teams", () => multiplayerScreenStack.ChildrenOfType().All(d => d.DisplayedTeam == null));
+ AddUntilStep("team displays are not displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam == null));
AddStep("change to team vs", () => client.ChangeSettings(matchType: MatchType.TeamVersus));
AddUntilStep("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus);
- AddUntilStep("team displays are displaying teams", () => multiplayerScreenStack.ChildrenOfType().All(d => d.DisplayedTeam != null));
+ AddUntilStep("team displays are displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam != null));
}
private void createRoom(Func room)
{
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(room()));
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open(room()));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
@@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("wait for join", () => multiplayerScreenStack.RoomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
}
}
diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
index 664c186cf8..48ab643992 100644
--- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
@@ -336,12 +336,12 @@ namespace osu.Game.Tests.Visual.Navigation
[Test]
public void TestPushMatchSubScreenAndPressBackButtonImmediately()
{
- TestMultiplayerScreenStack multiplayerScreenStack = null;
+ TestMultiplayerComponents multiplayerComponents = null;
- PushAndConfirm(() => multiplayerScreenStack = new TestMultiplayerScreenStack());
+ PushAndConfirm(() => multiplayerComponents = new TestMultiplayerComponents());
- AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open());
+ AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open());
AddStep("press back button", () => Game.ChildrenOfType().First().Action());
AddWaitStep("wait two frames", 2);
}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
index 76997bded7..dda9543159 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
@@ -2,9 +2,10 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Linq;
+using NUnit.Framework;
using osu.Framework.Allocation;
-using osu.Game.Online.API;
-using osu.Game.Online.API.Requests;
+using osu.Framework.Testing;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
@@ -14,72 +15,77 @@ namespace osu.Game.Tests.Visual.Online
{
public class TestSceneUserProfileHeader : OsuTestScene
{
- protected override bool UseOnlineAPI => true;
-
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
- [Resolved]
- private IAPIProvider api { get; set; }
+ private ProfileHeader header;
- private readonly ProfileHeader header;
-
- public TestSceneUserProfileHeader()
+ [SetUpSteps]
+ public void SetUpSteps()
{
- header = new ProfileHeader();
- Add(header);
+ AddStep("create header", () => Child = header = new ProfileHeader());
+ }
- AddStep("Show test dummy", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER);
+ [Test]
+ public void TestBasic()
+ {
+ AddStep("Show example user", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER);
+ }
- AddStep("Show null dummy", () => header.User.Value = new APIUser
- {
- Username = "Null"
- });
-
- AddStep("Show online dummy", () => header.User.Value = new APIUser
+ [Test]
+ public void TestOnlineState()
+ {
+ AddStep("Show online user", () => header.User.Value = new APIUser
{
+ Id = 1001,
Username = "IAmOnline",
LastVisit = DateTimeOffset.Now,
IsOnline = true,
});
- AddStep("Show offline dummy", () => header.User.Value = new APIUser
+ AddStep("Show offline user", () => header.User.Value = new APIUser
{
+ Id = 1002,
Username = "IAmOffline",
- LastVisit = DateTimeOffset.Now,
+ LastVisit = DateTimeOffset.Now.AddDays(-10),
IsOnline = false,
});
-
- addOnlineStep("Show ppy", new APIUser
- {
- Username = @"peppy",
- Id = 2,
- IsSupporter = true,
- Country = new Country { FullName = @"Australia", FlagName = @"AU" },
- CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
- });
-
- addOnlineStep("Show flyte", new APIUser
- {
- Username = @"flyte",
- Id = 3103765,
- Country = new Country { FullName = @"Japan", FlagName = @"JP" },
- CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
- });
}
- private void addOnlineStep(string name, APIUser fallback)
+ [Test]
+ public void TestRankedState()
{
- AddStep(name, () =>
+ AddStep("Show ranked user", () => header.User.Value = new APIUser
{
- if (api.IsLoggedIn)
+ Id = 2001,
+ Username = "RankedUser",
+ Statistics = new UserStatistics
{
- var request = new GetUserRequest(fallback.Id);
- request.Success += user => header.User.Value = user;
- api.Queue(request);
+ IsRanked = true,
+ GlobalRank = 15000,
+ CountryRank = 1500,
+ RankHistory = new APIRankHistory
+ {
+ Mode = @"osu",
+ Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
+ },
+ }
+ });
+
+ AddStep("Show unranked user", () => header.User.Value = new APIUser
+ {
+ Id = 2002,
+ Username = "UnrankedUser",
+ Statistics = new UserStatistics
+ {
+ IsRanked = false,
+ // web will sometimes return non-empty rank history even for unranked users.
+ RankHistory = new APIRankHistory
+ {
+ Mode = @"osu",
+ Data = Enumerable.Range(2345, 85).ToArray()
+ },
}
- else
- header.User.Value = fallback;
});
}
}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs
index 1c92bb1e38..78e2ceb45b 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs
@@ -29,6 +29,7 @@ namespace osu.Game.Tests.Visual.Online
ProfileOrder = new[] { "me" },
Statistics = new UserStatistics
{
+ IsRanked = true,
GlobalRank = 2148,
CountryRank = 1,
PP = 4567.89m,
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
index 25ca1299ef..e9210496ca 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
@@ -168,12 +168,13 @@ namespace osu.Game.Tests.Visual.Playlists
}));
});
+ AddUntilStep("wait for screen to load", () => resultsScreen.IsLoaded);
waitForDisplay();
}
private void waitForDisplay()
{
- AddUntilStep("wait for load to complete", () =>
+ AddUntilStep("wait for scores loaded", () =>
requestComplete
&& resultsScreen.ScorePanelList.GetScorePanels().Count() == totalCount
&& resultsScreen.ScorePanelList.AllPanelsVisible);
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index be390742ea..912d3f838c 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -466,7 +466,9 @@ namespace osu.Game.Tests.Visual.SongSelect
public void TestExternalBeatmapChangeWhileFiltered(bool differentRuleset)
{
createSongSelect();
- addManyTestMaps();
+ // ensure there is at least 1 difficulty for each of the rulesets
+ // (catch is excluded inside of addManyTestMaps).
+ addManyTestMaps(3);
changeRuleset(0);
@@ -488,8 +490,9 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("select beatmap externally", () =>
{
target = manager.GetAllUsableBeatmapSets()
- .Where(b => b.Beatmaps.Any(bi => bi.RulesetID == targetRuleset))
- .ElementAt(5).Beatmaps.First(bi => bi.RulesetID == targetRuleset);
+ .First(b => b.Beatmaps.Any(bi => bi.RulesetID == targetRuleset))
+ .Beatmaps
+ .First(bi => bi.RulesetID == targetRuleset);
Beatmap.Value = manager.GetWorkingBeatmap(target);
});
@@ -518,7 +521,9 @@ namespace osu.Game.Tests.Visual.SongSelect
public void TestExternalBeatmapChangeWhileFilteredThenRefilter()
{
createSongSelect();
- addManyTestMaps();
+ // ensure there is at least 1 difficulty for each of the rulesets
+ // (catch is excluded inside of addManyTestMaps).
+ addManyTestMaps(3);
changeRuleset(0);
@@ -534,8 +539,10 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("select beatmap externally", () =>
{
- target = manager.GetAllUsableBeatmapSets().Where(b => b.Beatmaps.Any(bi => bi.RulesetID == 1))
- .ElementAt(5).Beatmaps.First();
+ target = manager
+ .GetAllUsableBeatmapSets()
+ .First(b => b.Beatmaps.Any(bi => bi.RulesetID == 1))
+ .Beatmaps.First();
Beatmap.Value = manager.GetWorkingBeatmap(target);
});
@@ -877,14 +884,21 @@ namespace osu.Game.Tests.Visual.SongSelect
AddUntilStep("wait for carousel loaded", () => songSelect.Carousel.IsAlive);
}
- private void addManyTestMaps()
+ ///
+ /// Imports test beatmap sets to show in the carousel.
+ ///
+ ///
+ /// The exact count of difficulties to create for each beatmap set.
+ /// A value causes the count of difficulties to be selected randomly.
+ ///
+ private void addManyTestMaps(int? difficultyCountPerSet = null)
{
AddStep("import test maps", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
- for (int i = 0; i < 100; i += 10)
- manager.Import(TestResources.CreateTestBeatmapSetInfo(rulesets: usableRulesets)).Wait();
+ for (int i = 0; i < 10; i++)
+ manager.Import(TestResources.CreateTestBeatmapSetInfo(difficultyCountPerSet, usableRulesets)).Wait();
});
}
diff --git a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
similarity index 91%
rename from osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
rename to osu.Game.Tests/Visual/TestMultiplayerComponents.cs
index 370f3bd0ae..cd7a936778 100644
--- a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
+++ b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
@@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual
///
///
///
- public class TestMultiplayerScreenStack : OsuScreen
+ public class TestMultiplayerComponents : OsuScreen
{
public Screens.OnlinePlay.Multiplayer.Multiplayer MultiplayerScreen => multiplayerScreen;
@@ -42,14 +42,18 @@ namespace osu.Game.Tests.Visual
private readonly OsuScreenStack screenStack;
private readonly TestMultiplayer multiplayerScreen;
- public TestMultiplayerScreenStack()
+ public TestMultiplayerComponents()
{
multiplayerScreen = new TestMultiplayer();
InternalChildren = new Drawable[]
{
Client = new TestMultiplayerClient(RoomManager),
- screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }
+ screenStack = new OsuScreenStack
+ {
+ Name = nameof(TestMultiplayerComponents),
+ RelativeSizeAxes = Axes.Both
+ }
};
screenStack.Push(multiplayerScreen);
diff --git a/osu.Game/Database/RealmLiveUnmanaged.cs b/osu.Game/Database/RealmLiveUnmanaged.cs
index 5a69898206..ea50ccc1ff 100644
--- a/osu.Game/Database/RealmLiveUnmanaged.cs
+++ b/osu.Game/Database/RealmLiveUnmanaged.cs
@@ -26,6 +26,8 @@ namespace osu.Game.Database
public bool Equals(ILive? other) => ID == other?.ID;
+ public override string ToString() => Value.ToString();
+
public Guid ID => Value.ID;
public void PerformRead(Action perform) => perform(Value);
diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
index d6e515d8a1..d195babcbf 100644
--- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
+++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
@@ -42,7 +42,9 @@ namespace osu.Game.Overlays.Profile.Header.Components
private void updateStatistics(UserStatistics statistics)
{
- int[] userRanks = statistics?.RankHistory?.Data;
+ // checking both IsRanked and RankHistory is required.
+ // see https://github.com/ppy/osu-web/blob/154ceafba0f35a1dd935df53ec98ae2ea5615f9f/resources/assets/lib/profile-page/rank-chart.tsx#L46
+ int[] userRanks = statistics?.IsRanked == true ? statistics.RankHistory?.Data : null;
Data = userRanks?.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray();
}
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs
index c3190cd845..48f153ecbe 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs
@@ -87,7 +87,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
gameplayContent.Child = new PlayerIsolationContainer(beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.BeatmapInfo), Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods)
{
RelativeSizeAxes = Axes.Both,
- Child = stack = new OsuScreenStack()
+ Child = stack = new OsuScreenStack
+ {
+ Name = nameof(PlayerArea),
+ }
};
stack.Push(new MultiSpectatorPlayerLoader(Score, () => new MultiSpectatorPlayer(Score, GameplayClock)));
diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
index 5656704abf..7607122ef0 100644
--- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
@@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies;
- public bool RoomJoined => RoomManager.RoomJoined;
+ public bool RoomJoined => Client.RoomJoined;
private readonly bool joinRoom;
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
index 4e0cfe405e..5b08b6b835 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
@@ -31,9 +31,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
private readonly Bindable isConnected = new Bindable(true);
public new Room? APIRoom => base.APIRoom;
-
public Action? RoomSetupAction;
+ public bool RoomJoined { get; private set; }
+
[Resolved]
private IAPIProvider api { get; set; } = null!;
@@ -49,7 +50,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
private MultiplayerPlaylistItem? currentItem => Room?.Playlist[currentIndex];
private int currentIndex;
-
private long lastPlaylistItemId;
public TestMultiplayerClient(TestMultiplayerRoomManager roomManager)
@@ -217,9 +217,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
// emulate the server sending this after the join room. scheduler required to make sure the join room event is fired first (in Join).
changeMatchType(Room.Settings.MatchType).Wait();
+
+ RoomJoined = true;
}
- protected override Task LeaveRoomInternal() => Task.CompletedTask;
+ protected override Task LeaveRoomInternal()
+ {
+ RoomJoined = false;
+ return Task.CompletedTask;
+ }
public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId);
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs
index a1f010f082..296db3152d 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs
@@ -17,8 +17,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
///
public class TestMultiplayerRoomManager : MultiplayerRoomManager
{
- public bool RoomJoined { get; private set; }
-
private readonly TestRoomRequestsHandler requestsHandler;
public TestMultiplayerRoomManager(TestRoomRequestsHandler requestsHandler)
@@ -29,28 +27,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
public IReadOnlyList ServerSideRooms => requestsHandler.ServerSideRooms;
public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null)
- {
- base.CreateRoom(room, r =>
- {
- onSuccess?.Invoke(r);
- RoomJoined = true;
- }, onError);
- }
+ => base.CreateRoom(room, r => onSuccess?.Invoke(r), onError);
public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null)
- {
- base.JoinRoom(room, password, r =>
- {
- onSuccess?.Invoke(r);
- RoomJoined = true;
- }, onError);
- }
-
- public override void PartRoom()
- {
- base.PartRoom();
- RoomJoined = false;
- }
+ => base.JoinRoom(room, password, r => onSuccess?.Invoke(r), onError);
///
/// Adds a room to a local "server-side" list that's returned when a is fired.
diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs
index aa46b516bf..c44a848275 100644
--- a/osu.Game/Tests/Visual/ScreenTestScene.cs
+++ b/osu.Game/Tests/Visual/ScreenTestScene.cs
@@ -29,7 +29,11 @@ namespace osu.Game.Tests.Visual
{
base.Content.AddRange(new Drawable[]
{
- Stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both },
+ Stack = new OsuScreenStack
+ {
+ Name = nameof(ScreenTestScene),
+ RelativeSizeAxes = Axes.Both
+ },
content = new Container { RelativeSizeAxes = Axes.Both },
DialogOverlay = new DialogOverlay()
});
diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs
index c690447256..f8d26fe421 100644
--- a/osu.Game/Users/UserStatistics.cs
+++ b/osu.Game/Users/UserStatistics.cs
@@ -27,6 +27,9 @@ namespace osu.Game.Users
public int Progress;
}
+ [JsonProperty(@"is_ranked")]
+ public bool IsRanked;
+
[JsonProperty(@"global_rank")]
public int? GlobalRank;
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 0e8486cabc..6e6002bc8e 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 42d8962c14..de359245d1 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -60,7 +60,7 @@
-
+
@@ -83,7 +83,7 @@
-
+