From 81a22dbd29543b3ff5387669bd6ce1fc048a4811 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 2 Feb 2022 23:19:43 +0900 Subject: [PATCH] Add back playing users list --- osu.Game/Online/Spectator/SpectatorClient.cs | 28 +++++++++-- .../Dashboard/CurrentlyPlayingDisplay.cs | 48 ++++++++----------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 3646c51d94..9e168411b0 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -35,16 +35,28 @@ namespace osu.Game.Online.Spectator /// public abstract IBindable IsConnected { get; } + /// + /// The states of all users currently being watched. + /// + public IBindableDictionary WatchingUserStates => watchingUserStates; + + /// + /// A global list of all players currently playing. + /// + public IBindableList PlayingUsers => playingUsers; + + /// + /// All users currently being watched. + /// private readonly List watchingUsers = new List(); - public IBindableDictionary WatchingUserStates => watchingUserStates; private readonly BindableDictionary watchingUserStates = new BindableDictionary(); + private readonly BindableList playingUsers = new BindableList(); + private readonly SpectatorState currentState = new SpectatorState(); private IBeatmap? currentBeatmap; private Score? currentScore; - private readonly SpectatorState currentState = new SpectatorState(); - /// /// Whether the local user is playing. /// @@ -85,7 +97,10 @@ namespace osu.Game.Online.Spectator BeginPlayingInternal(currentState); } else + { watchingUserStates.Clear(); + playingUsers.Clear(); + } }), true); } @@ -93,8 +108,12 @@ namespace osu.Game.Online.Spectator { Schedule(() => { + if (!playingUsers.Contains(userId)) + playingUsers.Add(userId); + if (watchingUsers.Contains(userId)) watchingUserStates[userId] = state; + OnUserBeganPlaying?.Invoke(userId, state); }); @@ -105,8 +124,11 @@ namespace osu.Game.Online.Spectator { Schedule(() => { + playingUsers.Remove(userId); + if (watchingUsers.Contains(userId)) watchingUserStates[userId] = state; + OnUserFinishedPlaying?.Invoke(userId, state); }); diff --git a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs index 975402a443..02ef28f825 100644 --- a/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs +++ b/osu.Game/Overlays/Dashboard/CurrentlyPlayingDisplay.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Specialized; using System.Diagnostics; using System.Linq; using osu.Framework.Allocation; @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Dashboard { internal class CurrentlyPlayingDisplay : CompositeDrawable { - private readonly IBindableDictionary userStates = new BindableDictionary(); + private readonly IBindableList playingUsers = new BindableList(); private FillFlowContainer userFlow; @@ -51,55 +52,46 @@ namespace osu.Game.Overlays.Dashboard { base.LoadComplete(); - userStates.BindTo(spectatorClient.WatchingUserStates); - userStates.BindCollectionChanged(onUserStatesChanged, true); + playingUsers.BindTo(spectatorClient.PlayingUsers); + playingUsers.BindCollectionChanged(onPlayingUsersChanged, true); } - private void onUserStatesChanged(object sender, NotifyDictionaryChangedEventArgs e) => Schedule(() => + private void onPlayingUsersChanged(object sender, NotifyCollectionChangedEventArgs e) => Schedule(() => { switch (e.Action) { - case NotifyDictionaryChangedAction.Add: - case NotifyDictionaryChangedAction.Replace: + case NotifyCollectionChangedAction.Add: Debug.Assert(e.NewItems != null); - foreach ((int userId, SpectatorState state) in e.NewItems) + foreach (int userId in e.NewItems) { - if (state.State != SpectatingUserState.Playing) - { - removePlayingUser(userId); - continue; - } - users.GetUserAsync(userId).ContinueWith(task => { var user = task.GetResultSafely(); if (user != null) - Schedule(() => addPlayingUser(user)); + { + Schedule(() => + { + // user may no longer be playing. + if (!playingUsers.Contains(user.Id)) + return; + + userFlow.Add(createUserPanel(user)); + }); + } }); } break; - case NotifyDictionaryChangedAction.Remove: + case NotifyCollectionChangedAction.Remove: Debug.Assert(e.OldItems != null); - foreach ((int userId, _) in e.OldItems) - removePlayingUser(userId); + foreach (int userId in e.OldItems) + userFlow.FirstOrDefault(card => card.User.Id == userId)?.Expire(); break; } - - void addPlayingUser(APIUser user) - { - // user may no longer be playing. - if (!userStates.TryGetValue(user.Id, out var state2) || state2.State != SpectatingUserState.Playing) - return; - - userFlow.Add(createUserPanel(user)); - } - - void removePlayingUser(int userId) => userFlow.FirstOrDefault(card => card.User.Id == userId)?.Expire(); }); private PlayingUserPanel createUserPanel(APIUser user) =>