From 5652490d61c4ee2c5b046e8baf7e5524303a1a31 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 16 Apr 2021 14:11:55 +0900 Subject: [PATCH] Fix OnUserBeganPlaying not being invoked if already watching --- .../Visual/Gameplay/TestSceneSpectator.cs | 24 ++++++++++++++++ .../Spectator/SpectatorStreamingClient.cs | 28 +++++++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs index 397b37718d..ea66144b21 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSpectator.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; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -204,6 +205,29 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("screen didn't change", () => Stack.CurrentScreen is SoloSpectator); } + [Test] + public void OnUserBeganPlayingCallbackInvokedOnNewAdd() + { + bool callbackInvoked = false; + Action callbackAction = (_, __) => callbackInvoked = true; + + AddStep("bind first event", () => testSpectatorStreamingClient.OnUserBeganPlaying += callbackAction); + start(); + AddAssert("callback invoked", () => callbackInvoked); + + AddStep("reset", () => + { + testSpectatorStreamingClient.OnUserBeganPlaying -= callbackAction; + callbackInvoked = false; + }); + + AddStep("bind event again", () => testSpectatorStreamingClient.OnUserBeganPlaying += callbackAction); + AddAssert("callback invoked", () => callbackInvoked); + + // Don't leave the event bound if test run succeeded. + AddStep("reset", () => testSpectatorStreamingClient.OnUserBeganPlaying -= callbackAction); + } + private OsuFramedReplayInputHandler replayHandler => (OsuFramedReplayInputHandler)Stack.ChildrenOfType().First().ReplayInputHandler; diff --git a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs index 3a586874fe..7bea49e102 100644 --- a/osu.Game/Online/Spectator/SpectatorStreamingClient.cs +++ b/osu.Game/Online/Spectator/SpectatorStreamingClient.cs @@ -60,6 +60,7 @@ namespace osu.Game.Online.Spectator private IBindable> currentMods { get; set; } private readonly SpectatorState currentState = new SpectatorState(); + private readonly Dictionary currentUserStates = new Dictionary(); private bool isPlaying; @@ -68,10 +69,25 @@ namespace osu.Game.Online.Spectator /// public event Action OnNewFrames; + private event Action onUserBeganPlaying; + /// - /// Called whenever a user starts a play session. + /// Called whenever a user starts a play session, or immediately if the user is being watched and currently in a play session. /// - public event Action OnUserBeganPlaying; + public event Action OnUserBeganPlaying + { + add + { + onUserBeganPlaying += value; + + lock (userLock) + { + foreach (var (userId, state) in currentUserStates) + value?.Invoke(userId, state); + } + } + remove => onUserBeganPlaying -= value; + } /// /// Called whenever a user finishes a play session. @@ -134,7 +150,10 @@ namespace osu.Game.Online.Spectator if (!playingUsers.Contains(userId)) playingUsers.Add(userId); - OnUserBeganPlaying?.Invoke(userId, state); + lock (userLock) + currentUserStates[userId] = state; + + onUserBeganPlaying?.Invoke(userId, state); return Task.CompletedTask; } @@ -143,6 +162,9 @@ namespace osu.Game.Online.Spectator { playingUsers.Remove(userId); + lock (userLock) + currentUserStates.Remove(userId); + OnUserFinishedPlaying?.Invoke(userId, state); return Task.CompletedTask;