1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 09:32:55 +08:00

Merge pull request #11351 from bdach/client-playing-users

Change PlayingUsers population logic to match expectations
This commit is contained in:
Dean Herbert 2020-12-29 15:04:33 +09:00 committed by GitHub
commit d155f2c0e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 13 deletions

View File

@ -0,0 +1,57 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using Humanizer;
using NUnit.Framework;
using osu.Framework.Testing;
using osu.Game.Online.Multiplayer;
using osu.Game.Tests.Visual.Multiplayer;
using osu.Game.Users;
namespace osu.Game.Tests.NonVisual.Multiplayer
{
[HeadlessTest]
public class StatefulMultiplayerClientTest : MultiplayerTestScene
{
[Test]
public void TestPlayingUserTracking()
{
int id = 2000;
AddRepeatStep("add some users", () => Client.AddUser(new User { Id = id++ }), 5);
checkPlayingUserCount(0);
changeState(3, MultiplayerUserState.WaitingForLoad);
checkPlayingUserCount(3);
changeState(3, MultiplayerUserState.Playing);
checkPlayingUserCount(3);
changeState(3, MultiplayerUserState.Results);
checkPlayingUserCount(0);
changeState(6, MultiplayerUserState.WaitingForLoad);
checkPlayingUserCount(6);
AddStep("another user left", () => Client.RemoveUser(Client.Room?.Users.Last().User));
checkPlayingUserCount(5);
AddStep("leave room", () => Client.LeaveRoom());
checkPlayingUserCount(0);
}
private void checkPlayingUserCount(int expectedCount)
=> AddAssert($"{"user".ToQuantity(expectedCount)} playing", () => Client.CurrentMatchPlayingUserIds.Count == expectedCount);
private void changeState(int userCount, MultiplayerUserState state)
=> AddStep($"{"user".ToQuantity(userCount)} in {state}", () =>
{
for (int i = 0; i < userCount; ++i)
{
var userId = Client.Room?.Users[i].UserID ?? throw new AssertionException("Room cannot be null!");
Client.ChangeUserState(userId, state);
}
});
}
}

View File

@ -62,8 +62,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
streamingClient.Start(Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
Client.PlayingUsers.Clear();
Client.PlayingUsers.AddRange(streamingClient.PlayingUsers);
Client.CurrentMatchPlayingUserIds.Clear();
Client.CurrentMatchPlayingUserIds.AddRange(streamingClient.PlayingUsers);
Children = new Drawable[]
{
@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestUserQuit()
{
AddRepeatStep("mark user quit", () => Client.PlayingUsers.RemoveAt(0), users);
AddRepeatStep("mark user quit", () => Client.CurrentMatchPlayingUserIds.RemoveAt(0), users);
}
public class TestMultiplayerStreaming : SpectatorStreamingClient

View File

@ -61,9 +61,9 @@ namespace osu.Game.Online.Multiplayer
public MultiplayerRoom? Room { get; private set; }
/// <summary>
/// The users currently in gameplay.
/// The users in the joined <see cref="Room"/> which are participating in the current gameplay loop.
/// </summary>
public readonly BindableList<int> PlayingUsers = new BindableList<int>();
public readonly BindableList<int> CurrentMatchPlayingUserIds = new BindableList<int>();
[Resolved]
private UserLookupCache userLookupCache { get; set; } = null!;
@ -133,6 +133,7 @@ namespace osu.Game.Online.Multiplayer
apiRoom = null;
Room = null;
CurrentMatchPlayingUserIds.Clear();
RoomUpdated?.Invoke();
}, false);
@ -253,7 +254,7 @@ namespace osu.Game.Online.Multiplayer
return;
Room.Users.Remove(user);
PlayingUsers.Remove(user.UserID);
CurrentMatchPlayingUserIds.Remove(user.UserID);
RoomUpdated?.Invoke();
}, false);
@ -302,8 +303,7 @@ namespace osu.Game.Online.Multiplayer
Room.Users.Single(u => u.UserID == userId).State = state;
if (state != MultiplayerUserState.Playing)
PlayingUsers.Remove(userId);
updateUserPlayingState(userId, state);
RoomUpdated?.Invoke();
}, false);
@ -337,8 +337,6 @@ namespace osu.Game.Online.Multiplayer
if (Room == null)
return;
PlayingUsers.AddRange(Room.Users.Where(u => u.State == MultiplayerUserState.Playing).Select(u => u.UserID));
MatchStarted?.Invoke();
}, false);
@ -454,5 +452,24 @@ namespace osu.Game.Online.Multiplayer
apiRoom.Playlist.Clear(); // Clearing should be unnecessary, but here for sanity.
apiRoom.Playlist.Add(playlistItem);
}
/// <summary>
/// For the provided user ID, update whether the user is included in <see cref="CurrentMatchPlayingUserIds"/>.
/// </summary>
/// <param name="userId">The user's ID.</param>
/// <param name="state">The new state of the user.</param>
private void updateUserPlayingState(int userId, MultiplayerUserState state)
{
bool wasPlaying = CurrentMatchPlayingUserIds.Contains(userId);
bool isPlaying = state >= MultiplayerUserState.WaitingForLoad && state <= MultiplayerUserState.FinishedPlay;
if (isPlaying == wasPlaying)
return;
if (isPlaying)
CurrentMatchPlayingUserIds.Add(userId);
else
CurrentMatchPlayingUserIds.Remove(userId);
}
}
}

View File

@ -200,7 +200,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
Debug.Assert(client.Room != null);
int[] userIds = client.Room.Users.Where(u => u.State >= MultiplayerUserState.WaitingForLoad).Select(u => u.UserID).ToArray();
int[] userIds = client.CurrentMatchPlayingUserIds.ToArray();
StartPlay(() => new MultiplayerPlayer(SelectedItem.Value, userIds));
}

View File

@ -84,11 +84,11 @@ namespace osu.Game.Screens.Play.HUD
// BindableList handles binding in a really bad way (Clear then AddRange) so we need to do this manually..
foreach (int userId in playingUsers)
{
if (!multiplayerClient.PlayingUsers.Contains(userId))
if (!multiplayerClient.CurrentMatchPlayingUserIds.Contains(userId))
usersChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new[] { userId }));
}
playingUsers.BindTo(multiplayerClient.PlayingUsers);
playingUsers.BindTo(multiplayerClient.CurrentMatchPlayingUserIds);
playingUsers.BindCollectionChanged(usersChanged);
}