From 7f4cc221d25c9d9733c5ec6189db61a3a0f0e2f7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Feb 2022 18:33:27 +0900 Subject: [PATCH 01/20] Add API versioning --- osu.Game/Online/API/APIAccess.cs | 2 ++ osu.Game/Online/API/APIRequest.cs | 4 ++++ osu.Game/Online/API/DummyAPIAccess.cs | 2 ++ osu.Game/Online/API/IAPIProvider.cs | 5 +++++ 4 files changed, 13 insertions(+) diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index c5302a393c..8c9741b98b 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -36,6 +36,8 @@ namespace osu.Game.Online.API public string WebsiteRootUrl { get; } + public int APIVersion => 20220217; // We may want to pull this from the game version eventually. + public Exception LastLoginError { get; private set; } public string ProvidedUsername { get; private set; } diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 91148c177f..776ff5fd8f 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Globalization; using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.IO.Network; @@ -112,6 +113,9 @@ namespace osu.Game.Online.API WebRequest = CreateWebRequest(); WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; + + WebRequest.AddHeader("x-api-version", API.APIVersion.ToString(CultureInfo.InvariantCulture)); + if (!string.IsNullOrEmpty(API.AccessToken)) WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 7131c3a7d4..f292e95bd1 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -33,6 +33,8 @@ namespace osu.Game.Online.API public string WebsiteRootUrl => "http://localhost"; + public int APIVersion => int.Parse(DateTime.Now.ToString("yyyyMMdd")); + public Exception LastLoginError { get; private set; } /// diff --git a/osu.Game/Online/API/IAPIProvider.cs b/osu.Game/Online/API/IAPIProvider.cs index a97eae77e3..470d46cd7f 100644 --- a/osu.Game/Online/API/IAPIProvider.cs +++ b/osu.Game/Online/API/IAPIProvider.cs @@ -57,6 +57,11 @@ namespace osu.Game.Online.API /// string WebsiteRootUrl { get; } + /// + /// The version of the API. + /// + int APIVersion { get; } + /// /// The last login error that occurred, if any. /// From 39d64e779cd576f5e0a7e62705c7063ceb49930a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 17 Feb 2022 19:15:09 +0900 Subject: [PATCH 02/20] Handle API returned difficulty range for rooms --- osu.Game/Online/Rooms/Room.cs | 13 ++++++++++++ .../Components/StarRatingRangeDisplay.cs | 21 ++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index bbe854f2dd..6722dac51d 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -37,6 +37,9 @@ namespace osu.Game.Online.Rooms [JsonProperty("channel_id")] public readonly Bindable ChannelId = new Bindable(); + [JsonProperty("difficulty_range")] + public readonly Bindable DifficultyRange = new Bindable(); + [Cached] [JsonIgnore] public readonly Bindable Category = new Bindable(); @@ -228,5 +231,15 @@ namespace osu.Game.Online.Rooms public bool ShouldSerializeEndDate() => false; #endregion + + [JsonObject(MemberSerialization.OptIn)] + public class RoomDifficultyRange + { + [JsonProperty("min")] + public double Min; + + [JsonProperty("max")] + public double Max; + } } } diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 95ecadd21a..f27f5d6741 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -12,6 +12,7 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; +using osu.Game.Online.Rooms; using osuTK; namespace osu.Game.Screens.OnlinePlay.Components @@ -71,6 +72,9 @@ namespace osu.Game.Screens.OnlinePlay.Components }; } + [Resolved] + private Room room { get; set; } + protected override void LoadComplete() { base.LoadComplete(); @@ -80,10 +84,21 @@ namespace osu.Game.Screens.OnlinePlay.Components private void updateRange(object sender, NotifyCollectionChangedEventArgs e) { - var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray(); + StarDifficulty minDifficulty; + StarDifficulty maxDifficulty; - StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0); - StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0); + if (room.DifficultyRange != null) + { + minDifficulty = new StarDifficulty(room.DifficultyRange.Value.Min, 0); + maxDifficulty = new StarDifficulty(room.DifficultyRange.Value.Max, 0); + } + else + { + var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray(); + + minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0); + maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0); + } minDisplay.Current.Value = minDifficulty; maxDisplay.Current.Value = maxDifficulty; From b43008b9f6ffc796e5927bf218230d9a4e806dc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Feb 2022 19:02:21 +0900 Subject: [PATCH 03/20] Add cover and count handling from newer response version --- osu.Game/Online/Rooms/Room.cs | 21 +++++++++++++++++++ .../Components/OnlinePlayBackgroundSprite.cs | 3 ++- .../Lounge/Components/PlaylistCountPill.cs | 13 +++++++----- .../Screens/OnlinePlay/OnlinePlayComposite.cs | 6 ++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 6722dac51d..db24eeea41 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -37,6 +37,14 @@ namespace osu.Game.Online.Rooms [JsonProperty("channel_id")] public readonly Bindable ChannelId = new Bindable(); + [JsonProperty("current_playlist_item")] + [Cached] + public readonly Bindable CurrentPlaylistItem = new Bindable(); + + [JsonProperty("playlist_item_stats")] + [Cached] + public readonly Bindable PlaylistItemStats = new Bindable(); + [JsonProperty("difficulty_range")] public readonly Bindable DifficultyRange = new Bindable(); @@ -232,6 +240,19 @@ namespace osu.Game.Online.Rooms #endregion + [JsonObject(MemberSerialization.OptIn)] + public class RoomPlaylistItemStats + { + [JsonProperty("count_active")] + public int CountActive; + + [JsonProperty("count_total")] + public int CountTotal; + + [JsonProperty("ruleset_ids")] + public int[] RulesetIDs; + } + [JsonObject(MemberSerialization.OptIn)] public class RoomDifficultyRange { diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index d46ff12279..2faa46e622 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -23,6 +23,7 @@ namespace osu.Game.Screens.OnlinePlay.Components { InternalChild = sprite = CreateBackgroundSprite(); + CurrentPlaylistItem.BindValueChanged(_ => updateBeatmap()); Playlist.CollectionChanged += (_, __) => updateBeatmap(); updateBeatmap(); @@ -30,7 +31,7 @@ namespace osu.Game.Screens.OnlinePlay.Components private void updateBeatmap() { - sprite.Beatmap.Value = Playlist.GetCurrentItem()?.Beatmap; + sprite.Beatmap.Value = CurrentPlaylistItem.Value?.Beatmap ?? Playlist.GetCurrentItem()?.Beatmap; } protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index ef2c2df4a6..f387adfeb0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -1,13 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Specialized; using Humanizer; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { @@ -41,15 +42,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - Playlist.BindCollectionChanged(updateCount, true); + PlaylistItemStats.BindValueChanged(updateCount, true); } - private void updateCount(object sender, NotifyCollectionChangedEventArgs e) + private void updateCount(ValueChangedEvent valueChangedEvent) { + int activeItems = valueChangedEvent.NewValue.CountActive; + count.Clear(); - count.AddText(Playlist.Count.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + count.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); count.AddText(" "); - count.AddText("Beatmap".ToQuantity(Playlist.Count, ShowQuantityAs.None)); + count.AddText("Beatmap".ToQuantity(activeItems, ShowQuantityAs.None)); } } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index c833621fbc..3148b74c9c 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -32,6 +32,12 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(typeof(Room))] protected Bindable Type { get; private set; } + [Resolved(typeof(Room))] + protected Bindable CurrentPlaylistItem { get; private set; } + + [Resolved(typeof(Room))] + protected Bindable PlaylistItemStats { get; private set; } + [Resolved(typeof(Room))] protected BindableList Playlist { get; private set; } From b5348e04077910c65f497a88b5287d402dcf6427 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Feb 2022 19:05:32 +0900 Subject: [PATCH 04/20] Update ruleset filtering to use newly provided array return --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index 9f917c978c..a521306d7e 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { bool matchingFilter = true; - matchingFilter &= r.Room.Playlist.Count == 0 || criteria.Ruleset == null || r.Room.Playlist.Any(i => i.RulesetID == criteria.Ruleset.OnlineID); + matchingFilter &= criteria.Ruleset == null || r.Room.PlaylistItemStats.Value.RulesetIDs.Any(id => id == criteria.Ruleset.OnlineID); if (!string.IsNullOrEmpty(criteria.SearchString)) matchingFilter &= r.FilterTerms.Any(term => term.Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase)); From ffa5291b74b76c3083a4694a0a5961b631fba3d5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Feb 2022 19:37:36 +0900 Subject: [PATCH 05/20] Add fallback handling for item count to support different request types --- .../OnlinePlay/Lounge/Components/PlaylistCountPill.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index f387adfeb0..1aef41efbd 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -3,12 +3,10 @@ using Humanizer; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Online.Rooms; namespace osu.Game.Screens.OnlinePlay.Lounge.Components { @@ -42,12 +40,13 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - PlaylistItemStats.BindValueChanged(updateCount, true); + PlaylistItemStats.BindValueChanged(_ => updateCount(), true); + Playlist.BindCollectionChanged((_, __) => updateCount(), true); } - private void updateCount(ValueChangedEvent valueChangedEvent) + private void updateCount() { - int activeItems = valueChangedEvent.NewValue.CountActive; + int activeItems = PlaylistItemStats.Value?.CountActive ?? Playlist.Count; count.Clear(); count.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); From c7e9cf904bbd777bdc878f893fd37624a321e39f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 21 Feb 2022 19:38:26 +0900 Subject: [PATCH 06/20] Fix incorrect null check on now-bindable `DifficultyRange` --- .../Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index f27f5d6741..de56e6ff86 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -87,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay.Components StarDifficulty minDifficulty; StarDifficulty maxDifficulty; - if (room.DifficultyRange != null) + if (room.DifficultyRange.Value != null) { minDifficulty = new StarDifficulty(room.DifficultyRange.Value.Min, 0); maxDifficulty = new StarDifficulty(room.DifficultyRange.Value.Max, 0); From 2aa0364092819f821cd1be69c4d56e2150a1218d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Feb 2022 00:14:33 +0900 Subject: [PATCH 07/20] Fix null reference in tests during attempted ruleset filtering --- osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs index a521306d7e..f57bff13ca 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/RoomsContainer.cs @@ -77,7 +77,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { bool matchingFilter = true; - matchingFilter &= criteria.Ruleset == null || r.Room.PlaylistItemStats.Value.RulesetIDs.Any(id => id == criteria.Ruleset.OnlineID); + matchingFilter &= criteria.Ruleset == null || r.Room.PlaylistItemStats.Value?.RulesetIDs.Any(id => id == criteria.Ruleset.OnlineID) != false; if (!string.IsNullOrEmpty(criteria.SearchString)) matchingFilter &= r.FilterTerms.Any(term => term.Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase)); From 113153e6a34becbae3934939172511b2f8ee591a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Feb 2022 00:25:00 +0900 Subject: [PATCH 08/20] Fix remaining filter tests --- osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs index 8dfd969c51..7ade173c9c 100644 --- a/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs +++ b/osu.Game/Tests/Visual/OnlinePlay/TestRoomManager.cs @@ -43,6 +43,11 @@ namespace osu.Game.Tests.Visual.OnlinePlay if (ruleset != null) { + room.PlaylistItemStats.Value = new Room.RoomPlaylistItemStats + { + RulesetIDs = new[] { ruleset.OnlineID }, + }; + room.Playlist.Add(new PlaylistItem(new BeatmapInfo { Metadata = new BeatmapMetadata() }) { RulesetID = ruleset.OnlineID, From cde3d9c08ba8e3b9af8e8e6192c9febdfa306baa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Feb 2022 15:15:57 +0900 Subject: [PATCH 09/20] Change precedence order to favour playlist as a source for beatmap count --- .../OnlinePlay/Lounge/Components/PlaylistCountPill.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 1aef41efbd..e21439e931 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.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.Linq; using Humanizer; using osu.Framework.Allocation; using osu.Framework.Extensions.LocalisationExtensions; @@ -46,7 +47,11 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void updateCount() { - int activeItems = PlaylistItemStats.Value?.CountActive ?? Playlist.Count; + int activeItems = Playlist.Count > 0 || PlaylistItemStats.Value == null + // For now, use the playlist as the source of truth if it has any items. + // This allows the count to display correctly on the room screen (after joining a room). + ? Playlist.Count(i => !i.Expired) + : PlaylistItemStats.Value.CountActive; count.Clear(); count.AddText(activeItems.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); From f12044b03e97da4bbb883dd026c267f796345fe6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Feb 2022 15:31:08 +0900 Subject: [PATCH 10/20] Add mention of `PlaylistItem.Beatmap` being a placeholder in many cases --- osu.Game/Online/Rooms/PlaylistItem.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 33718f050b..f696362cbb 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -62,6 +62,10 @@ namespace osu.Game.Online.Rooms [JsonProperty("beatmap_id")] private int onlineBeatmapId => Beatmap.OnlineID; + /// + /// A beatmap representing this playlist item. + /// In many cases, this will *not* contain any usable information apart from OnlineID. + /// [JsonIgnore] public IBeatmapInfo Beatmap { get; set; } = null!; From 057fd6c352c354367ba5056dc7ed8c92976391de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Feb 2022 15:37:42 +0900 Subject: [PATCH 11/20] Add mention of `StarRatingRangeDisplay` fallback scenario being wrong for multiplayer --- .../Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index de56e6ff86..0b673006ef 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -94,6 +94,8 @@ namespace osu.Game.Screens.OnlinePlay.Components } else { + // In multiplayer rooms, the beatmaps of playlist items will not be populated to a point this can be correct. + // Either populating them via BeatmapLookupCache or polling the API for the room's DifficultyRange will be required. var orderedDifficulties = Playlist.Select(p => p.Beatmap).OrderBy(b => b.StarRating).ToArray(); minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0); From 61b3280de157b86d6b6ad61558902c491e617fc5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 22 Feb 2022 15:47:00 +0900 Subject: [PATCH 12/20] Add missing property copies in `Room.CopyFrom` implementation --- osu.Game/Online/Rooms/Room.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index d24cb7e74b..8ed37ad6b5 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -194,6 +194,8 @@ namespace osu.Game.Online.Rooms EndDate.Value = other.EndDate.Value; UserScore.Value = other.UserScore.Value; QueueMode.Value = other.QueueMode.Value; + DifficultyRange.Value = other.DifficultyRange.Value; + PlaylistItemStats.Value = other.PlaylistItemStats.Value; if (EndDate.Value != null && DateTimeOffset.Now >= EndDate.Value) Status.Value = new RoomStatusEnded(); From 2bea485af8da9bddd5fe404dd71e967a3c9b631b Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 23 Feb 2022 13:37:45 +0900 Subject: [PATCH 13/20] Fix currently playing text not showing in lounge --- osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 3148b74c9c..7d1feb0316 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -91,9 +91,15 @@ namespace osu.Game.Screens.OnlinePlay Playlist.BindCollectionChanged((_, __) => UpdateSelectedItem(), true); } - protected virtual void UpdateSelectedItem() - => SelectedItem.Value = RoomID.Value == null || subScreenSelectedItem == null - ? Playlist.GetCurrentItem() - : subScreenSelectedItem.Value; + protected void UpdateSelectedItem() + { + if (RoomID.Value == null || subScreenSelectedItem == null) + { + SelectedItem.Value = CurrentPlaylistItem.Value ?? Playlist.GetCurrentItem(); + return; + } + + SelectedItem.Value = subScreenSelectedItem.Value; + } } } From 71a012bea6021ad559da8ccce2f92413bff80c21 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 23 Feb 2022 13:42:47 +0900 Subject: [PATCH 14/20] Don't update count twice immediately MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartłomiej Dach --- .../Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index e21439e931..a6bbcd548d 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -41,7 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components { base.LoadComplete(); - PlaylistItemStats.BindValueChanged(_ => updateCount(), true); + PlaylistItemStats.BindValueChanged(_ => updateCount()); Playlist.BindCollectionChanged((_, __) => updateCount(), true); } From 28c9c5ab6a0ac889223a7f46ba6b16504cc9a3ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Feb 2022 17:05:46 +0900 Subject: [PATCH 15/20] Remove unnecessary `ShouldSerialize` rules in `Room` --- osu.Game/Online/Rooms/Room.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 8ed37ad6b5..7512d4fcf9 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -230,15 +230,9 @@ namespace osu.Game.Online.Rooms // They rely on being named exactly the same as the corresponding fields (casing included) and as such should NOT be renamed // unless the fields are also renamed. - [UsedImplicitly] - public bool ShouldSerializeRoomID() => false; - [UsedImplicitly] public bool ShouldSerializeHost() => false; - [UsedImplicitly] - public bool ShouldSerializeEndDate() => false; - #endregion [JsonObject(MemberSerialization.OptIn)] From f14a9af801c53552356f798a74e68fb6a18b4a3d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Feb 2022 17:06:40 +0900 Subject: [PATCH 16/20] Make `Room` opt-in rather than opt-out for json serialization --- osu.Game/Online/Rooms/Room.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 7512d4fcf9..5deedaaa6b 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -15,6 +15,7 @@ using osu.Game.Utils; namespace osu.Game.Online.Rooms { + [JsonObject(MemberSerialization.OptIn)] public class Room : IDeepCloneable { [Cached] @@ -49,7 +50,6 @@ namespace osu.Game.Online.Rooms public readonly Bindable DifficultyRange = new Bindable(); [Cached] - [JsonIgnore] public readonly Bindable Category = new Bindable(); // Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106) @@ -62,19 +62,15 @@ namespace osu.Game.Online.Rooms } [Cached] - [JsonIgnore] public readonly Bindable MaxAttempts = new Bindable(); [Cached] - [JsonIgnore] public readonly Bindable Status = new Bindable(new RoomStatusOpen()); [Cached] - [JsonIgnore] public readonly Bindable Availability = new Bindable(); [Cached] - [JsonIgnore] public readonly Bindable Type = new Bindable(); // Todo: osu-framework bug (https://github.com/ppy/osu-framework/issues/4106) @@ -87,7 +83,6 @@ namespace osu.Game.Online.Rooms } [Cached] - [JsonIgnore] public readonly Bindable QueueMode = new Bindable(); [JsonConverter(typeof(SnakeCaseStringEnumConverter))] @@ -99,7 +94,6 @@ namespace osu.Game.Online.Rooms } [Cached] - [JsonIgnore] public readonly Bindable MaxParticipants = new Bindable(); [Cached] @@ -124,7 +118,6 @@ namespace osu.Game.Online.Rooms public readonly Bindable Password = new Bindable(); [Cached] - [JsonIgnore] public readonly Bindable Duration = new Bindable(); [JsonProperty("duration")] From 43c83d2de1cd2cb861ba57f80dc903c837cb8181 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Feb 2022 17:07:29 +0900 Subject: [PATCH 17/20] Add note about why `RoomID` is nulled in `DeepClone` --- osu.Game/Online/Rooms/Room.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index 5deedaaa6b..b301c81921 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -162,6 +162,8 @@ namespace osu.Game.Online.Rooms var copy = new Room(); copy.CopyFrom(this); + + // ID must be unset as we use this as a marker for whether this is a client-side (not-yet-created) room or not. copy.RoomID.Value = null; return copy; From 53bbd0067545fbfc99e131de0a1bb6918980ed4e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 23 Feb 2022 17:12:38 +0900 Subject: [PATCH 18/20] Also make `APIUser` opt-in and remove the remaining serialization exclusion rule --- osu.Game/Online/API/Requests/Responses/APIUser.cs | 1 + osu.Game/Online/Rooms/Room.cs | 12 ------------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index 2b64e5de06..a53ac1cd9b 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -12,6 +12,7 @@ using osu.Game.Users; namespace osu.Game.Online.API.Requests.Responses { + [JsonObject(MemberSerialization.OptIn)] public class APIUser : IEquatable, IUser { [JsonProperty(@"id")] diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index b301c81921..c7f34905e2 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -3,7 +3,6 @@ using System; using System.Linq; -using JetBrains.Annotations; using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -219,17 +218,6 @@ namespace osu.Game.Online.Rooms Playlist.RemoveAll(i => i.Expired); } - #region Newtonsoft.Json implicit ShouldSerialize() methods - - // The properties in this region are used implicitly by Newtonsoft.Json to not serialise certain fields in some cases. - // They rely on being named exactly the same as the corresponding fields (casing included) and as such should NOT be renamed - // unless the fields are also renamed. - - [UsedImplicitly] - public bool ShouldSerializeHost() => false; - - #endregion - [JsonObject(MemberSerialization.OptIn)] public class RoomPlaylistItemStats { From c6d78b93257b172d044cc8932bd857555a82571d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Feb 2022 16:12:15 +0900 Subject: [PATCH 19/20] Fix several oversights in data linking causing drawable rooms not updating as expected --- osu.Game/Online/Rooms/Room.cs | 2 ++ .../Components/StarRatingRangeDisplay.cs | 16 ++++++---------- .../Screens/OnlinePlay/OnlinePlayComposite.cs | 3 +++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/Rooms/Room.cs b/osu.Game/Online/Rooms/Room.cs index c7f34905e2..a33150fe08 100644 --- a/osu.Game/Online/Rooms/Room.cs +++ b/osu.Game/Online/Rooms/Room.cs @@ -46,6 +46,7 @@ namespace osu.Game.Online.Rooms public readonly Bindable PlaylistItemStats = new Bindable(); [JsonProperty("difficulty_range")] + [Cached] public readonly Bindable DifficultyRange = new Bindable(); [Cached] @@ -190,6 +191,7 @@ namespace osu.Game.Online.Rooms QueueMode.Value = other.QueueMode.Value; DifficultyRange.Value = other.DifficultyRange.Value; PlaylistItemStats.Value = other.PlaylistItemStats.Value; + CurrentPlaylistItem.Value = other.CurrentPlaylistItem.Value; if (EndDate.Value != null && DateTimeOffset.Now >= EndDate.Value) Status.Value = new RoomStatusEnded(); diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 0b673006ef..7425e46bd3 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Specialized; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -12,7 +11,6 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Online.Rooms; using osuTK; namespace osu.Game.Screens.OnlinePlay.Components @@ -72,25 +70,23 @@ namespace osu.Game.Screens.OnlinePlay.Components }; } - [Resolved] - private Room room { get; set; } - protected override void LoadComplete() { base.LoadComplete(); - Playlist.BindCollectionChanged(updateRange, true); + DifficultyRange.BindValueChanged(_ => updateRange()); + Playlist.BindCollectionChanged((_, __) => updateRange(), true); } - private void updateRange(object sender, NotifyCollectionChangedEventArgs e) + private void updateRange() { StarDifficulty minDifficulty; StarDifficulty maxDifficulty; - if (room.DifficultyRange.Value != null) + if (DifficultyRange.Value != null) { - minDifficulty = new StarDifficulty(room.DifficultyRange.Value.Min, 0); - maxDifficulty = new StarDifficulty(room.DifficultyRange.Value.Max, 0); + minDifficulty = new StarDifficulty(DifficultyRange.Value.Min, 0); + maxDifficulty = new StarDifficulty(DifficultyRange.Value.Max, 0); } else { diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 7d1feb0316..984880dc3c 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -41,6 +41,9 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(typeof(Room))] protected BindableList Playlist { get; private set; } + [Resolved(typeof(Room))] + protected Bindable DifficultyRange { get; private set; } + [Resolved(typeof(Room))] protected Bindable Category { get; private set; } From bb1aa032bdd70c62abb6d6fe3833dacde8b32a71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 24 Feb 2022 16:20:40 +0900 Subject: [PATCH 20/20] Combine `SelectedItem` and `CurrentPlaylistItem` into same storage --- .../Lounge/Components/DrawableRoom.cs | 2 +- .../Match/MultiplayerMatchSettingsOverlay.cs | 4 ++-- .../Match/MultiplayerReadyButton.cs | 4 ++-- .../Match/Playlist/MultiplayerPlaylist.cs | 4 ++-- .../Screens/OnlinePlay/OnlinePlayComposite.cs | 22 ++++++++----------- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index a1a82c907a..5adce862a0 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -388,7 +388,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components protected override void LoadComplete() { base.LoadComplete(); - SelectedItem.BindValueChanged(onSelectedItemChanged, true); + CurrentPlaylistItem.BindValueChanged(onSelectedItemChanged, true); } private CancellationTokenSource beatmapLookupCancellation; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 7f1db733b3..be98a9d4e9 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -343,7 +343,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match base.LoadComplete(); drawablePlaylist.Items.BindTo(Playlist); - drawablePlaylist.SelectedItem.BindTo(SelectedItem); + drawablePlaylist.SelectedItem.BindTo(CurrentPlaylistItem); } protected override void Update() @@ -419,7 +419,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match if (text.StartsWith(not_found_prefix, StringComparison.Ordinal)) { ErrorText.Text = "The selected beatmap is not available online."; - SelectedItem.Value.MarkInvalid(); + CurrentPlaylistItem.Value.MarkInvalid(); } else { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs index 06959d942f..023af85f3b 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerReadyButton.cs @@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match { base.LoadComplete(); - SelectedItem.BindValueChanged(_ => updateState()); + CurrentPlaylistItem.BindValueChanged(_ => updateState()); } protected override void OnRoomUpdated() @@ -111,7 +111,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match bool enableButton = Room?.State == MultiplayerRoomState.Open - && SelectedItem.Value?.ID == Room.Settings.PlaylistItemId + && CurrentPlaylistItem.Value?.ID == Room.Settings.PlaylistItemId && !Room.Playlist.Single(i => i.ID == Room.Settings.PlaylistItemId).Expired && !operationInProgress.Value; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs index 7b90532cce..eeafebfec0 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerPlaylist.cs @@ -52,14 +52,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist queueList = new MultiplayerQueueList { RelativeSizeAxes = Axes.Both, - SelectedItem = { BindTarget = SelectedItem }, + SelectedItem = { BindTarget = CurrentPlaylistItem }, RequestEdit = item => RequestEdit?.Invoke(item) }, historyList = new MultiplayerHistoryList { RelativeSizeAxes = Axes.Both, Alpha = 0, - SelectedItem = { BindTarget = SelectedItem } + SelectedItem = { BindTarget = CurrentPlaylistItem } } } } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs index 984880dc3c..95d9b2af15 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs @@ -32,6 +32,10 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(typeof(Room))] protected Bindable Type { get; private set; } + /// + /// The currently selected item in the , or the current item from + /// if this is not within a . + /// [Resolved(typeof(Room))] protected Bindable CurrentPlaylistItem { get; private set; } @@ -80,12 +84,6 @@ namespace osu.Game.Screens.OnlinePlay [Resolved(CanBeNull = true)] private IBindable subScreenSelectedItem { get; set; } - /// - /// The currently selected item in the , or the current item from - /// if this is not within a . - /// - protected readonly Bindable SelectedItem = new Bindable(); - protected override void LoadComplete() { base.LoadComplete(); @@ -96,13 +94,11 @@ namespace osu.Game.Screens.OnlinePlay protected void UpdateSelectedItem() { - if (RoomID.Value == null || subScreenSelectedItem == null) - { - SelectedItem.Value = CurrentPlaylistItem.Value ?? Playlist.GetCurrentItem(); - return; - } - - SelectedItem.Value = subScreenSelectedItem.Value; + // null room ID means this is a room in the process of being created. + if (RoomID.Value == null) + CurrentPlaylistItem.Value = Playlist.GetCurrentItem(); + else if (subScreenSelectedItem != null) + CurrentPlaylistItem.Value = subScreenSelectedItem.Value; } } }