From d9a4f018e65ce669a1fd329a3aa6880b5c94bdbd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 18:26:36 +0900 Subject: [PATCH 1/5] Add event flow for receiving kick commands --- osu.Game/Online/Multiplayer/IMultiplayerClient.cs | 9 +++++++++ osu.Game/Online/Multiplayer/MultiplayerClient.cs | 6 ++++++ osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs | 1 + 3 files changed, 16 insertions(+) diff --git a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs index 064065ab00..8f16d22c4c 100644 --- a/osu.Game/Online/Multiplayer/IMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/IMultiplayerClient.cs @@ -31,6 +31,15 @@ namespace osu.Game.Online.Multiplayer /// The user. Task UserLeft(MultiplayerRoomUser user); + /// + /// Signals that a user has been kicked from the room. + /// + /// + /// This will also be sent to the user that was kicked. + /// + /// The user. + Task UserKicked(MultiplayerRoomUser user); + /// /// Signal that the host of the room has changed. /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 4607211cdf..7e964ed5fa 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -389,6 +389,12 @@ namespace osu.Game.Online.Multiplayer return Task.CompletedTask; } + Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) + { + // TODO: also inform users of the kick operation. + return ((IMultiplayerClient)this).UserLeft(user); + } + Task IMultiplayerClient.HostChanged(int userId) { if (Room == null) diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 55477a9fc7..c38a648a6a 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -50,6 +50,7 @@ namespace osu.Game.Online.Multiplayer connection.On(nameof(IMultiplayerClient.RoomStateChanged), ((IMultiplayerClient)this).RoomStateChanged); connection.On(nameof(IMultiplayerClient.UserJoined), ((IMultiplayerClient)this).UserJoined); connection.On(nameof(IMultiplayerClient.UserLeft), ((IMultiplayerClient)this).UserLeft); + connection.On(nameof(IMultiplayerClient.UserKicked), ((IMultiplayerClient)this).UserKicked); connection.On(nameof(IMultiplayerClient.HostChanged), ((IMultiplayerClient)this).HostChanged); connection.On(nameof(IMultiplayerClient.SettingsChanged), ((IMultiplayerClient)this).SettingsChanged); connection.On(nameof(IMultiplayerClient.UserStateChanged), ((IMultiplayerClient)this).UserStateChanged); From 9b21ebd6d04410d2e5fcd363cf26b4ee88a0bfec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 18:31:04 +0900 Subject: [PATCH 2/5] Add client side handling on incoming kick --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 7e964ed5fa..57dbfbb507 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -190,7 +190,8 @@ namespace osu.Game.Online.Multiplayer return joinOrLeaveTaskChain.Add(async () => { await scheduledReset.ConfigureAwait(false); - await LeaveRoomInternal().ConfigureAwait(false); + if (Room != null) + await LeaveRoomInternal().ConfigureAwait(false); }); } @@ -391,6 +392,12 @@ namespace osu.Game.Online.Multiplayer Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) { + if (LocalUser == null) + return Task.CompletedTask; + + if (user.Equals(LocalUser)) + LeaveRoom(); + // TODO: also inform users of the kick operation. return ((IMultiplayerClient)this).UserLeft(user); } From 31608a1bc6c4a691571967dd1e893a7ac4338ee9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Aug 2021 19:56:25 +0900 Subject: [PATCH 3/5] Leave the match screen when kicked --- .../OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 561fa220c8..57dde31b68 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -448,6 +448,13 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer private void onRoomUpdated() { + // may happen if the client is kicked or otherwise removed from the room. + if (client.Room == null) + { + Schedule(this.Exit); + return; + } + Scheduler.AddOnce(UpdateMods); } From b9721f5261c52a42e6eabec465a55e6b6d024431 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Aug 2021 14:37:43 +0900 Subject: [PATCH 4/5] Centralise screen exit logic and guard against non-current screen --- .../Multiplayer/MultiplayerMatchSubScreen.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index 36b86737bc..265b68afea 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -274,7 +274,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer isConnected.BindValueChanged(connected => { if (!connected.NewValue) - Schedule(this.Exit); + handleRoomLost(); }, true); currentRoom.BindValueChanged(room => @@ -284,7 +284,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // the room has gone away. // this could mean something happened during the join process, or an external connection issue occurred. // one specific scenario is where the underlying room is created, but the signalr server returns an error during the join process. this triggers a PartRoom operation (see https://github.com/ppy/osu/blob/7654df94f6f37b8382be7dfcb4f674e03bd35427/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs#L97) - Schedule(this.Exit); + handleRoomLost(); } }, true); } @@ -451,13 +451,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // may happen if the client is kicked or otherwise removed from the room. if (client.Room == null) { - Schedule(this.Exit); + handleRoomLost(); return; } Scheduler.AddOnce(UpdateMods); } + private void handleRoomLost() => Schedule(() => + { + if (this.IsCurrentScreen()) + this.Exit(); + else + ValidForResume = false; + }); + private void onLoadRequested() { if (BeatmapAvailability.Value.State != DownloadState.LocallyAvailable) From e6b3aba6e19557e2f2d493fb6d5c57a9c71d3b23 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Aug 2021 14:08:29 +0900 Subject: [PATCH 5/5] Fix incorrectly directed call in `TestMultiplayerClient` --- osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index a28b4140ca..67b79d7390 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -178,7 +178,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { Debug.Assert(Room != null); - return ((IMultiplayerClient)this).UserLeft(Room.Users.Single(u => u.UserID == userId)); + return ((IMultiplayerClient)this).UserKicked(Room.Users.Single(u => u.UserID == userId)); } public override async Task ChangeSettings(MultiplayerRoomSettings settings)