From 18d7b7920798bec5097f30b1ff85f413a4adf098 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 15 Dec 2021 17:37:39 +0900 Subject: [PATCH] Don't reset spectating state if gameplay is finished --- .../Multiplayer/TestSceneMultiplayer.cs | 91 ++++++++++++++++++- .../Visual/TestMultiplayerScreenStack.cs | 2 +- .../Spectate/MultiSpectatorScreen.cs | 9 +- 3 files changed, 96 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs index bc2902480d..a2de391aec 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs @@ -30,6 +30,7 @@ using osu.Game.Screens.OnlinePlay.Lounge.Components; using osu.Game.Screens.OnlinePlay.Match; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; +using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate; using osu.Game.Screens.Play; using osu.Game.Screens.Ranking; using osu.Game.Screens.Spectate; @@ -656,23 +657,107 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } + [Test] + public void TestSpectatingStateResetOnBackButtonDuringGameplay() + { + createRoom(() => new Room + { + Name = { Value = "Test Room" }, + QueueMode = { Value = QueueMode.AllPlayers }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + } + } + }); + + AddStep("set spectating state", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); + AddUntilStep("state set to spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + + AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 })); + AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready)); + + pressReadyButton(1234); + AddUntilStep("wait for gameplay", () => (multiplayerScreenStack.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true); + + AddStep("press back button and exit", () => + { + multiplayerScreenStack.OnBackButton(); + multiplayerScreenStack.Exit(); + }); + + AddUntilStep("wait for return to match subscreen", () => multiplayerScreenStack.MultiplayerScreen.IsCurrentScreen()); + AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle); + } + + [Test] + public void TestSpectatingStateNotResetOnBackButtonOutsideOfGameplay() + { + createRoom(() => new Room + { + Name = { Value = "Test Room" }, + QueueMode = { Value = QueueMode.AllPlayers }, + Playlist = + { + new PlaylistItem + { + Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + } + } + }); + + AddStep("set spectating state", () => client.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); + AddUntilStep("state set to spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + + AddStep("join other user", () => client.AddUser(new APIUser { Id = 1234 })); + AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready)); + + pressReadyButton(1234); + AddUntilStep("wait for gameplay", () => (multiplayerScreenStack.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(); + }); + + AddUntilStep("wait for return to match subscreen", () => multiplayerScreenStack.MultiplayerScreen.IsCurrentScreen()); + AddWaitStep("wait for possible state change", 5); + AddUntilStep("user state is spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating); + } + + private void enterGameplay() + { + pressReadyButton(); + pressReadyButton(); + AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player); + } + private ReadyButton readyButton => this.ChildrenOfType().Single(); - private void pressReadyButton() + private void pressReadyButton(int? playingUserId = null) { AddUntilStep("wait for ready button to be enabled", () => readyButton.Enabled.Value); MultiplayerUserState lastState = MultiplayerUserState.Idle; + MultiplayerRoomUser user = null; AddStep("click ready button", () => { - lastState = client.LocalUser?.State ?? MultiplayerUserState.Idle; + user = playingUserId == null ? client.LocalUser : client.Room?.Users.Single(u => u.UserID == playingUserId); + lastState = user?.State ?? MultiplayerUserState.Idle; InputManager.MoveMouseTo(readyButton); InputManager.Click(MouseButton.Left); }); - AddUntilStep("wait for state change", () => client.LocalUser?.State != lastState); + AddUntilStep("wait for state change", () => user?.State != lastState); } private void createRoom(Func room) diff --git a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs index 7f1171db1f..370f3bd0ae 100644 --- a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs +++ b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs @@ -61,7 +61,7 @@ namespace osu.Game.Tests.Visual ((DummyAPIAccess)api).HandleRequest = request => multiplayerScreen.RequestsHandler.HandleRequest(request, api.LocalUser.Value, game); } - public override bool OnBackButton() => multiplayerScreen.OnBackButton(); + public override bool OnBackButton() => (screenStack.CurrentScreen as OsuScreen)?.OnBackButton() ?? base.OnBackButton(); public override bool OnExiting(IScreen next) { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 9ac64add9a..7350408eba 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -226,8 +227,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate public override bool OnBackButton() { - // On a manual exit, set the player state back to idle. - multiplayerClient.ChangeState(MultiplayerUserState.Idle); + Debug.Assert(multiplayerClient.Room != null); + + // On a manual exit, set the player back to idle unless gameplay has finished. + if (multiplayerClient.Room.State != MultiplayerRoomState.Open) + multiplayerClient.ChangeState(MultiplayerUserState.Idle); + return base.OnBackButton(); } }