From 1d8e25311284f9c0bd5b96d75f9b1b107c7a4ecd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 16:44:39 +0900 Subject: [PATCH 01/17] Expose `PlaylistItem.APIBeatmap` for now --- osu.Game/Online/Rooms/PlaylistItem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 7fcce1514d..9a6269ecb1 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -43,7 +43,7 @@ namespace osu.Game.Online.Rooms public readonly BindableList RequiredMods = new BindableList(); [JsonProperty("beatmap")] - private APIBeatmap apiBeatmap { get; set; } + public APIBeatmap APIBeatmap { get; set; } private APIMod[] allowedModsBacking; @@ -71,7 +71,7 @@ namespace osu.Game.Online.Rooms public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) { - Beatmap.Value ??= apiBeatmap.ToBeatmapInfo(rulesets); + Beatmap.Value ??= APIBeatmap.ToBeatmapInfo(rulesets); Ruleset.Value ??= rulesets.GetRuleset(RulesetID); Ruleset rulesetInstance = Ruleset.Value.CreateInstance(); From 6fdeb66dc11552c46483486d57c0a508c6fe8cc0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 17:30:19 +0900 Subject: [PATCH 02/17] Use `APIBeatmap` instead of `BeatmapInfo` in playlist display classes where feasible --- .../Components/OnlinePlayBackgroundScreen.cs | 8 +++++-- .../Components/OnlinePlayBackgroundSprite.cs | 2 +- .../Components/PlaylistItemBackground.cs | 10 ++++----- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 22 ++++++++++--------- .../OnlinePlay/Match/DrawableMatchRoom.cs | 2 +- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index e2088c77d5..3e9b19cc17 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Shapes; using osu.Framework.Screens; +using osu.Game.Beatmaps; using osu.Game.Online.Rooms; using osuTK; using osuTK.Graphics; @@ -59,9 +60,12 @@ namespace osu.Game.Screens.OnlinePlay.Components { Schedule(() => { - var beatmap = playlistItem?.Beatmap.Value; + var beatmap = playlistItem?.APIBeatmap; - if (background?.BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers.Cover == beatmap?.BeatmapSet?.OnlineInfo?.Covers.Cover) + string? lastCover = (background?.Beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover; + string? newCover = beatmap?.BeatmapSet?.Covers.Cover; + + if (lastCover == newCover) return; cancellationSource?.Cancel(); diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index e2ba0b03b0..6df80a6d0a 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components private void updateBeatmap() { - sprite.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value; + sprite.Beatmap.Value = Playlist.FirstOrDefault()?.APIBeatmap; } protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs index 90ad6e0f6e..bf44ca6263 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs @@ -13,11 +13,11 @@ namespace osu.Game.Screens.OnlinePlay.Components { public class PlaylistItemBackground : Background { - public readonly BeatmapInfo? BeatmapInfo; + public readonly IBeatmapInfo? Beatmap; public PlaylistItemBackground(PlaylistItem? playlistItem) { - BeatmapInfo = playlistItem?.Beatmap.Value; + Beatmap = playlistItem?.APIBeatmap; } [BackgroundDependencyLoader] @@ -26,8 +26,8 @@ namespace osu.Game.Screens.OnlinePlay.Components Texture? texture = null; // prefer online cover where available. - if (BeatmapInfo?.BeatmapSet?.OnlineInfo?.Covers.Cover != null) - texture = textures.Get(BeatmapInfo.BeatmapSet.OnlineInfo.Covers.Cover); + if (Beatmap?.BeatmapSet is IBeatmapSetOnlineInfo online) + texture = textures.Get(online.Covers.Cover); Sprite.Texture = texture ?? beatmaps.DefaultBeatmap.Background; } @@ -38,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Components if (ReferenceEquals(this, other)) return true; return other.GetType() == GetType() - && ((PlaylistItemBackground)other).BeatmapInfo == BeatmapInfo; + && ((PlaylistItemBackground)other).Beatmap == Beatmap; } } } diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 826140944c..880f6d7195 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -96,6 +96,7 @@ namespace osu.Game.Screens.OnlinePlay } private ScheduledDelegate scheduledRefresh; + private PanelBackground panelBackground; private void scheduleRefresh() { @@ -105,23 +106,25 @@ namespace osu.Game.Screens.OnlinePlay private void refresh() { - difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; + difficultyIconContainer.Child = new DifficultyIcon(Item.APIBeatmap, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; + + panelBackground.Beatmap.Value = Item.APIBeatmap; beatmapText.Clear(); - beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text => + beatmapText.AddLink(Item.APIBeatmap.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.APIBeatmap.OnlineID.ToString(), null, text => { text.Truncate = true; }); authorText.Clear(); - if (Item.Beatmap?.Value?.Metadata?.Author != null) + if (Item.Beatmap.Value?.Metadata?.Author != null) { authorText.AddText("mapped by "); - authorText.AddUserLink(Item.Beatmap.Value?.Metadata.Author); + authorText.AddUserLink(Item.APIBeatmap?.BeatmapSet?.Author); } - bool hasExplicitContent = Item.Beatmap.Value.BeatmapSet.OnlineInfo?.HasExplicitContent == true; + bool hasExplicitContent = Item.Beatmap.Value?.BeatmapSet.OnlineInfo?.HasExplicitContent == true; explicitContentPill.Alpha = hasExplicitContent ? 1 : 0; modDisplay.Current.Value = requiredMods.ToArray(); @@ -145,10 +148,9 @@ namespace osu.Game.Screens.OnlinePlay Alpha = 0, AlwaysPresent = true }, - new PanelBackground + panelBackground = new PanelBackground { RelativeSizeAxes = Axes.Both, - Beatmap = { BindTarget = beatmap } }, new GridContainer { @@ -294,7 +296,7 @@ namespace osu.Game.Screens.OnlinePlay private const float width = 50; public PlaylistDownloadButton(PlaylistItem playlistItem) - : base(playlistItem.Beatmap.Value.BeatmapSet) + : base(playlistItem.APIBeatmap.BeatmapSet) { this.playlistItem = playlistItem; @@ -316,7 +318,7 @@ namespace osu.Game.Screens.OnlinePlay { case DownloadState.LocallyAvailable: // Perform a local query of the beatmap by beatmap checksum, and reset the state if not matching. - if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null) + if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.APIBeatmap.MD5Hash) == null) State.Value = DownloadState.NotDownloaded; else { @@ -337,7 +339,7 @@ namespace osu.Game.Screens.OnlinePlay // For now, this is the same implementation as in PanelBackground, but supports a beatmap info rather than a working beatmap private class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222) { - public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); public PanelBackground() { diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index e83403850f..affcf32bd6 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (editButton != null) host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); - SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap.Value, true); + SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.APIBeatmap, true); } protected override Drawable CreateBackground() => background = new BackgroundSprite(); From 3453160a8b9caa2e8fb7db835352443ebb52f849 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 12:30:19 +0900 Subject: [PATCH 03/17] Change `PlaylistItem.Beatmap` to be an `IBeatmapInfo` --- .../Online/Multiplayer/MultiplayerClient.cs | 15 +++++++++------ .../Multiplayer/OnlineMultiplayerClient.cs | 8 ++++---- osu.Game/Online/Rooms/MultiplayerScore.cs | 5 +++-- .../OnlinePlayBeatmapAvailabilityTracker.cs | 3 +++ osu.Game/Online/Rooms/PlaylistItem.cs | 6 +++--- .../Components/StarRatingRangeDisplay.cs | 6 +++--- .../OnlinePlay/DrawableRoomPlaylistItem.cs | 17 +++++++++-------- .../Lounge/Components/DrawableRoom.cs | 2 +- .../Screens/OnlinePlay/Match/RoomSubScreen.cs | 2 +- .../OnlinePlay/Playlists/PlaylistsPlayer.cs | 2 +- .../Playlists/PlaylistsResultsScreen.cs | 2 +- osu.Game/Screens/Play/SoloSpectator.cs | 14 +++++++++----- .../Visual/Multiplayer/TestMultiplayerClient.cs | 15 +++++++++++---- 13 files changed, 58 insertions(+), 39 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 0586e0ae60..b80253684e 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -17,6 +17,7 @@ using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; using osu.Game.Online.Rooms.RoomStatuses; using osu.Game.Rulesets; @@ -653,15 +654,17 @@ namespace osu.Game.Online.Multiplayer }), TaskContinuationOptions.OnlyOnRanToCompletion); }, cancellationToken); - private void updatePlaylist(MultiplayerRoomSettings settings, BeatmapSetInfo beatmapSet) + private void updatePlaylist(MultiplayerRoomSettings settings, APIBeatmapSet beatmapSet) { if (Room == null || !Room.Settings.Equals(settings)) return; Debug.Assert(APIRoom != null); - var beatmap = beatmapSet.Beatmaps.Single(b => b.OnlineBeatmapID == settings.BeatmapID); - beatmap.MD5Hash = settings.BeatmapChecksum; + var beatmap = beatmapSet.Beatmaps.Single(b => b.OnlineID == settings.BeatmapID); + + beatmap.Checksum = settings.BeatmapChecksum; + beatmap.BeatmapSet = beatmapSet; var ruleset = Rulesets.GetRuleset(settings.RulesetID).CreateInstance(); var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset)); @@ -694,12 +697,12 @@ namespace osu.Game.Online.Multiplayer } /// - /// Retrieves a from an online source. + /// Retrieves a from an online source. /// /// The beatmap set ID. /// A token to cancel the request. - /// The retrieval task. - protected abstract Task GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default); + /// The retrieval task. + protected abstract Task GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default); /// /// For the provided user ID, update whether the user is included in . diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs index 965674c2f2..a28abc78ca 100644 --- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs @@ -9,9 +9,9 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Rooms; namespace osu.Game.Online.Multiplayer @@ -148,9 +148,9 @@ namespace osu.Game.Online.Multiplayer return connection.InvokeAsync(nameof(IMultiplayerServer.StartMatch)); } - protected override Task GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default) + protected override Task GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default) { - var tcs = new TaskCompletionSource(); + var tcs = new TaskCompletionSource(); var req = new GetBeatmapSetRequest(beatmapId, BeatmapSetLookupType.BeatmapId); req.Success += res => @@ -161,7 +161,7 @@ namespace osu.Game.Online.Multiplayer return; } - tcs.SetResult(res.ToBeatmapSet(Rulesets)); + tcs.SetResult(res); }; req.Failure += e => tcs.SetException(e); diff --git a/osu.Game/Online/Rooms/MultiplayerScore.cs b/osu.Game/Online/Rooms/MultiplayerScore.cs index 7ec34e70d5..375e0b6b9f 100644 --- a/osu.Game/Online/Rooms/MultiplayerScore.cs +++ b/osu.Game/Online/Rooms/MultiplayerScore.cs @@ -7,6 +7,7 @@ using System.Linq; using JetBrains.Annotations; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; @@ -61,7 +62,7 @@ namespace osu.Game.Online.Rooms [CanBeNull] public MultiplayerScoresAround ScoresAround { get; set; } - public ScoreInfo CreateScoreInfo(PlaylistItem playlistItem) + public ScoreInfo CreateScoreInfo(PlaylistItem playlistItem, [NotNull] BeatmapInfo beatmap) { var rulesetInstance = playlistItem.Ruleset.Value.CreateInstance(); @@ -70,7 +71,7 @@ namespace osu.Game.Online.Rooms OnlineScoreID = ID, TotalScore = TotalScore, MaxCombo = MaxCombo, - BeatmapInfo = playlistItem.Beatmap.Value, + BeatmapInfo = beatmap, BeatmapInfoID = playlistItem.BeatmapID, Ruleset = playlistItem.Ruleset.Value, RulesetID = playlistItem.RulesetID, diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index a642e283f9..eb9ea608f7 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -52,6 +53,8 @@ namespace osu.Game.Online.Rooms downloadTracker?.RemoveAndDisposeImmediately(); + Debug.Assert(item.NewValue.Beatmap.Value.BeatmapSet != null); + downloadTracker = new BeatmapDownloadTracker(item.NewValue.Beatmap.Value.BeatmapSet); AddInternal(downloadTracker); diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 9a6269ecb1..13b609c9c9 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -31,7 +31,7 @@ namespace osu.Game.Online.Rooms public bool Expired { get; set; } [JsonIgnore] - public readonly Bindable Beatmap = new Bindable(); + public readonly Bindable Beatmap = new Bindable(); [JsonIgnore] public readonly Bindable Ruleset = new Bindable(); @@ -65,13 +65,13 @@ namespace osu.Game.Online.Rooms public PlaylistItem() { - Beatmap.BindValueChanged(beatmap => BeatmapID = beatmap.NewValue?.OnlineBeatmapID ?? 0); + Beatmap.BindValueChanged(beatmap => BeatmapID = beatmap.NewValue?.OnlineID ?? -1); Ruleset.BindValueChanged(ruleset => RulesetID = ruleset.NewValue?.ID ?? 0); } public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) { - Beatmap.Value ??= APIBeatmap.ToBeatmapInfo(rulesets); + Beatmap.Value ??= APIBeatmap; Ruleset.Value ??= rulesets.GetRuleset(RulesetID); Ruleset rulesetInstance = Ruleset.Value.CreateInstance(); diff --git a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs index 7b14acf924..fc029543bb 100644 --- a/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs +++ b/osu.Game/Screens/OnlinePlay/Components/StarRatingRangeDisplay.cs @@ -80,10 +80,10 @@ namespace osu.Game.Screens.OnlinePlay.Components private void updateRange(object sender, NotifyCollectionChangedEventArgs e) { - var orderedDifficulties = Playlist.Select(p => p.Beatmap.Value).OrderBy(b => b.StarDifficulty).ToArray(); + var orderedDifficulties = Playlist.Select(p => p.Beatmap.Value).OrderBy(b => b.StarRating).ToArray(); - StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarDifficulty : 0, 0); - StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarDifficulty : 0, 0); + StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0); + StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0); minDisplay.Current.Value = minDifficulty; maxDisplay.Current.Value = maxDifficulty; diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 880f6d7195..a7cce67fa3 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -27,6 +27,7 @@ using osu.Game.Overlays.BeatmapSet; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; +using osu.Game.Users; using osuTK; using osuTK.Graphics; @@ -45,7 +46,7 @@ namespace osu.Game.Screens.OnlinePlay private ExplicitContentBeatmapPill explicitContentPill; private ModDisplay modDisplay; - private readonly Bindable beatmap = new Bindable(); + private readonly Bindable beatmap = new Bindable(); private readonly Bindable ruleset = new Bindable(); private readonly BindableList requiredMods = new BindableList(); @@ -106,12 +107,12 @@ namespace osu.Game.Screens.OnlinePlay private void refresh() { - difficultyIconContainer.Child = new DifficultyIcon(Item.APIBeatmap, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; + difficultyIconContainer.Child = new DifficultyIcon(Item.Beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; - panelBackground.Beatmap.Value = Item.APIBeatmap; + panelBackground.Beatmap.Value = Item.Beatmap.Value; beatmapText.Clear(); - beatmapText.AddLink(Item.APIBeatmap.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.APIBeatmap.OnlineID.ToString(), null, text => + beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineID.ToString(), null, text => { text.Truncate = true; }); @@ -121,10 +122,10 @@ namespace osu.Game.Screens.OnlinePlay if (Item.Beatmap.Value?.Metadata?.Author != null) { authorText.AddText("mapped by "); - authorText.AddUserLink(Item.APIBeatmap?.BeatmapSet?.Author); + authorText.AddUserLink(new User { Username = Item.Beatmap.Value.Metadata.Author }); } - bool hasExplicitContent = Item.Beatmap.Value?.BeatmapSet.OnlineInfo?.HasExplicitContent == true; + bool hasExplicitContent = (Item.Beatmap.Value.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true; explicitContentPill.Alpha = hasExplicitContent ? 1 : 0; modDisplay.Current.Value = requiredMods.ToArray(); @@ -296,7 +297,7 @@ namespace osu.Game.Screens.OnlinePlay private const float width = 50; public PlaylistDownloadButton(PlaylistItem playlistItem) - : base(playlistItem.APIBeatmap.BeatmapSet) + : base(playlistItem.Beatmap.Value.BeatmapSet) { this.playlistItem = playlistItem; @@ -318,7 +319,7 @@ namespace osu.Game.Screens.OnlinePlay { case DownloadState.LocallyAvailable: // Perform a local query of the beatmap by beatmap checksum, and reset the state if not matching. - if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.APIBeatmap.MD5Hash) == null) + if (beatmapManager.QueryBeatmap(b => b.MD5Hash == playlistItem.Beatmap.Value.MD5Hash) == null) State.Value = DownloadState.NotDownloaded; else { diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs index 48202652f0..9920883078 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/DrawableRoom.cs @@ -384,7 +384,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components statusText.Text = "Currently playing "; beatmapText.AddLink(item.NewValue.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, - item.NewValue.Beatmap.Value.OnlineBeatmapID.ToString(), + item.NewValue.Beatmap.Value.OnlineID.ToString(), creationParameters: s => { s.Truncate = true; diff --git a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs index 2015a050bb..2cb29262e2 100644 --- a/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Match/RoomSubScreen.cs @@ -369,7 +369,7 @@ namespace osu.Game.Screens.OnlinePlay.Match var beatmap = SelectedItem.Value?.Beatmap.Value; // Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info - var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineBeatmapID); + var localBeatmap = beatmap == null ? null : beatmapManager.QueryBeatmap(b => b.OnlineBeatmapID == beatmap.OnlineID); Beatmap.Value = beatmapManager.GetWorkingBeatmap(localBeatmap); } diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs index fa4a4d5112..bdb5ff9bb2 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsPlayer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists private void load(IBindable ruleset) { // Sanity checks to ensure that PlaylistsPlayer matches the settings for the current PlaylistItem - if (Beatmap.Value.BeatmapInfo.OnlineBeatmapID != PlaylistItem.Beatmap.Value.OnlineBeatmapID) + if (Beatmap.Value.BeatmapInfo.OnlineBeatmapID != PlaylistItem.Beatmap.Value.OnlineID) throw new InvalidOperationException("Current Beatmap does not match PlaylistItem's Beatmap"); if (ruleset.Value.ID != PlaylistItem.Ruleset.Value.ID) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs index 89bc659f63..34698fccab 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsResultsScreen.cs @@ -169,7 +169,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists /// An optional pivot around which the scores were retrieved. private void performSuccessCallback([NotNull] Action> callback, [NotNull] List scores, [CanBeNull] MultiplayerScores pivot = null) { - var scoreInfos = scores.Select(s => s.CreateScoreInfo(playlistItem)).ToArray(); + var scoreInfos = scores.Select(s => s.CreateScoreInfo(playlistItem, Beatmap.Value.BeatmapInfo)).ToArray(); // Score panels calculate total score before displaying, which can take some time. In order to count that calculation as part of the loading spinner display duration, // calculate the total scores locally before invoking the success callback. diff --git a/osu.Game/Screens/Play/SoloSpectator.cs b/osu.Game/Screens/Play/SoloSpectator.cs index 83ea660092..6a73512f2d 100644 --- a/osu.Game/Screens/Play/SoloSpectator.cs +++ b/osu.Game/Screens/Play/SoloSpectator.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Spectator; using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Overlays.Settings; @@ -50,7 +51,7 @@ namespace osu.Game.Screens.Play private Container beatmapPanelContainer; private TriangleButton watchButton; private SettingsCheckbox automaticDownload; - private BeatmapSetInfo onlineBeatmap; + private APIBeatmapSet onlineBeatmap; /// /// The player's immediate online gameplay state. @@ -222,8 +223,8 @@ namespace osu.Game.Screens.Play onlineBeatmapRequest = new GetBeatmapSetRequest(state.BeatmapID.Value, BeatmapSetLookupType.BeatmapId); onlineBeatmapRequest.Success += res => Schedule(() => { - onlineBeatmap = res.ToBeatmapSet(rulesets); - beatmapPanelContainer.Child = new GridBeatmapPanel(res); + onlineBeatmap = res; + beatmapPanelContainer.Child = new GridBeatmapPanel(onlineBeatmap); checkForAutomaticDownload(); }); @@ -238,10 +239,13 @@ namespace osu.Game.Screens.Play if (!automaticDownload.Current.Value) return; - if (beatmaps.IsAvailableLocally(onlineBeatmap)) + // Used to interact with manager classes that don't support interface types. Will eventually be replaced. + var beatmapSetInfo = new BeatmapSetInfo { OnlineBeatmapSetID = onlineBeatmap.OnlineID }; + + if (beatmaps.IsAvailableLocally(beatmapSetInfo)) return; - beatmaps.Download(onlineBeatmap); + beatmaps.Download(beatmapSetInfo); } public override bool OnExiting(IScreen next) diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index c6634abe82..c690a621eb 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -13,6 +13,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; using osu.Game.Online.Rooms; @@ -265,18 +266,24 @@ namespace osu.Game.Tests.Visual.Multiplayer return ((IMultiplayerClient)this).LoadRequested(); } - protected override Task GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default) + protected override Task GetOnlineBeatmapSet(int beatmapId, CancellationToken cancellationToken = default) { Debug.Assert(Room != null); var apiRoom = roomManager.ServerSideRooms.Single(r => r.RoomID.Value == Room.RoomID); - var set = apiRoom.Playlist.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet - ?? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId)?.BeatmapSet; + IBeatmapSetInfo? set = apiRoom.Playlist.FirstOrDefault(p => p.BeatmapID == beatmapId)?.Beatmap.Value.BeatmapSet + ?? beatmaps.QueryBeatmap(b => b.OnlineBeatmapID == beatmapId)?.BeatmapSet; if (set == null) throw new InvalidOperationException("Beatmap not found."); - return Task.FromResult(set); + var apiSet = new APIBeatmapSet + { + OnlineID = set.OnlineID, + Beatmaps = set.Beatmaps.Select(b => new APIBeatmap { OnlineID = b.OnlineID }) + }; + + return Task.FromResult(apiSet); } private async Task changeMatchType(MatchType type) From 05f1fd4bc92711d46157cfd0002cb1ba44bae9e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 13:33:54 +0900 Subject: [PATCH 04/17] Remove unnecessary properties and parameters --- osu.Game/Online/Rooms/PlaylistItem.cs | 2 +- .../Screens/OnlinePlay/Components/RoomManager.cs | 2 +- osu.Game/Screens/Play/SoloSpectator.cs | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 13b609c9c9..108477987b 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -69,7 +69,7 @@ namespace osu.Game.Online.Rooms Ruleset.BindValueChanged(ruleset => RulesetID = ruleset.NewValue?.ID ?? 0); } - public void MapObjects(BeatmapManager beatmaps, RulesetStore rulesets) + public void MapObjects(RulesetStore rulesets) { Beatmap.Value ??= APIBeatmap; Ruleset.Value ??= rulesets.GetRuleset(RulesetID); diff --git a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs index abda9e897b..ddfdab18f7 100644 --- a/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs +++ b/osu.Game/Screens/OnlinePlay/Components/RoomManager.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.OnlinePlay.Components try { foreach (var pi in room.Playlist) - pi.MapObjects(beatmaps, rulesets); + pi.MapObjects(rulesets); var existing = rooms.FirstOrDefault(e => e.RoomID.Value == room.RoomID.Value); if (existing == null) diff --git a/osu.Game/Screens/Play/SoloSpectator.cs b/osu.Game/Screens/Play/SoloSpectator.cs index 6a73512f2d..ab324af705 100644 --- a/osu.Game/Screens/Play/SoloSpectator.cs +++ b/osu.Game/Screens/Play/SoloSpectator.cs @@ -51,7 +51,6 @@ namespace osu.Game.Screens.Play private Container beatmapPanelContainer; private TriangleButton watchButton; private SettingsCheckbox automaticDownload; - private APIBeatmapSet onlineBeatmap; /// /// The player's immediate online gameplay state. @@ -61,6 +60,8 @@ namespace osu.Game.Screens.Play private GetBeatmapSetRequest onlineBeatmapRequest; + private APIBeatmapSet beatmapSet; + public SoloSpectator([NotNull] User targetUser) : base(targetUser.Id) { @@ -221,10 +222,10 @@ namespace osu.Game.Screens.Play Debug.Assert(state.BeatmapID != null); onlineBeatmapRequest = new GetBeatmapSetRequest(state.BeatmapID.Value, BeatmapSetLookupType.BeatmapId); - onlineBeatmapRequest.Success += res => Schedule(() => + onlineBeatmapRequest.Success += beatmapSet => Schedule(() => { - onlineBeatmap = res; - beatmapPanelContainer.Child = new GridBeatmapPanel(onlineBeatmap); + this.beatmapSet = beatmapSet; + beatmapPanelContainer.Child = new GridBeatmapPanel(this.beatmapSet); checkForAutomaticDownload(); }); @@ -233,14 +234,14 @@ namespace osu.Game.Screens.Play private void checkForAutomaticDownload() { - if (onlineBeatmap == null) + if (beatmapSet == null) return; if (!automaticDownload.Current.Value) return; // Used to interact with manager classes that don't support interface types. Will eventually be replaced. - var beatmapSetInfo = new BeatmapSetInfo { OnlineBeatmapSetID = onlineBeatmap.OnlineID }; + var beatmapSetInfo = new BeatmapSetInfo { OnlineBeatmapSetID = beatmapSet.OnlineID }; if (beatmaps.IsAvailableLocally(beatmapSetInfo)) return; From 9f9c960fe38d16d66ae379b856ce0eb691d57b71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 13:36:32 +0900 Subject: [PATCH 05/17] Revert `PlaylistItem.APIBeatmap` to be private --- osu.Game/Online/Rooms/PlaylistItem.cs | 4 ++-- .../OnlinePlay/Components/OnlinePlayBackgroundScreen.cs | 4 +--- .../OnlinePlay/Components/OnlinePlayBackgroundSprite.cs | 2 +- .../Screens/OnlinePlay/Components/PlaylistItemBackground.cs | 2 +- osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index 108477987b..cb550281a9 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -43,7 +43,7 @@ namespace osu.Game.Online.Rooms public readonly BindableList RequiredMods = new BindableList(); [JsonProperty("beatmap")] - public APIBeatmap APIBeatmap { get; set; } + private APIBeatmap apiBeatmap { get; set; } private APIMod[] allowedModsBacking; @@ -71,7 +71,7 @@ namespace osu.Game.Online.Rooms public void MapObjects(RulesetStore rulesets) { - Beatmap.Value ??= APIBeatmap; + Beatmap.Value ??= apiBeatmap; Ruleset.Value ??= rulesets.GetRuleset(RulesetID); Ruleset rulesetInstance = Ruleset.Value.CreateInstance(); diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 3e9b19cc17..279a8e1a14 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -60,10 +60,8 @@ namespace osu.Game.Screens.OnlinePlay.Components { Schedule(() => { - var beatmap = playlistItem?.APIBeatmap; - string? lastCover = (background?.Beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover; - string? newCover = beatmap?.BeatmapSet?.Covers.Cover; + string? newCover = (background?.Beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover; if (lastCover == newCover) return; diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs index 6df80a6d0a..e2ba0b03b0 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs @@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components private void updateBeatmap() { - sprite.Beatmap.Value = Playlist.FirstOrDefault()?.APIBeatmap; + sprite.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value; } protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both }; diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs index bf44ca6263..f3e90aa396 100644 --- a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs +++ b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs @@ -17,7 +17,7 @@ namespace osu.Game.Screens.OnlinePlay.Components public PlaylistItemBackground(PlaylistItem? playlistItem) { - Beatmap = playlistItem?.APIBeatmap; + Beatmap = playlistItem?.Beatmap.Value; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs index affcf32bd6..e83403850f 100644 --- a/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs +++ b/osu.Game/Screens/OnlinePlay/Match/DrawableMatchRoom.cs @@ -62,7 +62,7 @@ namespace osu.Game.Screens.OnlinePlay.Match if (editButton != null) host.BindValueChanged(h => editButton.Alpha = h.NewValue?.Equals(api.LocalUser.Value) == true ? 1 : 0, true); - SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.APIBeatmap, true); + SelectedItem.BindValueChanged(item => background.Beatmap.Value = item.NewValue?.Beatmap.Value, true); } protected override Drawable CreateBackground() => background = new BackgroundSprite(); From 0ab50f1cc9af44d2accd2d0bf8d720f614cb5dd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 13:45:59 +0900 Subject: [PATCH 06/17] Add inline comment explaining why we are manually populating `beatmap.BeatmapSet` --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index b80253684e..6c4747ea54 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -645,12 +645,19 @@ namespace osu.Game.Online.Multiplayer RoomUpdated?.Invoke(); - GetOnlineBeatmapSet(settings.BeatmapID, cancellationToken).ContinueWith(set => Schedule(() => + GetOnlineBeatmapSet(settings.BeatmapID, cancellationToken).ContinueWith(task => Schedule(() => { if (cancellationToken.IsCancellationRequested) return; - updatePlaylist(settings, set.Result); + APIBeatmapSet beatmapSet = task.Result; + + // The incoming response is deserialised without circular reference handling currently. + // Because we require using metadata from this instance, populate the nested beatmaps' sets manually here. + foreach (var b in beatmapSet.Beatmaps) + b.BeatmapSet = beatmapSet; + + updatePlaylist(settings, beatmapSet); }), TaskContinuationOptions.OnlyOnRanToCompletion); }, cancellationToken); @@ -664,7 +671,6 @@ namespace osu.Game.Online.Multiplayer var beatmap = beatmapSet.Beatmaps.Single(b => b.OnlineID == settings.BeatmapID); beatmap.Checksum = settings.BeatmapChecksum; - beatmap.BeatmapSet = beatmapSet; var ruleset = Rulesets.GetRuleset(settings.RulesetID).CreateInstance(); var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset)); From 0df339d0b8a08a4042f50375428d3fe8d9af928a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 13:50:04 +0900 Subject: [PATCH 07/17] Fix incorrect invocation of download method in `SoloSpectator` --- osu.Game/Screens/Play/SoloSpectator.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/SoloSpectator.cs b/osu.Game/Screens/Play/SoloSpectator.cs index ab324af705..250738df39 100644 --- a/osu.Game/Screens/Play/SoloSpectator.cs +++ b/osu.Game/Screens/Play/SoloSpectator.cs @@ -240,13 +240,10 @@ namespace osu.Game.Screens.Play if (!automaticDownload.Current.Value) return; - // Used to interact with manager classes that don't support interface types. Will eventually be replaced. - var beatmapSetInfo = new BeatmapSetInfo { OnlineBeatmapSetID = beatmapSet.OnlineID }; - - if (beatmaps.IsAvailableLocally(beatmapSetInfo)) + if (beatmaps.IsAvailableLocally(new BeatmapSetInfo { OnlineBeatmapSetID = beatmapSet.OnlineID })) return; - beatmaps.Download(beatmapSetInfo); + beatmaps.Download(beatmapSet); } public override bool OnExiting(IScreen next) From a49366ff84328c44267c98b9b9d83d47170fb3b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 14:25:30 +0900 Subject: [PATCH 08/17] Remove nullability from `IBeatmapInfo.Metadata` --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- osu.Game/Beatmaps/BeatmapInfoExtensions.cs | 10 +++------- osu.Game/Beatmaps/IBeatmapInfo.cs | 2 +- .../Screens/OnlinePlay/DrawableRoomPlaylistItem.cs | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 9069ea4404..00a0c49298 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -186,7 +186,7 @@ namespace osu.Game.Beatmaps string IBeatmapInfo.DifficultyName => Version; [JsonIgnore] - IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata; + IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata ?? BeatmapSet.Metadata; [JsonIgnore] IBeatmapDifficultyInfo IBeatmapInfo.Difficulty => BaseDifficulty; diff --git a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs index 2d69015933..707b588063 100644 --- a/osu.Game/Beatmaps/BeatmapInfoExtensions.cs +++ b/osu.Game/Beatmaps/BeatmapInfoExtensions.cs @@ -11,14 +11,14 @@ namespace osu.Game.Beatmaps /// /// A user-presentable display title representing this beatmap. /// - public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) => $"{getClosestMetadata(beatmapInfo)} {getVersionString(beatmapInfo)}".Trim(); + public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) => $"{beatmapInfo.Metadata} {getVersionString(beatmapInfo)}".Trim(); /// /// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields. /// public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapInfo beatmapInfo, bool includeDifficultyName = true, bool includeCreator = true) { - var metadata = getClosestMetadata(beatmapInfo).GetDisplayTitleRomanisable(includeCreator); + var metadata = beatmapInfo.Metadata.GetDisplayTitleRomanisable(includeCreator); if (includeDifficultyName) { @@ -32,12 +32,8 @@ namespace osu.Game.Beatmaps public static string[] GetSearchableTerms(this IBeatmapInfo beatmapInfo) => new[] { beatmapInfo.DifficultyName - }.Concat(getClosestMetadata(beatmapInfo).GetSearchableTerms()).Where(s => !string.IsNullOrEmpty(s)).ToArray(); + }.Concat(beatmapInfo.Metadata.GetSearchableTerms()).Where(s => !string.IsNullOrEmpty(s)).ToArray(); private static string getVersionString(IBeatmapInfo beatmapInfo) => string.IsNullOrEmpty(beatmapInfo.DifficultyName) ? string.Empty : $"[{beatmapInfo.DifficultyName}]"; - - // temporary helper methods until we figure which metadata should be where. - private static IBeatmapMetadataInfo getClosestMetadata(IBeatmapInfo beatmapInfo) => - beatmapInfo.Metadata ?? beatmapInfo.BeatmapSet?.Metadata ?? new BeatmapMetadata(); } } diff --git a/osu.Game/Beatmaps/IBeatmapInfo.cs b/osu.Game/Beatmaps/IBeatmapInfo.cs index d206cfaaed..84ea6d3019 100644 --- a/osu.Game/Beatmaps/IBeatmapInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapInfo.cs @@ -21,7 +21,7 @@ namespace osu.Game.Beatmaps /// /// The metadata representing this beatmap. May be shared between multiple beatmaps. /// - IBeatmapMetadataInfo? Metadata { get; } + IBeatmapMetadataInfo Metadata { get; } /// /// The difficulty settings for this beatmap. diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index a7cce67fa3..0681ac23ad 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -119,7 +119,7 @@ namespace osu.Game.Screens.OnlinePlay authorText.Clear(); - if (Item.Beatmap.Value?.Metadata?.Author != null) + if (!string.IsNullOrEmpty(Item.Beatmap.Value?.Metadata.Author)) { authorText.AddText("mapped by "); authorText.AddUserLink(new User { Username = Item.Beatmap.Value.Metadata.Author }); From 84d36cbae723e753f67deefcf48b94ad7b6807d9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 15:22:32 +0900 Subject: [PATCH 09/17] Add fallback for cases where `BeatmapSet` may be null Seems to only happen in tests, but better safe than sorry. --- osu.Game/Beatmaps/BeatmapInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 00a0c49298..952e205aa0 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -186,7 +186,7 @@ namespace osu.Game.Beatmaps string IBeatmapInfo.DifficultyName => Version; [JsonIgnore] - IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata ?? BeatmapSet.Metadata; + IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata ?? BeatmapSet?.Metadata ?? new BeatmapMetadata(); [JsonIgnore] IBeatmapDifficultyInfo IBeatmapInfo.Difficulty => BaseDifficulty; From e3a9fbecfea26045e819fbeabb51ecb15d7ca343 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 16:42:22 +0900 Subject: [PATCH 10/17] Add method to create sample `APIBeatmap` (with `BeatmapSet` populated) --- osu.Game/Tests/Visual/OsuTestScene.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 90e85f7716..090a085f71 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -175,6 +175,28 @@ namespace osu.Game.Tests.Visual protected virtual IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset); + /// + /// Returns a sample API Beatmap with BeatmapSet populated. + /// + /// The ruleset to create the sample model using. + protected APIBeatmap CreateAPIBeatmap(RulesetInfo ruleset) + { + var beatmapSet = CreateAPIBeatmapSet(ruleset); + + // Avoid circular reference. + var beatmap = beatmapSet.Beatmaps.First(); + beatmapSet.Beatmaps = Array.Empty(); + + // Populate the set as that's generally what we expect from the API. + beatmap.BeatmapSet = beatmapSet; + + return beatmap; + } + + /// + /// Returns a sample API BeatmapSet with beatmaps populated. + /// + /// The ruleset to create the sample model using. protected APIBeatmapSet CreateAPIBeatmapSet(RulesetInfo ruleset) { var beatmap = CreateBeatmap(ruleset).BeatmapInfo; From 66f4516eee5b871ce82954bde74dad69319286dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 16:43:39 +0900 Subject: [PATCH 11/17] Allow creating sample API models without specifying a ruleset --- .../Multiplayer/TestSceneDrawableRoomPlaylist.cs | 16 +++++++++------- .../Online/TestSceneDirectDownloadButton.cs | 5 ++--- .../TestSceneUpdateableBeatmapSetCover.cs | 6 +++--- osu.Game/Tests/Visual/OsuTestScene.cs | 12 ++++++------ 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index f44b0c9716..5dfa055d7d 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Platform; @@ -202,7 +203,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDownloadButtonHiddenWhenBeatmapExists() { - var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; + var beatmap = CreateAPIBeatmapSet(); AddStep("import beatmap", () => manager.Import(beatmap.BeatmapSet).Wait()); @@ -223,11 +224,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDownloadButtonVisibleInitiallyWhenBeatmapDoesNotExist() { - var byOnlineId = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; - byOnlineId.BeatmapSet.OnlineBeatmapSetID = 1337; // Some random ID that does not exist locally. + var byOnlineId = CreateAPIBeatmapSet(); + byOnlineId.OnlineID = 1337; // Some random ID that does not exist locally. - var byChecksum = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; - byChecksum.MD5Hash = "1337"; // Some random checksum that does not exist locally. + var byChecksum = CreateAPIBeatmapSet(); + byChecksum.Beatmaps.ForEach(b => b.Checksum = "1337"); // Some random checksum that does not exist locally. createPlaylist(byOnlineId, byChecksum); @@ -237,8 +238,9 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestExplicitBeatmapItem() { - var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; - beatmap.BeatmapSet.OnlineInfo.HasExplicitContent = true; + var beatmap = CreateAPIBeatmapSet(); + + beatmap.HasExplicitContent = true; createPlaylist(beatmap); } diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs index f0cf88840a..3d828077c8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs @@ -9,7 +9,6 @@ using osu.Game.Beatmaps; using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.BeatmapListing.Panels; -using osu.Game.Rulesets.Osu; using osu.Game.Tests.Resources; using osuTK; @@ -110,7 +109,7 @@ namespace osu.Game.Tests.Visual.Online private IBeatmapSetInfo getDownloadableBeatmapSet() { - var apiBeatmapSet = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).BeatmapSetInfo.OnlineInfo; + var apiBeatmapSet = CreateAPIBeatmapSet(); apiBeatmapSet.HasVideo = true; apiBeatmapSet.HasStoryboard = true; @@ -120,7 +119,7 @@ namespace osu.Game.Tests.Visual.Online private IBeatmapSetInfo getUndownloadableBeatmapSet() { - var apiBeatmapSet = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).BeatmapSetInfo.OnlineInfo; + var apiBeatmapSet = CreateAPIBeatmapSet(); apiBeatmapSet.Artist = "test"; apiBeatmapSet.Title = "undownloadable"; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs index f67f6258cc..6896e7a67a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs @@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.UserInterface { AddStep("setup cover", () => Child = new UpdateableOnlineBeatmapSetCover(coverType) { - OnlineInfo = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet.OnlineInfo, + OnlineInfo = CreateAPIBeatmapSet(), RelativeSizeAxes = Axes.Both, Masking = true, }); @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("setup covers", () => { - BeatmapSetInfo setInfo = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet; + var beatmapSet = CreateAPIBeatmapSet(); FillFlowContainer fillFlow; @@ -99,7 +99,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("setup cover", () => Child = updateableCover = new TestUpdateableOnlineBeatmapSetCover { - OnlineInfo = CreateBeatmap(Ruleset.Value).BeatmapInfo.BeatmapSet.OnlineInfo, + OnlineInfo = CreateAPIBeatmapSet(), RelativeSizeAxes = Axes.Both, Masking = true, }); diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 090a085f71..e25cbaf467 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -178,10 +178,10 @@ namespace osu.Game.Tests.Visual /// /// Returns a sample API Beatmap with BeatmapSet populated. /// - /// The ruleset to create the sample model using. - protected APIBeatmap CreateAPIBeatmap(RulesetInfo ruleset) + /// The ruleset to create the sample model using. osu! ruleset will be used if not specified. + protected APIBeatmap CreateAPIBeatmap(RulesetInfo ruleset = null) { - var beatmapSet = CreateAPIBeatmapSet(ruleset); + var beatmapSet = CreateAPIBeatmapSet(ruleset ?? Ruleset.Value); // Avoid circular reference. var beatmap = beatmapSet.Beatmaps.First(); @@ -196,10 +196,10 @@ namespace osu.Game.Tests.Visual /// /// Returns a sample API BeatmapSet with beatmaps populated. /// - /// The ruleset to create the sample model using. - protected APIBeatmapSet CreateAPIBeatmapSet(RulesetInfo ruleset) + /// The ruleset to create the sample model using. osu! ruleset will be used if not specified. + protected APIBeatmapSet CreateAPIBeatmapSet(RulesetInfo ruleset = null) { - var beatmap = CreateBeatmap(ruleset).BeatmapInfo; + var beatmap = CreateBeatmap(ruleset ?? Ruleset.Value).BeatmapInfo; return new APIBeatmapSet { From 9c926e551446fa512b25eaf2e4f13c78491b17b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 15:42:12 +0900 Subject: [PATCH 12/17] Remove `BeatmapSetInfo.OnlineInfo` and all usages --- .../NonVisual/BeatmapSetInfoEqualityTest.cs | 4 +- .../TestSceneDrawableRoomPlaylist.cs | 18 +- .../SongSelect/TestSceneBeatmapDetails.cs | 157 ++++++------------ .../TestSceneUpdateableBeatmapSetCover.cs | 13 +- osu.Game/Beatmaps/BeatmapSetInfo.cs | 83 +-------- .../UpdateableBeatmapBackgroundSprite.cs | 5 - .../API/Requests/Responses/APIBeatmapSet.cs | 1 - osu.Game/Screens/Select/BeatmapDetails.cs | 19 ++- osu.Game/Tests/Beatmaps/TestBeatmap.cs | 10 -- osu.Game/Tests/Visual/OsuTestScene.cs | 24 +-- 10 files changed, 91 insertions(+), 243 deletions(-) diff --git a/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs b/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs index 42a3b4cf43..9ce7e0a0e0 100644 --- a/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs +++ b/osu.Game.Tests/NonVisual/BeatmapSetInfoEqualityTest.cs @@ -39,8 +39,8 @@ namespace osu.Game.Tests.NonVisual [Test] public void TestCheckNullID() { - var ourInfo = new BeatmapSetInfo { Status = BeatmapSetOnlineStatus.Loved }; - var otherInfo = new BeatmapSetInfo { Status = BeatmapSetOnlineStatus.Approved }; + var ourInfo = new BeatmapSetInfo { Hash = "1" }; + var otherInfo = new BeatmapSetInfo { Hash = "2" }; Assert.AreNotEqual(ourInfo, otherInfo); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 5dfa055d7d..afd48d5191 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -2,11 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Audio; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Platform; @@ -203,7 +203,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDownloadButtonHiddenWhenBeatmapExists() { - var beatmap = CreateAPIBeatmapSet(); + var beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo; AddStep("import beatmap", () => manager.Import(beatmap.BeatmapSet).Wait()); @@ -224,11 +224,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestDownloadButtonVisibleInitiallyWhenBeatmapDoesNotExist() { - var byOnlineId = CreateAPIBeatmapSet(); + var byOnlineId = CreateAPIBeatmap(); byOnlineId.OnlineID = 1337; // Some random ID that does not exist locally. - var byChecksum = CreateAPIBeatmapSet(); - byChecksum.Beatmaps.ForEach(b => b.Checksum = "1337"); // Some random checksum that does not exist locally. + var byChecksum = CreateAPIBeatmap(); + byChecksum.Checksum = "1337"; // Some random checksum that does not exist locally. createPlaylist(byOnlineId, byChecksum); @@ -238,9 +238,11 @@ namespace osu.Game.Tests.Visual.Multiplayer [Test] public void TestExplicitBeatmapItem() { - var beatmap = CreateAPIBeatmapSet(); + var beatmap = CreateAPIBeatmap(); - beatmap.HasExplicitContent = true; + Debug.Assert(beatmap.BeatmapSet != null); + + beatmap.BeatmapSet.HasExplicitContent = true; createPlaylist(beatmap); } @@ -312,7 +314,7 @@ namespace osu.Game.Tests.Visual.Multiplayer AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); } - private void createPlaylist(params BeatmapInfo[] beatmaps) + private void createPlaylist(params IBeatmapInfo[] beatmaps) { AddStep("create playlist", () => { diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index 9856b28b00..bd15c40271 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; -using osu.Game.Rulesets.Osu; using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect @@ -32,159 +31,112 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestAllMetrics() { - AddStep("all metrics", () => details.BeatmapInfo = new BeatmapInfo + AddStep("all metrics", () => details.BeatmapInfo = new APIBeatmap { - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new APIBeatmapSet - { - Ratings = Enumerable.Range(0, 11).ToArray(), - } - }, - Version = "All Metrics", - Metadata = new BeatmapMetadata + BeatmapSet = new APIBeatmapSet { Source = "osu!", Tags = "this beatmap has all the metrics", + Ratings = Enumerable.Range(0, 11).ToArray(), }, - BaseDifficulty = new BeatmapDifficulty + DifficultyName = "All Metrics", + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + StarRating = 5.3f, + FailTimes = new APIFailTimes { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, - StarDifficulty = 5.3f, - Ruleset = new OsuRuleset().RulesetInfo, - OnlineInfo = new APIBeatmap - { - FailTimes = new APIFailTimes - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } }); } [Test] public void TestAllMetricsExceptSource() { - AddStep("all except source", () => details.BeatmapInfo = new BeatmapInfo + AddStep("all except source", () => details.BeatmapInfo = new APIBeatmap { - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new APIBeatmapSet - { - Ratings = Enumerable.Range(0, 11).ToArray(), - } - }, - Version = "All Metrics", - Metadata = new BeatmapMetadata + BeatmapSet = new APIBeatmapSet { Tags = "this beatmap has all the metrics", + Ratings = Enumerable.Range(0, 11).ToArray(), }, - BaseDifficulty = new BeatmapDifficulty + DifficultyName = "All Metrics", + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + StarRating = 5.3f, + FailTimes = new APIFailTimes { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, - StarDifficulty = 5.3f, - Ruleset = new OsuRuleset().RulesetInfo, - OnlineInfo = new APIBeatmap - { - FailTimes = new APIFailTimes - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } }); } [Test] public void TestOnlyRatings() { - AddStep("ratings", () => details.BeatmapInfo = new BeatmapInfo + AddStep("ratings", () => details.BeatmapInfo = new APIBeatmap { - BeatmapSet = new BeatmapSetInfo - { - OnlineInfo = new APIBeatmapSet - { - Ratings = Enumerable.Range(0, 11).ToArray(), - } - }, - Version = "Only Ratings", - Metadata = new BeatmapMetadata + BeatmapSet = new APIBeatmapSet { + Ratings = Enumerable.Range(0, 11).ToArray(), Source = "osu!", Tags = "this beatmap has ratings metrics but not retries or fails", }, - Ruleset = new OsuRuleset().RulesetInfo, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 6, - DrainRate = 9, - OverallDifficulty = 6, - ApproachRate = 6, - }, - StarDifficulty = 4.8f, + DifficultyName = "Only Ratings", + CircleSize = 6, + DrainRate = 9, + OverallDifficulty = 6, + ApproachRate = 6, + StarRating = 4.8f, }); } [Test] public void TestOnlyFailsAndRetries() { - AddStep("fails retries", () => details.BeatmapInfo = new BeatmapInfo + AddStep("fails retries", () => details.BeatmapInfo = new APIBeatmap { - Version = "Only Retries and Fails", - Metadata = new BeatmapMetadata + DifficultyName = "Only Retries and Fails", + BeatmapSet = new APIBeatmapSet { Source = "osu!", Tags = "this beatmap has retries and fails but no ratings", }, - BaseDifficulty = new BeatmapDifficulty + CircleSize = 3.7f, + DrainRate = 6, + OverallDifficulty = 6, + ApproachRate = 7, + StarRating = 2.91f, + FailTimes = new APIFailTimes { - CircleSize = 3.7f, - DrainRate = 6, - OverallDifficulty = 6, - ApproachRate = 7, + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, - Ruleset = new OsuRuleset().RulesetInfo, - StarDifficulty = 2.91f, - OnlineInfo = new APIBeatmap - { - FailTimes = new APIFailTimes - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } }); } [Test] public void TestNoMetrics() { - AddStep("no metrics", () => details.BeatmapInfo = new BeatmapInfo + AddStep("no metrics", () => details.BeatmapInfo = new APIBeatmap { - Version = "No Metrics", - Metadata = new BeatmapMetadata + DifficultyName = "No Metrics", + BeatmapSet = new APIBeatmapSet { Source = "osu!", Tags = "this beatmap has no metrics", }, - Ruleset = new OsuRuleset().RulesetInfo, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 5, - DrainRate = 5, - OverallDifficulty = 5.5f, - ApproachRate = 6.5f, - }, - StarDifficulty = 1.97f, + CircleSize = 5, + DrainRate = 5, + OverallDifficulty = 5.5f, + ApproachRate = 6.5f, + StarRating = 1.97f, }); } @@ -197,10 +149,9 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestOnlineMetrics() { - AddStep("online ratings/retries/fails", () => details.BeatmapInfo = new BeatmapInfo + AddStep("online ratings/retries/fails", () => details.BeatmapInfo = new APIBeatmap { - OnlineBeatmapID = 162, - Ruleset = new OsuRuleset().RulesetInfo + OnlineID = 162, }); AddStep("set online", () => api.SetState(APIState.Online)); AddStep("set offline", () => api.SetState(APIState.Offline)); diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs index 6896e7a67a..7b6774a6b2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapSetCover.cs @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.UserInterface var cover = new UpdateableOnlineBeatmapSetCover(coverType) { - OnlineInfo = setInfo.OnlineInfo, + OnlineInfo = beatmapSet, Height = 100, Masking = true, }; @@ -117,7 +117,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("setup cover", () => Child = updateableCover = new TestUpdateableOnlineBeatmapSetCover(0) { - OnlineInfo = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg").OnlineInfo, + OnlineInfo = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1189904/covers/cover.jpg"), RelativeSizeAxes = Axes.Both, Masking = true, Alpha = 0.4f @@ -128,16 +128,13 @@ namespace osu.Game.Tests.Visual.UserInterface AddUntilStep("wait for fade complete", () => initialCover.Alpha == 1); AddStep("switch beatmap", - () => updateableCover.OnlineInfo = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg").OnlineInfo); + () => updateableCover.OnlineInfo = createBeatmapWithCover("https://assets.ppy.sh/beatmaps/1079428/covers/cover.jpg")); AddUntilStep("new cover loaded", () => updateableCover.ChildrenOfType().Except(new[] { initialCover }).Any()); } - private static BeatmapSetInfo createBeatmapWithCover(string coverUrl) => new BeatmapSetInfo + private static APIBeatmapSet createBeatmapWithCover(string coverUrl) => new APIBeatmapSet { - OnlineInfo = new APIBeatmapSet - { - Covers = new BeatmapSetOnlineCovers { Cover = coverUrl } - } + Covers = new BeatmapSetOnlineCovers { Cover = coverUrl } }; private class TestUpdateableOnlineBeatmapSetCover : UpdateableOnlineBeatmapSetCover diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 79cc8b70fb..638366c580 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -6,10 +6,8 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using JetBrains.Annotations; -using Newtonsoft.Json; using osu.Framework.Testing; using osu.Game.Database; -using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Beatmaps { @@ -32,13 +30,11 @@ namespace osu.Game.Beatmaps public List Beatmaps { get; set; } + public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; + [NotNull] public List Files { get; set; } = new List(); - // This field is temporary and only used by `APIBeatmapSet.ToBeatmapSet` (soon to be removed) and tests (to be updated to provide APIBeatmapSet instead). - [NotMapped] - public APIBeatmapSet OnlineInfo { get; set; } - /// /// The maximum star difficulty of all beatmaps in this set. /// @@ -100,80 +96,5 @@ namespace osu.Game.Beatmaps IEnumerable IBeatmapSetInfo.Files => Files; #endregion - - #region Delegation for IBeatmapSetOnlineInfo - - [NotMapped] - [JsonIgnore] - public DateTimeOffset Submitted => OnlineInfo.Submitted; - - [NotMapped] - [JsonIgnore] - public DateTimeOffset? Ranked => OnlineInfo.Ranked; - - [NotMapped] - [JsonIgnore] - public DateTimeOffset? LastUpdated => OnlineInfo.LastUpdated; - - [JsonIgnore] - public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; - - [NotMapped] - [JsonIgnore] - public bool HasExplicitContent => OnlineInfo.HasExplicitContent; - - [NotMapped] - [JsonIgnore] - public bool HasVideo => OnlineInfo.HasVideo; - - [NotMapped] - [JsonIgnore] - public bool HasStoryboard => OnlineInfo.HasStoryboard; - - [NotMapped] - [JsonIgnore] - public BeatmapSetOnlineCovers Covers => OnlineInfo.Covers; - - [NotMapped] - [JsonIgnore] - public string Preview => OnlineInfo.Preview; - - [NotMapped] - [JsonIgnore] - public double BPM => OnlineInfo.BPM; - - [NotMapped] - [JsonIgnore] - public int PlayCount => OnlineInfo.PlayCount; - - [NotMapped] - [JsonIgnore] - public int FavouriteCount => OnlineInfo.FavouriteCount; - - [NotMapped] - [JsonIgnore] - public bool HasFavourited => OnlineInfo.HasFavourited; - - [NotMapped] - [JsonIgnore] - public BeatmapSetOnlineAvailability Availability => OnlineInfo.Availability; - - [NotMapped] - [JsonIgnore] - public BeatmapSetOnlineGenre Genre => OnlineInfo.Genre; - - [NotMapped] - [JsonIgnore] - public BeatmapSetOnlineLanguage Language => OnlineInfo.Language; - - [NotMapped] - [JsonIgnore] - public int? TrackId => OnlineInfo?.TrackId; - - [NotMapped] - [JsonIgnore] - public int[] Ratings => OnlineInfo?.Ratings; - - #endregion } } diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 4100fe9586..636c568bd0 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -57,12 +57,7 @@ namespace osu.Game.Beatmaps.Drawables return new OnlineBeatmapSetCover(online, beatmapSetCoverType); if (model is BeatmapInfo localModel) - { - if (localModel.BeatmapSet?.OnlineInfo != null) - return new OnlineBeatmapSetCover(localModel.BeatmapSet.OnlineInfo, beatmapSetCoverType); - return new BeatmapBackgroundSprite(beatmaps.GetWorkingBeatmap(localModel)); - } return new BeatmapBackgroundSprite(beatmaps.DefaultBeatmap); } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index d8efa20b39..2b6c556c76 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -128,7 +128,6 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapSetID = OnlineID, Metadata = metadata, Status = Status, - OnlineInfo = this }; beatmapSet.Beatmaps = Beatmaps.Select(b => diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index ece16a8e57..6f215b9287 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -41,13 +41,13 @@ namespace osu.Game.Screens.Select [Resolved] private RulesetStore rulesets { get; set; } - private BeatmapInfo beatmapInfo; + private IBeatmapInfo beatmapInfo; private APIFailTimes failTimes; private int[] ratings; - public BeatmapInfo BeatmapInfo + public IBeatmapInfo BeatmapInfo { get => beatmapInfo; set @@ -56,8 +56,11 @@ namespace osu.Game.Screens.Select beatmapInfo = value; - failTimes = beatmapInfo?.OnlineInfo?.FailTimes; - ratings = beatmapInfo?.BeatmapSet?.OnlineInfo?.Ratings; + var onlineInfo = beatmapInfo as IBeatmapOnlineInfo; + var onlineSetInfo = beatmapInfo.BeatmapSet as IBeatmapSetOnlineInfo; + + failTimes = onlineInfo?.FailTimes; + ratings = onlineSetInfo?.Ratings; Scheduler.AddOnce(updateStatistics); } @@ -178,9 +181,9 @@ namespace osu.Game.Screens.Select private void updateStatistics() { advanced.BeatmapInfo = BeatmapInfo; - description.Text = BeatmapInfo?.Version; - source.Text = BeatmapInfo?.Metadata?.Source; - tags.Text = BeatmapInfo?.Metadata?.Tags; + description.Text = BeatmapInfo?.DifficultyName; + source.Text = BeatmapInfo?.Metadata.Source; + tags.Text = BeatmapInfo?.Metadata.Tags; // failTimes may have been previously fetched if (ratings != null && failTimes != null) @@ -190,7 +193,7 @@ namespace osu.Game.Screens.Select } // for now, let's early abort if an OnlineBeatmapID is not present (should have been populated at import time). - if (BeatmapInfo?.OnlineBeatmapID == null || api.State.Value == APIState.Offline) + if (BeatmapInfo == null || BeatmapInfo.OnlineID <= 0 || api.State.Value == APIState.Offline) { updateMetrics(); return; diff --git a/osu.Game/Tests/Beatmaps/TestBeatmap.cs b/osu.Game/Tests/Beatmaps/TestBeatmap.cs index caf83973c4..b9eda5c06e 100644 --- a/osu.Game/Tests/Beatmaps/TestBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestBeatmap.cs @@ -39,16 +39,6 @@ namespace osu.Game.Tests.Beatmaps BeatmapInfo.Length = 75000; BeatmapInfo.OnlineInfo = new APIBeatmap(); BeatmapInfo.OnlineBeatmapID = Interlocked.Increment(ref onlineBeatmapID); - BeatmapInfo.BeatmapSet.OnlineInfo = new APIBeatmapSet - { - Status = BeatmapSetOnlineStatus.Ranked, - Covers = new BeatmapSetOnlineCovers - { - Cover = "https://assets.ppy.sh/beatmaps/163112/covers/cover.jpg", - Card = "https://assets.ppy.sh/beatmaps/163112/covers/card.jpg", - List = "https://assets.ppy.sh/beatmaps/163112/covers/list.jpg" - } - }; } protected virtual Beatmap CreateBeatmap() => createTestBeatmap(); diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index e25cbaf467..153e2c487c 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -203,21 +203,14 @@ namespace osu.Game.Tests.Visual return new APIBeatmapSet { - Covers = beatmap.BeatmapSet.Covers, OnlineID = beatmap.BeatmapSet.OnlineID, - Status = beatmap.BeatmapSet.Status, - Preview = beatmap.BeatmapSet.Preview, - HasFavourited = beatmap.BeatmapSet.HasFavourited, - PlayCount = beatmap.BeatmapSet.PlayCount, - FavouriteCount = beatmap.BeatmapSet.FavouriteCount, - BPM = beatmap.BeatmapSet.BPM, - HasExplicitContent = beatmap.BeatmapSet.HasExplicitContent, - HasVideo = beatmap.BeatmapSet.HasVideo, - HasStoryboard = beatmap.BeatmapSet.HasStoryboard, - Submitted = beatmap.BeatmapSet.Submitted, - Ranked = beatmap.BeatmapSet.Ranked, - LastUpdated = beatmap.BeatmapSet.LastUpdated, - TrackId = beatmap.BeatmapSet.TrackId, + Status = BeatmapSetOnlineStatus.Ranked, + Covers = new BeatmapSetOnlineCovers + { + Cover = "https://assets.ppy.sh/beatmaps/163112/covers/cover.jpg", + Card = "https://assets.ppy.sh/beatmaps/163112/covers/card.jpg", + List = "https://assets.ppy.sh/beatmaps/163112/covers/list.jpg" + }, Title = beatmap.BeatmapSet.Metadata.Title, TitleUnicode = beatmap.BeatmapSet.Metadata.TitleUnicode, Artist = beatmap.BeatmapSet.Metadata.Artist, @@ -225,9 +218,6 @@ namespace osu.Game.Tests.Visual Author = beatmap.BeatmapSet.Metadata.Author, AuthorID = beatmap.BeatmapSet.Metadata.AuthorID, AuthorString = beatmap.BeatmapSet.Metadata.AuthorString, - Availability = beatmap.BeatmapSet.Availability, - Genre = beatmap.BeatmapSet.Genre, - Language = beatmap.BeatmapSet.Language, Source = beatmap.BeatmapSet.Metadata.Source, Tags = beatmap.BeatmapSet.Metadata.Tags, Beatmaps = new[] From 4b1b92cde6f0d9dfd9f116739fe2ea09094c67ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 17:03:26 +0900 Subject: [PATCH 13/17] Stop `BeatmapInfo` from implementing `IBeatmapOnlineInfo` and remove all usages --- osu.Game/Beatmaps/BeatmapInfo.cs | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 952e205aa0..01a819dead 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] [Serializable] - public class BeatmapInfo : IEquatable, IHasPrimaryKey, IBeatmapInfo, IBeatmapOnlineInfo + public class BeatmapInfo : IEquatable, IHasPrimaryKey, IBeatmapInfo { public int ID { get; set; } @@ -201,24 +201,5 @@ namespace osu.Game.Beatmaps double IBeatmapInfo.StarRating => StarDifficulty; #endregion - - #region Implementation of IBeatmapOnlineInfo - - [JsonIgnore] - public int CircleCount => OnlineInfo.CircleCount; - - [JsonIgnore] - public int SliderCount => OnlineInfo.SliderCount; - - [JsonIgnore] - public int PlayCount => OnlineInfo.PlayCount; - - [JsonIgnore] - public int PassCount => OnlineInfo.PassCount; - - [JsonIgnore] - public APIFailTimes FailTimes => OnlineInfo.FailTimes; - - #endregion } } From a5a7181915a041abb18c14e622e61f1ac4ac1d21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 15:35:32 +0900 Subject: [PATCH 14/17] Fix unintentionally broken background update logic --- .../OnlinePlay/Components/OnlinePlayBackgroundScreen.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index 279a8e1a14..ffc5c07d4e 100644 --- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs @@ -60,8 +60,10 @@ namespace osu.Game.Screens.OnlinePlay.Components { Schedule(() => { + var beatmap = playlistItem?.Beatmap.Value; + string? lastCover = (background?.Beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover; - string? newCover = (background?.Beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover; + string? newCover = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.Covers.Cover; if (lastCover == newCover) return; From baabe99f789aea701030531d538780efc7830dd0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 1 Nov 2021 15:38:45 +0900 Subject: [PATCH 15/17] Clean up `DirectDownloadButton` test scene --- .../Online/TestSceneDirectDownloadButton.cs | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs index 3d828077c8..8d7e0f9f0c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs @@ -40,14 +40,14 @@ namespace osu.Game.Tests.Visual.Online { AddUntilStep("ensure manager loaded", () => beatmaps != null); ensureSoleilyRemoved(); - createButtonWithBeatmap(createSoleily()); + createButtonWithBeatmap(CreateAPIBeatmapSet()); AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded); AddStep("import soleily", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport())); AddUntilStep("wait for beatmap import", () => beatmaps.GetAllUsableBeatmapSets().Any(b => b.OnlineBeatmapSetID == 241526)); AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable); - createButtonWithBeatmap(createSoleily()); + createButtonWithBeatmap(CreateAPIBeatmapSet()); AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable); ensureSoleilyRemoved(); AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded); @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert($"button {(enabled ? "enabled" : "disabled")}", () => downloadButton.DownloadEnabled == enabled); } - private void createButtonWithBeatmap(IBeatmapSetInfo beatmap) + private void createButtonWithBeatmap(APIBeatmapSet beatmap) { AddStep("create button", () => { @@ -94,20 +94,7 @@ namespace osu.Game.Tests.Visual.Online }); } - private IBeatmapSetInfo createSoleily() - { - return new APIBeatmapSet - { - OnlineID = 241526, - Availability = new BeatmapSetOnlineAvailability - { - DownloadDisabled = false, - ExternalLink = string.Empty, - }, - }; - } - - private IBeatmapSetInfo getDownloadableBeatmapSet() + private APIBeatmapSet getDownloadableBeatmapSet() { var apiBeatmapSet = CreateAPIBeatmapSet(); @@ -117,7 +104,7 @@ namespace osu.Game.Tests.Visual.Online return apiBeatmapSet; } - private IBeatmapSetInfo getUndownloadableBeatmapSet() + private APIBeatmapSet getUndownloadableBeatmapSet() { var apiBeatmapSet = CreateAPIBeatmapSet(); @@ -143,7 +130,7 @@ namespace osu.Game.Tests.Visual.Online public DownloadState DownloadState => State.Value; - public TestDownloadButton(IBeatmapSetInfo beatmapSet) + public TestDownloadButton(APIBeatmapSet beatmapSet) : base(beatmapSet) { } From 8f459e6ce83dc59bd955cbff99b51019b412607e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 16:44:05 +0900 Subject: [PATCH 16/17] Fix `APIBeatmapSet.Beatmaps` being `IEnumerable`, causing stupid issues --- osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs | 4 ++-- .../Beatmaps/TestSceneDifficultySpectrumDisplay.cs | 2 +- .../Visual/Online/TestSceneBeatmapRulesetSelector.cs | 10 +++------- .../Visual/Online/TestSceneBeatmapSetOverlay.cs | 6 +++--- .../Visual/Online/TestSceneBeatmapSetOverlayDetails.cs | 3 +-- osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs | 4 ++-- .../Online/API/Requests/Responses/APIBeatmapSet.cs | 2 +- .../Overlays/BeatmapListing/Panels/BeatmapPanel.cs | 2 +- .../Tests/Visual/Multiplayer/TestMultiplayerClient.cs | 2 +- 9 files changed, 15 insertions(+), 20 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index d1b21547dc..2aeb4ab4e2 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.Beatmaps HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), - Beatmaps = new List + Beatmaps = new[] { new APIBeatmap { @@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.Beatmaps HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), - Beatmaps = beatmaps, + Beatmaps = beatmaps.ToArray(), }; } diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs index 1f38b05879..4063fa1252 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneDifficultySpectrumDisplay.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Beatmaps { RulesetID = difficulty.rulesetId, StarRating = difficulty.stars - }).ToList() + }).ToArray() }; [Test] diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs index b880633559..90f3eb64e4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapRulesetSelector.cs @@ -1,7 +1,6 @@ // 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.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -37,7 +36,7 @@ namespace osu.Game.Tests.Visual.Online { selector.BeatmapSet = new APIBeatmapSet { - Beatmaps = enabledRulesets.Select(r => new APIBeatmap { RulesetID = r.OnlineID }).ToList() + Beatmaps = enabledRulesets.Select(r => new APIBeatmap { RulesetID = r.OnlineID }).ToArray() }; }); @@ -55,7 +54,7 @@ namespace osu.Game.Tests.Visual.Online { selector.BeatmapSet = new APIBeatmapSet { - Beatmaps = new List + Beatmaps = new[] { new APIBeatmap { @@ -71,10 +70,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestEmptyBeatmapSet() { - AddStep("load empty beatmapset", () => selector.BeatmapSet = new APIBeatmapSet - { - Beatmaps = new List() - }); + AddStep("load empty beatmapset", () => selector.BeatmapSet = new APIBeatmapSet()); AddAssert("no ruleset selected", () => selector.SelectedTab == null); AddAssert("all rulesets disabled", () => selector.TabContainer.TabItems.All(t => !t.Enabled.Value)); diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index bae9af1897..63ce057667 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -71,7 +71,7 @@ namespace osu.Game.Tests.Visual.Online Ratings = Enumerable.Range(0, 11).ToArray(), HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), - Beatmaps = new List + Beatmaps = new[] { new APIBeatmap { @@ -145,7 +145,7 @@ namespace osu.Game.Tests.Visual.Online var set = getBeatmapSet(); - set.Beatmaps = beatmaps; + set.Beatmaps = beatmaps.ToArray(); overlay.ShowBeatmapSet(set); }); @@ -211,7 +211,7 @@ namespace osu.Game.Tests.Visual.Online }); } - set.Beatmaps = beatmaps; + set.Beatmaps = beatmaps.ToArray(); return set; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index 491a2d5d90..9c0c67b1d8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -1,7 +1,6 @@ // 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.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -46,7 +45,7 @@ namespace osu.Game.Tests.Visual.Online static APIBeatmapSet createSet() => new APIBeatmapSet { - Beatmaps = new List + Beatmaps = new[] { new APIBeatmap { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs index 9a3d998966..a3c8935fa8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectPanel.cs @@ -90,7 +90,7 @@ namespace osu.Game.Tests.Visual.Online HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), - Beatmaps = new List + Beatmaps = new[] { new APIBeatmap { @@ -129,7 +129,7 @@ namespace osu.Game.Tests.Visual.Online HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), - Beatmaps = beatmaps, + Beatmaps = beatmaps.ToArray(), }; } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 2b6c556c76..c41271ad5c 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -119,7 +119,7 @@ namespace osu.Game.Online.API.Requests.Responses public string Tags { get; set; } = string.Empty; [JsonProperty(@"beatmaps")] - public IEnumerable Beatmaps { get; set; } = Array.Empty(); + public APIBeatmap[] Beatmaps { get; set; } = Array.Empty(); public virtual BeatmapSetInfo ToBeatmapSet(RulesetStore rulesets) { diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs index 2fd05f6742..34086c214f 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanel.cs @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels { var icons = new List(); - if (SetInfo.Beatmaps.Count() > maximum_difficulty_icons) + if (SetInfo.Beatmaps.Length > maximum_difficulty_icons) { foreach (var ruleset in SetInfo.Beatmaps.Select(b => b.Ruleset).Distinct()) icons.Add(new GroupedDifficultyIcon(SetInfo.Beatmaps.Where(b => b.RulesetID == ruleset.OnlineID).ToList(), ruleset, this is ListBeatmapPanel ? Color4.White : colours.Gray5)); diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index c690a621eb..70d907ba15 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -280,7 +280,7 @@ namespace osu.Game.Tests.Visual.Multiplayer var apiSet = new APIBeatmapSet { OnlineID = set.OnlineID, - Beatmaps = set.Beatmaps.Select(b => new APIBeatmap { OnlineID = b.OnlineID }) + Beatmaps = set.Beatmaps.Select(b => new APIBeatmap { OnlineID = b.OnlineID }).ToArray(), }; return Task.FromResult(apiSet); From 77be610b26c4dc5c6d99bbc5337f6aa2c0b675a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 4 Nov 2021 17:09:20 +0900 Subject: [PATCH 17/17] Revert "Clean up `DirectDownloadButton` test scene" This reverts commit baabe99f789aea701030531d538780efc7830dd0. --- .../Online/TestSceneDirectDownloadButton.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs index 8d7e0f9f0c..3d828077c8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectDownloadButton.cs @@ -40,14 +40,14 @@ namespace osu.Game.Tests.Visual.Online { AddUntilStep("ensure manager loaded", () => beatmaps != null); ensureSoleilyRemoved(); - createButtonWithBeatmap(CreateAPIBeatmapSet()); + createButtonWithBeatmap(createSoleily()); AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded); AddStep("import soleily", () => beatmaps.Import(TestResources.GetQuickTestBeatmapForImport())); AddUntilStep("wait for beatmap import", () => beatmaps.GetAllUsableBeatmapSets().Any(b => b.OnlineBeatmapSetID == 241526)); AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable); - createButtonWithBeatmap(CreateAPIBeatmapSet()); + createButtonWithBeatmap(createSoleily()); AddAssert("button state downloaded", () => downloadButton.DownloadState == DownloadState.LocallyAvailable); ensureSoleilyRemoved(); AddAssert("button state not downloaded", () => downloadButton.DownloadState == DownloadState.NotDownloaded); @@ -68,7 +68,7 @@ namespace osu.Game.Tests.Visual.Online AddAssert($"button {(enabled ? "enabled" : "disabled")}", () => downloadButton.DownloadEnabled == enabled); } - private void createButtonWithBeatmap(APIBeatmapSet beatmap) + private void createButtonWithBeatmap(IBeatmapSetInfo beatmap) { AddStep("create button", () => { @@ -94,7 +94,20 @@ namespace osu.Game.Tests.Visual.Online }); } - private APIBeatmapSet getDownloadableBeatmapSet() + private IBeatmapSetInfo createSoleily() + { + return new APIBeatmapSet + { + OnlineID = 241526, + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = false, + ExternalLink = string.Empty, + }, + }; + } + + private IBeatmapSetInfo getDownloadableBeatmapSet() { var apiBeatmapSet = CreateAPIBeatmapSet(); @@ -104,7 +117,7 @@ namespace osu.Game.Tests.Visual.Online return apiBeatmapSet; } - private APIBeatmapSet getUndownloadableBeatmapSet() + private IBeatmapSetInfo getUndownloadableBeatmapSet() { var apiBeatmapSet = CreateAPIBeatmapSet(); @@ -130,7 +143,7 @@ namespace osu.Game.Tests.Visual.Online public DownloadState DownloadState => State.Value; - public TestDownloadButton(APIBeatmapSet beatmapSet) + public TestDownloadButton(IBeatmapSetInfo beatmapSet) : base(beatmapSet) { }