diff --git a/osu.Game/Online/Spectator/ISpectatorClient.cs b/osu.Game/Online/Spectator/ISpectatorClient.cs
index ccba280001..605ebc4ef0 100644
--- a/osu.Game/Online/Spectator/ISpectatorClient.cs
+++ b/osu.Game/Online/Spectator/ISpectatorClient.cs
@@ -32,5 +32,12 @@ namespace osu.Game.Online.Spectator
/// The user.
/// The frame data.
Task UserSentFrames(int userId, FrameDataBundle data);
+
+ ///
+ /// Signals that a user's submitted score was fully processed.
+ ///
+ /// The ID of the user who achieved the score.
+ /// The ID of the score.
+ Task UserScoreProcessed(int userId, long scoreId);
}
}
diff --git a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs
index 01b775549e..3118e05053 100644
--- a/osu.Game/Online/Spectator/OnlineSpectatorClient.cs
+++ b/osu.Game/Online/Spectator/OnlineSpectatorClient.cs
@@ -41,6 +41,7 @@ namespace osu.Game.Online.Spectator
connection.On(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying);
connection.On(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames);
connection.On(nameof(ISpectatorClient.UserFinishedPlaying), ((ISpectatorClient)this).UserFinishedPlaying);
+ connection.On(nameof(ISpectatorClient.UserScoreProcessed), ((ISpectatorClient)this).UserScoreProcessed);
};
IsConnected.BindTo(connector.IsConnected);
diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs
index fce61c019b..b60cef2835 100644
--- a/osu.Game/Online/Spectator/SpectatorClient.cs
+++ b/osu.Game/Online/Spectator/SpectatorClient.cs
@@ -64,6 +64,11 @@ namespace osu.Game.Online.Spectator
///
public virtual event Action? OnUserFinishedPlaying;
+ ///
+ /// Called whenever a user-submitted score has been fully processed.
+ ///
+ public virtual event Action? OnUserScoreProcessed;
+
///
/// A dictionary containing all users currently being watched, with the number of watching components for each user.
///
@@ -160,6 +165,13 @@ namespace osu.Game.Online.Spectator
return Task.CompletedTask;
}
+ Task ISpectatorClient.UserScoreProcessed(int userId, long scoreId)
+ {
+ Schedule(() => OnUserScoreProcessed?.Invoke(userId, scoreId));
+
+ return Task.CompletedTask;
+ }
+
public void BeginPlaying(long? scoreToken, GameplayState state, Score score)
{
// This schedule is only here to match the one below in `EndPlaying`.