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

Make Room.ParticipantCount & Room.MaxParticipants non-bindable

This commit is contained in:
Dan Balasescu 2024-11-13 19:45:03 +09:00
parent f001cce24a
commit b8bae30b66
No known key found for this signature in database
11 changed files with 146 additions and 61 deletions

View File

@ -143,13 +143,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
Id = id, Id = id,
Username = $"User {id}" Username = $"User {id}"
}); });
SelectedRoom.Value.ParticipantCount.Value++; SelectedRoom.Value.ParticipantCount++;
} }
private void removeUserAt(int index) private void removeUserAt(int index)
{ {
SelectedRoom.Value.RecentParticipants.RemoveAt(index); SelectedRoom.Value.RecentParticipants.RemoveAt(index);
SelectedRoom.Value.ParticipantCount.Value--; SelectedRoom.Value.ParticipantCount--;
} }
} }
} }

View File

@ -248,7 +248,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
} }
}); });
AddUntilStep("Check participant count correct", () => multiplayerClient.ClientAPIRoom?.ParticipantCount.Value == 1); AddUntilStep("Check participant count correct", () => multiplayerClient.ClientAPIRoom?.ParticipantCount == 1);
AddUntilStep("Check participant list contains user", () => multiplayerClient.ClientAPIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); AddUntilStep("Check participant list contains user", () => multiplayerClient.ClientAPIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
} }
@ -308,7 +308,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true); AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
AddUntilStep("wait for join", () => multiplayerClient.RoomJoined); AddUntilStep("wait for join", () => multiplayerClient.RoomJoined);
AddUntilStep("Check participant count correct", () => multiplayerClient.ClientAPIRoom?.ParticipantCount.Value == 1); AddUntilStep("Check participant count correct", () => multiplayerClient.ClientAPIRoom?.ParticipantCount == 1);
AddUntilStep("Check participant list contains user", () => multiplayerClient.ClientAPIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1); AddUntilStep("Check participant list contains user", () => multiplayerClient.ClientAPIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
} }

View File

