From 5d4838a08b93cd4ae5d4d963710b6e679fdada69 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 13 Nov 2024 18:48:13 +0900 Subject: [PATCH] Make `Room.Status` non-bindable --- .../Multiplayer/TestSceneDrawableRoom.cs | 14 +++---- .../Online/Multiplayer/MultiplayerClient.cs | 8 ++-- osu.Game/Online/Rooms/GetRoomsRequest.cs | 6 +-- osu.Game/Online/Rooms/Room.cs | 19 ++++++--- .../Components/StatusColouredContainer.cs | 39 +++++++++++++------ .../Lounge/Components/DrawableRoom.cs | 2 +- .../Lounge/Components/RoomStatusPill.cs | 35 +++++++++++++---- .../Multiplayer/MultiplayerRoomManager.cs | 2 +- .../Screens/OnlinePlay/OnlinePlayComposite.cs | 3 -- 9 files changed, 84 insertions(+), 44 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs index 4c9aa6af15..a40a75c885 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoom.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Multiplayer createLoungeRoom(new Room { Name = "Multiplayer room", - Status = { Value = new RoomStatusOpen() }, + Status = new RoomStatusOpen(), EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, Type = MatchType.HeadToHead, Playlist = { item1 }, @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.Multiplayer createLoungeRoom(new Room { Name = "Private room", - Status = { Value = new RoomStatusOpenPrivate() }, + Status = new RoomStatusOpenPrivate(), HasPassword = { Value = true }, EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, Type = MatchType.HeadToHead, @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Visual.Multiplayer createLoungeRoom(new Room { Name = "Playlist room with multiple beatmaps", - Status = { Value = new RoomStatusPlaying() }, + Status = new RoomStatusPlaying(), EndDate = { Value = DateTimeOffset.Now.AddDays(1) }, Playlist = { item1, item2 }, CurrentPlaylistItem = item1 @@ -103,19 +103,19 @@ namespace osu.Game.Tests.Visual.Multiplayer createLoungeRoom(new Room { Name = "Finished room", - Status = { Value = new RoomStatusEnded() }, + Status = new RoomStatusEnded(), EndDate = { Value = DateTimeOffset.Now }, }), createLoungeRoom(new Room { Name = "Spotlight room", - Status = { Value = new RoomStatusOpen() }, + Status = new RoomStatusOpen(), Category = RoomCategory.Spotlight, }), createLoungeRoom(new Room { Name = "Featured artist room", - Status = { Value = new RoomStatusOpen() }, + Status = new RoomStatusOpen(), Category = RoomCategory.FeaturedArtist, }), } @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddStep("create room", () => Child = drawableRoom = createLoungeRoom(room = new Room { Name = "Room with password", - Status = { Value = new RoomStatusOpen() }, + Status = new RoomStatusOpen(), Type = MatchType.HeadToHead, })); diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index a6037e8907..f26dbb3239 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -397,15 +397,15 @@ namespace osu.Game.Online.Multiplayer switch (state) { case MultiplayerRoomState.Open: - APIRoom.Status.Value = APIRoom.HasPassword.Value ? new RoomStatusOpenPrivate() : new RoomStatusOpen(); + APIRoom.Status = APIRoom.HasPassword.Value ? new RoomStatusOpenPrivate() : new RoomStatusOpen(); break; case MultiplayerRoomState.Playing: - APIRoom.Status.Value = new RoomStatusPlaying(); + APIRoom.Status = new RoomStatusPlaying(); break; case MultiplayerRoomState.Closed: - APIRoom.Status.Value = new RoomStatusEnded(); + APIRoom.Status = new RoomStatusEnded(); break; } @@ -843,7 +843,7 @@ namespace osu.Game.Online.Multiplayer Room.Settings = settings; APIRoom.Name = Room.Settings.Name; APIRoom.Password.Value = Room.Settings.Password; - APIRoom.Status.Value = string.IsNullOrEmpty(Room.Settings.Password) ? new RoomStatusOpen() : new RoomStatusOpenPrivate(); + APIRoom.Status = string.IsNullOrEmpty(Room.Settings.Password) ? new RoomStatusOpen() : new RoomStatusOpenPrivate(); APIRoom.Type = Room.Settings.MatchType; APIRoom.QueueMode.Value = Room.Settings.QueueMode; APIRoom.AutoStartDuration.Value = Room.Settings.AutoStartDuration; diff --git a/osu.Game/Online/Rooms/GetRoomsRequest.cs b/osu.Game/Online/Rooms/GetRoomsRequest.cs index 1b5e08c729..980ce74718 100644 --- a/osu.Game/Online/Rooms/GetRoomsRequest.cs +++ b/osu.Game/Online/Rooms/GetRoomsRequest.cs @@ -45,11 +45,11 @@ namespace osu.Game.Online.Rooms foreach (var room in Response) { if (room.EndDate.Value != null && DateTimeOffset.Now >= room.EndDate.Value) - room.Status.Value = new RoomStatusEnded(); + room.Status = new RoomStatusEnded(); else if (room.HasPassword.Value) - room.Status.Value = new RoomStatusOpenPrivate(); + room.Status = new RoomStatusOpenPrivate(); else - room.Status.Value = new RoomStatusOpen(); + room.Status = new RoomStatusOpen(); } } } diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index acc7d7b3df..760580c003 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -78,6 +78,15 @@ namespace osu.Game.Online.Rooms set => SetField(ref currentPlaylistItem, value); } + /// + /// The current room status. + /// + public RoomStatus Status + { + get => status; + set => SetField(ref status, value); + } + [JsonProperty("id")] private long? roomId; @@ -98,6 +107,9 @@ namespace osu.Game.Online.Rooms [JsonProperty("current_playlist_item")] private PlaylistItem? currentPlaylistItem; + // Not serialised (see: GetRoomsRequest). + private RoomStatus status = new RoomStatusOpen(); + [Cached] [JsonProperty("playlist")] public readonly BindableList Playlist = new BindableList(); @@ -117,9 +129,6 @@ namespace osu.Game.Online.Rooms [Cached] public readonly Bindable MaxAttempts = new Bindable(); - [Cached] - public readonly Bindable Status = new Bindable(new RoomStatusOpen()); - [Cached] public readonly Bindable Availability = new Bindable(); @@ -231,7 +240,7 @@ namespace osu.Game.Online.Rooms Host = other.Host; ChannelId.Value = other.ChannelId.Value; - Status.Value = other.Status.Value; + Status = other.Status; Availability.Value = other.Availability.Value; HasPassword.Value = other.HasPassword.Value; Type = other.Type; @@ -266,7 +275,7 @@ namespace osu.Game.Online.Rooms // Todo: This is not the best way/place to do this, but the intention is to display all playlist items when the room has ended, // and display only the non-expired playlist items while the room is still active. In order to achieve this, all expired items are removed from the source Room. // More refactoring is required before this can be done locally instead - DrawableRoomPlaylist is currently directly bound to the playlist to display items in the room. - if (!(Status.Value is RoomStatusEnded)) + if (Status is not RoomStatusEnded) Playlist.RemoveAll(i => i.Expired); } diff --git a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs index 90127dc961..2b1233506f 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StatusColouredContainer.cs @@ -1,22 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.ComponentModel; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Online.Rooms; +using Container = osu.Framework.Graphics.Containers.Container; namespace osu.Game.Screens.OnlinePlay.Components { public partial class StatusColouredContainer : Container { + [Resolved] + private OsuColour colours { get; set; } = null!; + private readonly double transitionDuration; - - [Resolved(typeof(Room), nameof(Room.Status))] - private Bindable status { get; set; } = null!; - private readonly Room room; public StatusColouredContainer(Room room, double transitionDuration = 100) @@ -25,13 +24,29 @@ namespace osu.Game.Screens.OnlinePlay.Components this.transitionDuration = transitionDuration; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + protected override void LoadComplete() { - status.BindValueChanged(s => - { - this.FadeColour(colours.ForRoomCategory(room.Category) ?? s.NewValue.GetAppropriateColour(colours), transitionDuration); - }, true); + base.LoadComplete(); + + room.PropertyChanged += onRoomPropertyChanged; + updateRoomStatus(); + } + + private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(Room.Status)) + updateRoomStatus(); + } + + private void updateRoomStatus() + { + this.FadeColour(colours.ForRoomCategory(room.Category) ?? room.Status.GetAppropriateColour(colours), transitionDuration); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + room.PropertyChanged -= onRoomPropertyChanged; } } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index d05d887038..8fb439452c 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -159,7 +159,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components Spacing = new Vector2(5), Children = new Drawable[] { - new RoomStatusPill + new RoomStatusPill(Room) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs index 96d698a184..10d3695d14 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomStatusPill.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; @@ -19,25 +20,43 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected override FontUsage Font => base.Font.With(weight: FontWeight.SemiBold); + private readonly Room room; + + public RoomStatusPill(Room room) + { + this.room = room; + } + protected override void LoadComplete() { base.LoadComplete(); - EndDate.BindValueChanged(_ => updateDisplay()); - Status.BindValueChanged(_ => updateDisplay(), true); - - FinishTransforms(true); - TextFlow.Colour = Colour4.Black; Pill.Background.Alpha = 1; + + EndDate.BindValueChanged(_ => updateDisplay()); + room.PropertyChanged += onRoomPropertyChanged; + updateDisplay(); + + FinishTransforms(true); + } + + private void onRoomPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(Room.Status)) + updateDisplay(); } private void updateDisplay() { - RoomStatus status = Status.Value; + Pill.Background.FadeColour(room.Status.GetAppropriateColour(colours), 100); + TextFlow.Text = room.Status.Message; + } - Pill.Background.FadeColour(status.GetAppropriateColour(colours), 100); - TextFlow.Text = status.Message; + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + room.PropertyChanged -= onRoomPropertyChanged; } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs index d7efd30435..b119c6d59d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomManager.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // this is done here as a pre-check to avoid clicking on already closed rooms in the lounge from triggering a server join. // should probably be done at a higher level, but due to the current structure of things this is the easiest place for now. - if (room.Status.Value is RoomStatusEnded) + if (room.Status is RoomStatusEnded) { onError?.Invoke("Cannot join an ended room."); return; diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 7e29c2f117..82774abac7 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -16,9 +16,6 @@ namespace osu.Game.Screens.OnlinePlay /// public partial class OnlinePlayComposite : CompositeDrawable { - [Resolved(typeof(Room))] - protected Bindable Status { get; private set; } = null!; - [Resolved(typeof(Room))] protected Bindable PlaylistItemStats { get; private set; } = null!;