diff --git a/osu.Server.Spectator/Hubs/Spectator/SpectatorClientState.cs b/osu.Server.Spectator/Hubs/Spectator/SpectatorClientState.cs index ce6f200a..2e6b4ea0 100644 --- a/osu.Server.Spectator/Hubs/Spectator/SpectatorClientState.cs +++ b/osu.Server.Spectator/Hubs/Spectator/SpectatorClientState.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using Newtonsoft.Json; using osu.Game.Online.Spectator; using osu.Game.Scoring; @@ -26,6 +27,11 @@ public class SpectatorClientState : ClientState /// public long? ScoreToken; + /// + /// The list of IDs of users that this client is currently watching. + /// + public HashSet WatchedUsers = new HashSet(); + [JsonConstructor] public SpectatorClientState(in string connectionId, in int userId) : base(connectionId, userId) diff --git a/osu.Server.Spectator/Hubs/Spectator/SpectatorHub.cs b/osu.Server.Spectator/Hubs/Spectator/SpectatorHub.cs index c913e164..892c5e81 100644 --- a/osu.Server.Spectator/Hubs/Spectator/SpectatorHub.cs +++ b/osu.Server.Spectator/Hubs/Spectator/SpectatorHub.cs @@ -154,7 +154,12 @@ public async Task EndPlaySession(SpectatorState state) } finally { - usage.Destroy(); + if (usage.Item != null) + { + usage.Item.State = null; + usage.Item.Score = null; + usage.Item.ScoreToken = null; + } } } @@ -202,6 +207,12 @@ public async Task StartWatchingUser(int userId) // user isn't tracked. } + using (var state = await GetOrCreateLocalUserState()) + { + var clientState = state.Item ??= new SpectatorClientState(Context.ConnectionId, Context.GetUserId()); + clientState.WatchedUsers.Add(userId); + } + await Groups.AddToGroupAsync(Context.ConnectionId, GetGroupId(userId)); int watcherId = Context.GetUserId(); @@ -225,6 +236,12 @@ public async Task EndWatchingUser(int userId) { await Groups.RemoveFromGroupAsync(Context.ConnectionId, GetGroupId(userId)); + using (var state = await GetOrCreateLocalUserState()) + { + var clientState = state.Item ??= new SpectatorClientState(Context.ConnectionId, Context.GetUserId()); + clientState.WatchedUsers.Remove(userId); + } + int watcherId = Context.GetUserId(); await Clients.User(userId.ToString()).UserEndedWatching(watcherId); @@ -245,6 +262,9 @@ protected override async Task CleanUpState(SpectatorClientState state) if (state.State != null) await endPlaySession(state.UserId, state.State); + foreach (int watchedUserId in state.WatchedUsers) + await Clients.User(watchedUserId.ToString()).UserEndedWatching(state.UserId); + await base.CleanUpState(state); }