diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs index 4646f42d63..bbdd7a3d56 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/MultiSpectatorScreen.cs @@ -215,8 +215,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate protected override void StartGameplay(int userId, SpectatorGameplayState spectatorGameplayState) => instances.Single(i => i.UserId == userId).LoadScore(spectatorGameplayState.Score); - protected override void EndGameplay(int userId) + protected override void EndGameplay(int userId, SpectatorState state) { + if (state.State == SpectatingUserState.Completed || state.State == SpectatingUserState.Failed) + return; + RemoveUser(userId); var instance = instances.Single(i => i.UserId == userId); diff --git a/osu.Game/Screens/Play/SoloSpectator.cs b/osu.Game/Screens/Play/SoloSpectator.cs index b530965269..a710db6d24 100644 --- a/osu.Game/Screens/Play/SoloSpectator.cs +++ b/osu.Game/Screens/Play/SoloSpectator.cs @@ -180,7 +180,7 @@ namespace osu.Game.Screens.Play scheduleStart(spectatorGameplayState); } - protected override void EndGameplay(int userId) + protected override void EndGameplay(int userId, SpectatorState state) { scheduledStart?.Cancel(); immediateSpectatorGameplayState = null; diff --git a/osu.Game/Screens/Spectate/SpectatorScreen.cs b/osu.Game/Screens/Spectate/SpectatorScreen.cs index 460352ee07..7b58f669a0 100644 --- a/osu.Game/Screens/Spectate/SpectatorScreen.cs +++ b/osu.Game/Screens/Spectate/SpectatorScreen.cs @@ -118,8 +118,8 @@ namespace osu.Game.Screens.Spectate break; case NotifyDictionaryChangedAction.Remove: - foreach ((int userId, _) in e.OldItems.AsNonNull()) - onUserStateRemoved(userId); + foreach ((int userId, SpectatorState state) in e.OldItems.AsNonNull()) + onUserStateRemoved(userId, state); break; } } @@ -147,7 +147,7 @@ namespace osu.Game.Screens.Spectate } } - private void onUserStateRemoved(int userId) + private void onUserStateRemoved(int userId, SpectatorState state) { if (!userMap.ContainsKey(userId)) return; @@ -158,7 +158,7 @@ namespace osu.Game.Screens.Spectate gameplayState.Score.Replay.HasReceivedAllFrames = true; gameplayStates.Remove(userId); - Schedule(() => EndGameplay(userId)); + Schedule(() => EndGameplay(userId, state)); } private void updateGameplayState(int userId) @@ -212,7 +212,8 @@ namespace osu.Game.Screens.Spectate /// Ends gameplay for a user. /// /// The user to end gameplay for. - protected abstract void EndGameplay(int userId); + /// The final user state. + protected abstract void EndGameplay(int userId, SpectatorState state); /// /// Stops spectating a user. @@ -220,7 +221,10 @@ namespace osu.Game.Screens.Spectate /// The user to stop spectating. protected void RemoveUser(int userId) { - onUserStateRemoved(userId); + if (!userStates.TryGetValue(userId, out var state)) + return; + + onUserStateRemoved(userId, state); users.Remove(userId); userMap.Remove(userId);