diff --git a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs index 559db16751..a6d715df62 100644 --- a/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs +++ b/osu.Game.Tests/NonVisual/Multiplayer/StatefulMultiplayerClientTest.cs @@ -6,6 +6,7 @@ using Humanizer; using NUnit.Framework; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Testing; +using osu.Game.Extensions; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; @@ -93,6 +94,29 @@ namespace osu.Game.Tests.NonVisual.Multiplayer checkPlayingUserCount(1); } + [Test] + public void TestJoinRoomWithManyUsers() + { + AddStep("leave room", () => MultiplayerClient.LeaveRoom()); + AddUntilStep("wait for room part", () => !RoomJoined); + + AddStep("create room with many users", () => + { + var newRoom = new Room(); + newRoom.CopyFrom(SelectedRoom.Value!); + + newRoom.RoomID = null; + MultiplayerClient.RoomSetupAction = room => + { + room.Users.AddRange(Enumerable.Range(PLAYER_1_ID, 100).Select(id => new MultiplayerRoomUser(id))); + }; + + RoomManager.CreateRoom(newRoom); + }); + + AddUntilStep("wait for room join", () => RoomJoined); + } + private void checkPlayingUserCount(int expectedCount) => AddAssert($"{"user".ToQuantity(expectedCount)} playing", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count == expectedCount); diff --git a/osu.Game/Online/API/Requests/GetUsersRequest.cs b/osu.Game/Online/API/Requests/GetUsersRequest.cs index cd75ff4e31..fe7ba8c33d 100644 --- a/osu.Game/Online/API/Requests/GetUsersRequest.cs +++ b/osu.Game/Online/API/Requests/GetUsersRequest.cs @@ -13,14 +13,14 @@ namespace osu.Game.Online.API.Requests /// public class GetUsersRequest : APIRequest { - public readonly int[] UserIds; + public const int MAX_IDS_PER_REQUEST = 50; - private const int max_ids_per_request = 50; + public readonly int[] UserIds; public GetUsersRequest(int[] userIds) { - if (userIds.Length > max_ids_per_request) - throw new ArgumentException($"{nameof(GetUsersRequest)} calls only support up to {max_ids_per_request} IDs at once"); + if (userIds.Length > MAX_IDS_PER_REQUEST) + throw new ArgumentException($"{nameof(GetUsersRequest)} calls only support up to {MAX_IDS_PER_REQUEST} IDs at once"); UserIds = userIds; } diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 2d445ea25a..9abc013b66 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -815,19 +815,22 @@ namespace osu.Game.Online.Multiplayer /// The s to populate. protected async Task PopulateUsers(IEnumerable multiplayerUsers) { - var request = new GetUsersRequest(multiplayerUsers.Select(u => u.UserID).Distinct().ToArray()); - - await API.PerformAsync(request).ConfigureAwait(false); - - if (request.Response == null) - return; - - Dictionary users = request.Response.Users.ToDictionary(user => user.Id); - - foreach (var multiplayerUser in multiplayerUsers) + foreach (int[] userChunk in multiplayerUsers.Select(u => u.UserID).Distinct().Chunk(GetUsersRequest.MAX_IDS_PER_REQUEST)) { - if (users.TryGetValue(multiplayerUser.UserID, out var user)) - multiplayerUser.User = user; + var request = new GetUsersRequest(userChunk); + + await API.PerformAsync(request).ConfigureAwait(false); + + if (request.Response == null) + return; + + Dictionary users = request.Response.Users.ToDictionary(user => user.Id); + + foreach (var multiplayerUser in multiplayerUsers) + { + if (users.TryGetValue(multiplayerUser.UserID, out var user)) + multiplayerUser.User = user; + } } }