@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Playlists
{ {
AddStep("create component", () => AddStep("create component", () =>
{ {
Child = new ParticipantsDisplay(Direction.Horizontal) Child = new ParticipantsDisplay(SelectedRoom.Value, Direction.Horizontal)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual.Playlists
{ {
AddStep("create component", () => AddStep("create component", () =>
{ {
Child = new ParticipantsDisplay(Direction.Vertical) Child = new ParticipantsDisplay(SelectedRoom.Value, Direction.Vertical)
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,

View File

@ -492,7 +492,7 @@ namespace osu.Game.Online.Multiplayer
Id = user.UserID, Id = user.UserID,
Username = "[Unresolved]" Username = "[Unresolved]"
}); });
APIRoom.ParticipantCount.Value++; APIRoom.ParticipantCount++;
} }
private Task handleUserLeft(MultiplayerRoomUser user, Action<MultiplayerRoomUser>? callback) private Task handleUserLeft(MultiplayerRoomUser user, Action<MultiplayerRoomUser>? callback)
@ -507,7 +507,7 @@ namespace osu.Game.Online.Multiplayer
Debug.Assert(APIRoom != null); Debug.Assert(APIRoom != null);
APIRoom.RecentParticipants.RemoveAll(u => u.Id == user.UserID); APIRoom.RecentParticipants.RemoveAll(u => u.Id == user.UserID);
APIRoom.ParticipantCount.Value--; APIRoom.ParticipantCount--;
callback?.Invoke(user); callback?.Invoke(user);
RoomUpdated?.Invoke(); RoomUpdated?.Invoke();

View File

@ -86,6 +86,24 @@ namespace osu.Game.Online.Rooms
set => SetField(ref category, value); set => SetField(ref category, value);
} }
/// <summary>
/// The maximum number of users allowed in the room.
/// </summary>
public int? MaxParticipants
{
get => maxParticipants;
set => SetField(ref maxParticipants, value);
}
/// <summary>
/// The current number of users in the room.
/// </summary>
public int ParticipantCount
{
get => participantCount;
set => SetField(ref participantCount, value);
}
/// <summary> /// <summary>
/// The match type. /// The match type.
/// </summary> /// </summary>
@ -162,6 +180,12 @@ namespace osu.Game.Online.Rooms
[JsonConverter(typeof(SnakeCaseStringEnumConverter))] [JsonConverter(typeof(SnakeCaseStringEnumConverter))]
private RoomCategory category; private RoomCategory category;
// Not yet serialised (not implemented).
private int? maxParticipants;
[JsonProperty("participant_count")]
private int participantCount;
[JsonConverter(typeof(SnakeCaseStringEnumConverter))] [JsonConverter(typeof(SnakeCaseStringEnumConverter))]
[JsonProperty("type")] [JsonProperty("type")]
private MatchType type; private MatchType type;
@ -211,9 +235,6 @@ namespace osu.Game.Online.Rooms
set => AutoStartDuration.Value = TimeSpan.FromSeconds(value); set => AutoStartDuration.Value = TimeSpan.FromSeconds(value);
} }
[Cached]
public readonly Bindable<int?> MaxParticipants = new Bindable<int?>();
[Cached] [Cached]
[JsonProperty("current_user_score")] [JsonProperty("current_user_score")]
public readonly Bindable<PlaylistAggregateScore> UserScore = new Bindable<PlaylistAggregateScore>(); public readonly Bindable<PlaylistAggregateScore> UserScore = new Bindable<PlaylistAggregateScore>();
@ -222,10 +243,6 @@ namespace osu.Game.Online.Rooms
[JsonProperty("recent_participants")] [JsonProperty("recent_participants")]
public readonly BindableList<APIUser> RecentParticipants = new BindableList<APIUser>(); public readonly BindableList<APIUser> RecentParticipants = new BindableList<APIUser>();
[Cached]
[JsonProperty("participant_count")]
public readonly Bindable<int> ParticipantCount = new Bindable<int>();
#region Properties only used for room creation request #region Properties only used for room creation request
[Cached] [Cached]
@ -286,8 +303,8 @@ namespace osu.Game.Online.Rooms
Availability = other.Availability; Availability = other.Availability;
HasPassword = other.HasPassword; HasPassword = other.HasPassword;
Type = other.Type; Type = other.Type;
MaxParticipants.Value = other.MaxParticipants.Value; MaxParticipants = other.MaxParticipants;
ParticipantCount.Value = other.ParticipantCount.Value; ParticipantCount = other.ParticipantCount;
EndDate.Value = other.EndDate.Value; EndDate.Value = other.EndDate.Value;
UserScore.Value = other.UserScore.Value; UserScore.Value = other.UserScore.Value;
QueueMode = other.QueueMode; QueueMode = other.QueueMode;

View File

@ -1,13 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
#nullable disable using System.ComponentModel;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Components namespace osu.Game.Screens.OnlinePlay.Components
{ {
@ -16,18 +16,21 @@ namespace osu.Game.Screens.OnlinePlay.Components
private const float text_size = 30; private const float text_size = 30;
private const float transition_duration = 100; private const float transition_duration = 100;
private OsuSpriteText slash, maxText; private readonly Room room;
public ParticipantCountDisplay() private OsuSpriteText slash = null!;
private OsuSpriteText maxText = null!;
private OsuSpriteText count = null!;
public ParticipantCountDisplay(Room room)
{ {
this.room = room;
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
OsuSpriteText count;
InternalChild = new FillFlowContainer InternalChild = new FillFlowContainer
{ {
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
@ -50,14 +53,33 @@ namespace osu.Game.Screens.OnlinePlay.Components
}, },
} }
}; };
MaxParticipants.BindValueChanged(_ => updateMax(), true);
ParticipantCount.BindValueChanged(c => count.Text = c.NewValue.ToString("#,0"), true);
} }
private void updateMax() protected override void LoadComplete()
{ {
if (MaxParticipants.Value == null) base.LoadComplete();
room.PropertyChanged += onRoomPropertyChanged;
updateRoomParticipantCount();
}
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(Room.MaxParticipants):
updateRoomMaxParticipants();
break;
case nameof(Room.ParticipantCount):
updateRoomParticipantCount();
break;
}
}
private void updateRoomMaxParticipants()
{
if (room.MaxParticipants == null)
{ {
slash.FadeOut(transition_duration); slash.FadeOut(transition_duration);
maxText.FadeOut(transition_duration); maxText.FadeOut(transition_duration);
@ -65,9 +87,18 @@ namespace osu.Game.Screens.OnlinePlay.Components
else else
{ {
slash.FadeIn(transition_duration); slash.FadeIn(transition_duration);
maxText.Text = MaxParticipants.Value.ToString(); maxText.Text = room.MaxParticipants.ToString()!;
maxText.FadeIn(transition_duration); maxText.FadeIn(transition_duration);
} }
} }
private void updateRoomParticipantCount()
=> count.Text = room.ParticipantCount.ToString("#,0");
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
room.PropertyChanged -= onRoomPropertyChanged;
}
} }
} }

