From dea7f2308c00f673ce16d42a51d346d2d5dead5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 7 Dec 2021 17:24:03 +0900 Subject: [PATCH] Fix participant panels potentially keeping a reference to an old user If a user leave and then rejoins a multiplayer match while another user is not at the lobby screen, there is a potential the `ParticipantPanel` tracking the user will not correctly be recreated to reference the new instance of the `MultiplayerUser`. This happens because the `OnRoomUpdated` call is scheduled, which means it is not running in the background, coupled with the local logic that relies on `IEquatable(MultiplayerRoomUser)` (which in turn falls back to a UserID comparison). Changing this to a reference comparison is the easiest way to resolve this. Whether we change the `IEquatable` implementation is up for discussion. Closes https://github.com/ppy/osu/issues/15970. --- .../Multiplayer/Participants/ParticipantsList.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs index 2ad64e115e..d36c556fac 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Participants/ParticipantsList.cs @@ -77,7 +77,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants else { // Remove panels for users no longer in the room. - panels.RemoveAll(p => !Room.Users.Contains(p.User)); + foreach (var p in panels) + { + // Note that we *must* use reference equality here, as this call is scheduled and a user may have left and joined since it was last run. + if (Room.Users.All(u => !ReferenceEquals(p.User, u))) + p.Expire(); + } // Add panels for all users new to the room. foreach (var user in Room.Users.Except(panels.Select(p => p.User)))