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/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 9069ea4404..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; + IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata ?? BeatmapSet?.Metadata ?? new BeatmapMetadata(); [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/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index d8efa20b39..22cf6d25cd 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/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 0586e0ae60..6c4747ea54 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; @@ -644,24 +645,32 @@ 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); - 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; var ruleset = Rulesets.GetRuleset(settings.RulesetID).CreateInstance(); var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset)); @@ -694,12 +703,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 7fcce1514d..cb550281a9 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) + public void MapObjects(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/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/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundScreen.cs index e2088c77d5..ffc5c07d4e 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; @@ -61,7 +62,10 @@ namespace osu.Game.Screens.OnlinePlay.Components { var beatmap = playlistItem?.Beatmap.Value; - 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 as IBeatmapSetOnlineInfo)?.Covers.Cover; + + if (lastCover == newCover) return; cancellationSource?.Cancel(); diff --git a/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs b/osu.Game/Screens/OnlinePlay/Components/PlaylistItemBackground.cs index 90ad6e0f6e..f3e90aa396 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?.Beatmap.Value; } [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/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/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 826140944c..0681ac23ad 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(); @@ -96,6 +97,7 @@ namespace osu.Game.Screens.OnlinePlay } private ScheduledDelegate scheduledRefresh; + private PanelBackground panelBackground; private void scheduleRefresh() { @@ -105,23 +107,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.Beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; + + panelBackground.Beatmap.Value = Item.Beatmap.Value; beatmapText.Clear(); - beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text => + beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineID.ToString(), null, text => { text.Truncate = true; }); authorText.Clear(); - if (Item.Beatmap?.Value?.Metadata?.Author != null) + if (!string.IsNullOrEmpty(Item.Beatmap.Value?.Metadata.Author)) { authorText.AddText("mapped by "); - authorText.AddUserLink(Item.Beatmap.Value?.Metadata.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(); @@ -145,10 +149,9 @@ namespace osu.Game.Screens.OnlinePlay Alpha = 0, AlwaysPresent = true }, - new PanelBackground + panelBackground = new PanelBackground { RelativeSizeAxes = Axes.Both, - Beatmap = { BindTarget = beatmap } }, new GridContainer { @@ -337,7 +340,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/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..250738df39 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,6 @@ namespace osu.Game.Screens.Play private Container beatmapPanelContainer; private TriangleButton watchButton; private SettingsCheckbox automaticDownload; - private BeatmapSetInfo onlineBeatmap; /// /// The player's immediate online gameplay state. @@ -60,6 +60,8 @@ namespace osu.Game.Screens.Play private GetBeatmapSetRequest onlineBeatmapRequest; + private APIBeatmapSet beatmapSet; + public SoloSpectator([NotNull] User targetUser) : base(targetUser.Id) { @@ -220,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.ToBeatmapSet(rulesets); - beatmapPanelContainer.Child = new GridBeatmapPanel(res); + this.beatmapSet = beatmapSet; + beatmapPanelContainer.Child = new GridBeatmapPanel(this.beatmapSet); checkForAutomaticDownload(); }); @@ -232,16 +234,16 @@ namespace osu.Game.Screens.Play private void checkForAutomaticDownload() { - if (onlineBeatmap == null) + if (beatmapSet == null) return; if (!automaticDownload.Current.Value) return; - if (beatmaps.IsAvailableLocally(onlineBeatmap)) + if (beatmaps.IsAvailableLocally(new BeatmapSetInfo { OnlineBeatmapSetID = beatmapSet.OnlineID })) return; - beatmaps.Download(onlineBeatmap); + beatmaps.Download(beatmapSet); } 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..70d907ba15 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 }).ToArray(), + }; + + return Task.FromResult(apiSet); } private async Task changeMatchType(MatchType type)