View File

@ -1,19 +1,23 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation; using System.ComponentModel;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Components namespace osu.Game.Screens.OnlinePlay.Components
{ {
public partial class ParticipantsDisplay : OnlinePlayComposite public partial class ParticipantsDisplay : OnlinePlayComposite
{ {
public Bindable<string> Details = new Bindable<string>(); public readonly Bindable<string> Details = new Bindable<string>();
public ParticipantsDisplay(Direction direction) private readonly Room room;
public ParticipantsDisplay(Room room, Direction direction)
{ {
this.room = room;
OsuScrollContainer scroll; OsuScrollContainer scroll;
ParticipantsList list; ParticipantsList list;
@ -46,14 +50,32 @@ namespace osu.Game.Screens.OnlinePlay.Components
} }
} }
[BackgroundDependencyLoader] protected override void LoadComplete()
private void load()
{ {
ParticipantCount.BindValueChanged(_ => setParticipantCount()); base.LoadComplete();
MaxParticipants.BindValueChanged(_ => setParticipantCount(), true);
room.PropertyChanged += onRoomPropertyChanged;
updateRoomParticipantCount();
} }
private void setParticipantCount() => private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
Details.Value = MaxParticipants.Value != null ? $"{ParticipantCount.Value}/{MaxParticipants.Value}" : ParticipantCount.Value.ToString(); {
switch (e.PropertyName)
{
case nameof(Room.MaxParticipants):
case nameof(Room.ParticipantCount):
updateRoomParticipantCount();
break;
}
}
private void updateRoomParticipantCount()
=> Details.Value = room.MaxParticipants != null ? $"{room.ParticipantCount}/{room.MaxParticipants}" : room.ParticipantCount.ToString();
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
room.PropertyChanged -= onRoomPropertyChanged;
}
} }
} }

View File

@ -166,14 +166,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
base.LoadComplete(); base.LoadComplete();
RecentParticipants.BindCollectionChanged(onParticipantsChanged, true); RecentParticipants.BindCollectionChanged(onParticipantsChanged, true);
ParticipantCount.BindValueChanged(_ =>
{
updateHiddenUsers();
totalCount.Text = ParticipantCount.Value.ToString();
}, true);
room.PropertyChanged += onRoomPropertyChanged; room.PropertyChanged += onRoomPropertyChanged;
updateRoomHost(); updateRoomHost();
updateRoomParticipantCount();
} }
private int numberOfCircles = 4; private int numberOfCircles = 4;
@ -257,7 +254,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{ {
int hiddenCount = 0; int hiddenCount = 0;
if (RecentParticipants.Count > NumberOfCircles) if (RecentParticipants.Count > NumberOfCircles)
hiddenCount = ParticipantCount.Value - NumberOfCircles + 1; hiddenCount = room.ParticipantCount - NumberOfCircles + 1;
hiddenUsers.Count = hiddenCount; hiddenUsers.Count = hiddenCount;
@ -272,8 +269,16 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e) private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(Room.Host)) switch (e.PropertyName)
updateRoomHost(); {
case nameof(Room.Host):
updateRoomHost();
break;
case nameof(Room.ParticipantCount):
updateRoomParticipantCount();
break;
}
} }
private void updateRoomHost() private void updateRoomHost()
@ -288,6 +293,12 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
} }
} }
private void updateRoomParticipantCount()
{
updateHiddenUsers();
totalCount.Text = room.ParticipantCount.ToString();
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);

View File

