From e62a01cf773efc42be52cc0f5ca25ec4ceefe1e4 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 19 Jan 2026 18:34:00 +0900 Subject: [PATCH] Add metadata endpoint to refresh friend listing (#36386) Alternative to / closes https://github.com/ppy/osu/pull/36341 See also: https://github.com/ppy/osu-server-spectator/pull/415 This is a simple solution by adding a spectator endpoint to refresh the friend listing. A more complicated form of this is to make adding/removing friends only via spectator, but that would require osu-web changes too. --- osu.Game/Online/Metadata/IMetadataServer.cs | 5 +++++ osu.Game/Online/Metadata/MetadataClient.cs | 13 +++++++++++++ osu.Game/Online/Metadata/OnlineMetadataClient.cs | 9 +++++++++ .../Tests/Visual/Metadata/TestMetadataClient.cs | 2 ++ 4 files changed, 29 insertions(+) diff --git a/osu.Game/Online/Metadata/IMetadataServer.cs b/osu.Game/Online/Metadata/IMetadataServer.cs index 79ed8b5634..dc1d486b4a 100644 --- a/osu.Game/Online/Metadata/IMetadataServer.cs +++ b/osu.Game/Online/Metadata/IMetadataServer.cs @@ -53,5 +53,10 @@ namespace osu.Game.Online.Metadata /// Signals to the server that the current user would like to stop receiving updates about the state of the multiplayer room with the given . /// Task EndWatchingMultiplayerRoom(long id); + + /// + /// Refresh this user's friend listing. + /// + Task RefreshFriends(); } } diff --git a/osu.Game/Online/Metadata/MetadataClient.cs b/osu.Game/Online/Metadata/MetadataClient.cs index 0679191a52..e70fe6d3bb 100644 --- a/osu.Game/Online/Metadata/MetadataClient.cs +++ b/osu.Game/Online/Metadata/MetadataClient.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Users; @@ -21,6 +22,16 @@ namespace osu.Game.Online.Metadata [Resolved] private IAPIProvider api { get; set; } = null!; + private readonly IBindableList localFriends = new BindableList(); + + protected override void LoadComplete() + { + base.LoadComplete(); + + localFriends.BindTo(api.LocalUserState.Friends); + localFriends.BindCollectionChanged((_, _) => RefreshFriends().FireAndForget()); + } + #region Beatmap metadata updates public abstract Task GetChangesSince(int queueId); @@ -152,6 +163,8 @@ namespace osu.Game.Online.Metadata public abstract Task EndWatchingMultiplayerRoom(long id); + public abstract Task RefreshFriends(); + public event Action? MultiplayerRoomScoreSet; Task IMetadataClient.MultiplayerRoomScoreSet(MultiplayerRoomScoreSetEvent roomScoreSetEvent) diff --git a/osu.Game/Online/Metadata/OnlineMetadataClient.cs b/osu.Game/Online/Metadata/OnlineMetadataClient.cs index 052b742beb..0853ccf9df 100644 --- a/osu.Game/Online/Metadata/OnlineMetadataClient.cs +++ b/osu.Game/Online/Metadata/OnlineMetadataClient.cs @@ -288,6 +288,15 @@ namespace osu.Game.Online.Metadata Logger.Log($@"{nameof(OnlineMetadataClient)} stopped watching multiplayer room with ID {id}", LoggingTarget.Network); } + public override async Task RefreshFriends() + { + if (connector?.IsConnected.Value != true) + throw new OperationCanceledException(); + + Debug.Assert(connection != null); + await connection.InvokeAsync(nameof(IMetadataServer.RefreshFriends)).ConfigureAwait(false); + } + public override async Task DisconnectRequested() { await base.DisconnectRequested().ConfigureAwait(false); diff --git a/osu.Game/Tests/Visual/Metadata/TestMetadataClient.cs b/osu.Game/Tests/Visual/Metadata/TestMetadataClient.cs index dca1b0e468..5ded0601df 100644 --- a/osu.Game/Tests/Visual/Metadata/TestMetadataClient.cs +++ b/osu.Game/Tests/Visual/Metadata/TestMetadataClient.cs @@ -128,6 +128,8 @@ namespace osu.Game.Tests.Visual.Metadata public override Task EndWatchingMultiplayerRoom(long id) => Task.CompletedTask; + public override Task RefreshFriends() => Task.CompletedTask; + public void Disconnect() { isConnected.Value = false;