mirror of https://github.com/ppy/osu
Fix spectator client not handling multiple watch calls properly
This commit is contained in:
parent
51e607e834
commit
7e5086c8d7
|
@ -65,11 +65,12 @@ public abstract class SpectatorClient : Component, ISpectatorClient
|
|||
public virtual event Action<int, SpectatorState>? OnUserFinishedPlaying;
|
||||
|
||||
/// <summary>
|
||||
/// All users currently being watched.
|
||||
/// A dictionary containing all users currently being watched, with the number of watching components for each user.
|
||||
/// </summary>
|
||||
private readonly List<int> watchedUsers = new List<int>();
|
||||
private readonly Dictionary<int, int> watchedUsers = new Dictionary<int, int>();
|
||||
|
||||
private readonly BindableDictionary<int, SpectatorState> watchedUserStates = new BindableDictionary<int, SpectatorState>();
|
||||
|
||||
private readonly BindableList<int> playingUsers = new BindableList<int>();
|
||||
private readonly SpectatorState currentState = new SpectatorState();
|
||||
|
||||
|
@ -94,12 +95,15 @@ private void load()
|
|||
if (connected.NewValue)
|
||||
{
|
||||
// get all the users that were previously being watched
|
||||
int[] users = watchedUsers.ToArray();
|
||||
var users = new Dictionary<int, int>(watchedUsers);
|
||||
watchedUsers.Clear();
|
||||
|
||||
// resubscribe to watched users.
|
||||
foreach (int userId in users)
|
||||
WatchUser(userId);
|
||||
foreach ((int user, int watchers) in users)
|
||||
{
|
||||
for (int i = 0; i < watchers; i++)
|
||||
WatchUser(user);
|
||||
}
|
||||
|
||||
// re-send state in case it wasn't received
|
||||
if (IsPlaying)
|
||||
|
@ -121,7 +125,7 @@ Task ISpectatorClient.UserBeganPlaying(int userId, SpectatorState state)
|
|||
if (!playingUsers.Contains(userId))
|
||||
playingUsers.Add(userId);
|
||||
|
||||
if (watchedUsers.Contains(userId))
|
||||
if (watchedUsers.ContainsKey(userId))
|
||||
watchedUserStates[userId] = state;
|
||||
|
||||
OnUserBeganPlaying?.Invoke(userId, state);
|
||||
|
@ -136,7 +140,7 @@ Task ISpectatorClient.UserFinishedPlaying(int userId, SpectatorState state)
|
|||
{
|
||||
playingUsers.Remove(userId);
|
||||
|
||||
if (watchedUsers.Contains(userId))
|
||||
if (watchedUsers.ContainsKey(userId))
|
||||
watchedUserStates[userId] = state;
|
||||
|
||||
OnUserFinishedPlaying?.Invoke(userId, state);
|
||||
|
@ -232,11 +236,13 @@ public virtual void WatchUser(int userId)
|
|||
{
|
||||
Debug.Assert(ThreadSafety.IsUpdateThread);
|
||||
|
||||
if (watchedUsers.Contains(userId))
|
||||
if (watchedUsers.ContainsKey(userId))
|
||||
{
|
||||
watchedUsers[userId]++;
|
||||
return;
|
||||
}
|
||||
|
||||
watchedUsers.Add(userId);
|
||||
|
||||
watchedUsers.Add(userId, 1);
|
||||
WatchUserInternal(userId);
|
||||
}
|
||||
|
||||
|
@ -246,6 +252,12 @@ public void StopWatchingUser(int userId)
|
|||
// Todo: This should not be a thing, but requires framework changes.
|
||||
Schedule(() =>
|
||||
{
|
||||
if (watchedUsers.TryGetValue(userId, out int watchers) && watchers > 1)
|
||||
{
|
||||
watchedUsers[userId]--;
|
||||
return;
|
||||
}
|
||||
|
||||
watchedUsers.Remove(userId);
|
||||
watchedUserStates.Remove(userId);
|
||||
StopWatchingUserInternal(userId);
|
||||
|
|
Loading…
Reference in New Issue