@ -350,7 +350,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
}; };
TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue.GetLocalisableDescription(), true); TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue.GetLocalisableDescription(), true);
MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true);
AutoStartDuration.BindValueChanged(duration => startModeDropdown.Current.Value = (StartMode)(int)duration.NewValue.TotalSeconds, true); AutoStartDuration.BindValueChanged(duration => startModeDropdown.Current.Value = (StartMode)(int)duration.NewValue.TotalSeconds, true);
operationInProgress.BindTo(ongoingOperationTracker.InProgress); operationInProgress.BindTo(ongoingOperationTracker.InProgress);
@ -377,6 +376,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
updateRoomQueueMode(); updateRoomQueueMode();
updateRoomPassword(); updateRoomPassword();
updateRoomAutoSkip(); updateRoomAutoSkip();
updateRoomMaxParticipants();
} }
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e) private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
@ -402,6 +402,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
case nameof(Room.AutoSkip): case nameof(Room.AutoSkip):
updateRoomAutoSkip(); updateRoomAutoSkip();
break; break;
case nameof(Room.MaxParticipants):
updateRoomMaxParticipants();
break;
} }
} }
@ -420,6 +424,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private void updateRoomAutoSkip() private void updateRoomAutoSkip()
=> AutoSkipCheckbox.Current.Value = room.AutoSkip; => AutoSkipCheckbox.Current.Value = room.AutoSkip;
private void updateRoomMaxParticipants()
=> MaxParticipantsField.Text = room.MaxParticipants?.ToString();
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
@ -469,9 +476,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
room.AutoSkip = AutoSkipCheckbox.Current.Value; room.AutoSkip = AutoSkipCheckbox.Current.Value;
if (int.TryParse(MaxParticipantsField.Text, out int max)) if (int.TryParse(MaxParticipantsField.Text, out int max))
room.MaxParticipants.Value = max; room.MaxParticipants = max;
else else
room.MaxParticipants.Value = null; room.MaxParticipants = null;
manager.CreateRoom(room, onSuccess, onError); manager.CreateRoom(room, onSuccess, onError);
} }

View File

@ -27,12 +27,6 @@ namespace osu.Game.Screens.OnlinePlay
[Resolved(typeof(Room))] [Resolved(typeof(Room))]
protected BindableList<APIUser> RecentParticipants { get; private set; } = null!; protected BindableList<APIUser> RecentParticipants { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<int> ParticipantCount { get; private set; } = null!;
[Resolved(typeof(Room))]
protected Bindable<int?> MaxParticipants { get; private set; } = null!;
[Resolved(typeof(Room))] [Resolved(typeof(Room))]
protected Bindable<int?> MaxAttempts { get; private set; } = null!; protected Bindable<int?> MaxAttempts { get; private set; } = null!;

View File

@ -316,7 +316,6 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
loadingLayer = new LoadingLayer(true) loadingLayer = new LoadingLayer(true)
}; };
MaxParticipants.BindValueChanged(count => MaxParticipantsField.Text = count.NewValue?.ToString(), true);
MaxAttempts.BindValueChanged(count => MaxAttemptsField.Text = count.NewValue?.ToString(), true); MaxAttempts.BindValueChanged(count => MaxAttemptsField.Text = count.NewValue?.ToString(), true);
Duration.BindValueChanged(duration => DurationField.Current.Value = duration.NewValue ?? TimeSpan.FromMinutes(30), true); Duration.BindValueChanged(duration => DurationField.Current.Value = duration.NewValue ?? TimeSpan.FromMinutes(30), true);
@ -346,6 +345,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
updateRoomName(); updateRoomName();
updateRoomAvailability(); updateRoomAvailability();
updateRoomMaxParticipants();
} }
private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e) private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e)
@ -359,6 +359,10 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
case nameof(Room.Availability): case nameof(Room.Availability):
updateRoomAvailability(); updateRoomAvailability();
break; break;
case nameof(Room.MaxParticipants):
updateRoomMaxParticipants();
break;
} }
} }
@ -368,6 +372,9 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
private void updateRoomAvailability() private void updateRoomAvailability()
=> AvailabilityPicker.Current.Value = room.Availability; => AvailabilityPicker.Current.Value = room.Availability;
private void updateRoomMaxParticipants()
=> MaxParticipantsField.Text = room.MaxParticipants?.ToString();
private void populateDurations(ValueChangedEvent<APIUser> user) private void populateDurations(ValueChangedEvent<APIUser> user)
{ {
// roughly correct (see https://github.com/Humanizr/Humanizer/blob/18167e56c082449cc4fe805b8429e3127a7b7f93/readme.md?plain=1#L427) // roughly correct (see https://github.com/Humanizr/Humanizer/blob/18167e56c082449cc4fe805b8429e3127a7b7f93/readme.md?plain=1#L427)
@ -417,11 +424,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
room.Name = NameField.Text; room.Name = NameField.Text;
room.Availability = AvailabilityPicker.Current.Value; room.Availability = AvailabilityPicker.Current.Value;
room.MaxParticipants = int.TryParse(MaxParticipantsField.Text, out int max) ? max : null;
if (int.TryParse(MaxParticipantsField.Text, out int max))
MaxParticipants.Value = max;
else
MaxParticipants.Value = null;
if (int.TryParse(MaxAttemptsField.Text, out max)) if (int.TryParse(MaxAttemptsField.Text, out max))
MaxAttempts.Value = max; MaxAttempts.Value = max;