diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index c67cbade6a..51e77694a1 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -78,7 +78,7 @@ namespace osu.Game.Online.Rooms // handles changes to hash that didn't occur from the import process (ie. a user editing the beatmap in the editor, somehow). realmSubscription?.Dispose(); - realmSubscription = realm.RegisterForNotifications(r => filteredBeatmaps(), (items, changes, ___) => + realmSubscription = realm.RegisterForNotifications(r => QueryBeatmapForOnlinePlay(r, SelectedItem.Value.Beatmap.Value), (items, changes, ___) => { if (changes == null) return; @@ -108,12 +108,12 @@ namespace osu.Game.Online.Rooms break; case DownloadState.LocallyAvailable: - bool hashMatches = filteredBeatmaps().Any(); + bool available = QueryBeatmapForOnlinePlay(realm.Realm, SelectedItem.Value.Beatmap.Value).Any(); - availability.Value = hashMatches ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded(); + availability.Value = available ? BeatmapAvailability.LocallyAvailable() : BeatmapAvailability.NotDownloaded(); // only display a message to the user if a download seems to have just completed. - if (!hashMatches && downloadTracker.Progress.Value == 1) + if (!available && downloadTracker.Progress.Value == 1) Logger.Log("The imported beatmap set does not match the online version.", LoggingTarget.Runtime, LogLevel.Important); break; @@ -123,14 +123,15 @@ namespace osu.Game.Online.Rooms } } - private IQueryable filteredBeatmaps() + /// + /// Performs a query for a local matching a requested one for the purpose of online play. + /// + /// The realm to query from. + /// The requested beatmap. + /// A beatmap query. + public static IQueryable QueryBeatmapForOnlinePlay(Realm realm, IBeatmapInfo beatmap) { - int onlineId = SelectedItem.Value.Beatmap.Value.OnlineID; - string checksum = SelectedItem.Value.Beatmap.Value.MD5Hash; - - return realm.Realm - .All() - .Filter("OnlineID == $0 && MD5Hash == $1 && BeatmapSet.DeletePending == false", onlineId, checksum); + return realm.All().Filter("OnlineID == $0 && MD5Hash == $1 && BeatmapSet.DeletePending == false", beatmap.OnlineID, beatmap.MD5Hash); } protected override void Dispose(bool isDisposing) diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index dcf2a5a480..7674fac88e 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -25,7 +24,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online; using osu.Game.Online.Chat; -using osu.Game.Online.Multiplayer; using osu.Game.Online.Rooms; using osu.Game.Overlays.BeatmapSet; using osu.Game.Rulesets; @@ -68,8 +66,8 @@ namespace osu.Game.Screens.OnlinePlay private readonly DelayedLoadWrapper onScreenLoader = new DelayedLoadWrapper(Empty) { RelativeSizeAxes = Axes.Both }; private readonly IBindable valid = new Bindable(); - private readonly Bindable beatmap = new Bindable(); + private IBeatmapInfo beatmap; private IRulesetInfo ruleset; private Mod[] requiredMods; @@ -96,13 +94,12 @@ namespace osu.Game.Screens.OnlinePlay [Resolved] private UserLookupCache userLookupCache { get; set; } - [CanBeNull] - [Resolved(CanBeNull = true)] - private MultiplayerClient multiplayerClient { get; set; } - [Resolved] private BeatmapLookupCache beatmapLookupCache { get; set; } + [Resolved] + private RealmAccess realm { get; set; } + protected override bool ShouldBeConsideredForInput(Drawable child) => AllowReordering || AllowDeletion || !AllowSelection || SelectedItem.Value == Model; public DrawableRoomPlaylistItem(PlaylistItem item) @@ -110,7 +107,6 @@ namespace osu.Game.Screens.OnlinePlay { Item = item; - beatmap.BindTo(item.Beatmap); valid.BindTo(item.Valid); if (item.Expired) @@ -151,7 +147,6 @@ namespace osu.Game.Screens.OnlinePlay maskingContainer.BorderThickness = isCurrent ? 5 : 0; }, true); - beatmap.BindValueChanged(_ => Scheduler.AddOnce(refresh)); valid.BindValueChanged(_ => Scheduler.AddOnce(refresh)); onScreenLoader.DelayedLoadStarted += _ => @@ -166,19 +161,9 @@ namespace osu.Game.Screens.OnlinePlay Schedule(() => ownerAvatar.User = foundUser); } - if (Item.Beatmap.Value == null) - { - IBeatmapInfo foundBeatmap; + beatmap = await beatmapLookupCache.GetBeatmapAsync(Item.Beatmap.Value.OnlineID).ConfigureAwait(false); - if (multiplayerClient != null) - // This call can eventually go away (and use the else case below). - // Currently required only due to the method being overridden to provide special behaviour in tests. - foundBeatmap = await multiplayerClient.GetAPIBeatmap(Item.BeatmapID).ConfigureAwait(false); - else - foundBeatmap = await beatmapLookupCache.GetBeatmapAsync(Item.BeatmapID).ConfigureAwait(false); - - Schedule(() => Item.Beatmap.Value = foundBeatmap); - } + Scheduler.AddOnce(refresh); } catch (Exception e) { @@ -280,18 +265,18 @@ namespace osu.Game.Screens.OnlinePlay maskingContainer.BorderColour = colours.Red; } - if (Item.Beatmap.Value != null) - difficultyIconContainer.Child = new DifficultyIcon(Item.Beatmap.Value, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) }; + if (beatmap != null) + difficultyIconContainer.Child = new DifficultyIcon(beatmap, ruleset, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(icon_height) }; else difficultyIconContainer.Clear(); - panelBackground.Beatmap.Value = Item.Beatmap.Value; + panelBackground.Beatmap.Value = beatmap; beatmapText.Clear(); - if (Item.Beatmap.Value != null) + if (beatmap != null) { - beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineID.ToString(), null, text => + beatmapText.AddLink(beatmap.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, beatmap.OnlineID.ToString(), null, text => { text.Truncate = true; }); @@ -299,13 +284,13 @@ namespace osu.Game.Screens.OnlinePlay authorText.Clear(); - if (!string.IsNullOrEmpty(Item.Beatmap.Value?.Metadata.Author.Username)) + if (!string.IsNullOrEmpty(beatmap?.Metadata.Author.Username)) { authorText.AddText("mapped by "); - authorText.AddUserLink(Item.Beatmap.Value.Metadata.Author); + authorText.AddUserLink(beatmap.Metadata.Author); } - bool hasExplicitContent = (Item.Beatmap.Value?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true; + bool hasExplicitContent = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true; explicitContentPill.Alpha = hasExplicitContent ? 1 : 0; modDisplay.Current.Value = requiredMods.ToArray(); @@ -448,31 +433,34 @@ namespace osu.Game.Screens.OnlinePlay }; } - private IEnumerable createButtons() => new[] + private IEnumerable createButtons() { - showResultsButton = new GrayButton(FontAwesome.Solid.ChartPie) + return new[] { - Size = new Vector2(30, 30), - Action = () => RequestResults?.Invoke(Item), - Alpha = AllowShowingResults ? 1 : 0, - TooltipText = "View results" - }, - Item.Beatmap.Value == null ? Empty() : new PlaylistDownloadButton(Item), - editButton = new PlaylistEditButton - { - Size = new Vector2(30, 30), - Alpha = AllowEditing ? 1 : 0, - Action = () => RequestEdit?.Invoke(Item), - TooltipText = "Edit" - }, - removeButton = new PlaylistRemoveButton - { - Size = new Vector2(30, 30), - Alpha = AllowDeletion ? 1 : 0, - Action = () => RequestDeletion?.Invoke(Item), - TooltipText = "Remove from playlist" - }, - }; + showResultsButton = new GrayButton(FontAwesome.Solid.ChartPie) + { + Size = new Vector2(30, 30), + Action = () => RequestResults?.Invoke(Item), + Alpha = AllowShowingResults ? 1 : 0, + TooltipText = "View results" + }, + OnlinePlayBeatmapAvailabilityTracker.QueryBeatmapForOnlinePlay(realm.Realm, beatmap).Any() ? Empty() : new PlaylistDownloadButton(beatmap), + editButton = new PlaylistEditButton + { + Size = new Vector2(30, 30), + Alpha = AllowEditing ? 1 : 0, + Action = () => RequestEdit?.Invoke(Item), + TooltipText = "Edit" + }, + removeButton = new PlaylistRemoveButton + { + Size = new Vector2(30, 30), + Alpha = AllowDeletion ? 1 : 0, + Action = () => RequestDeletion?.Invoke(Item), + TooltipText = "Remove from playlist" + }, + }; + } protected override bool OnClick(ClickEvent e) { @@ -499,7 +487,7 @@ namespace osu.Game.Screens.OnlinePlay private sealed class PlaylistDownloadButton : BeatmapDownloadButton { - private readonly PlaylistItem playlistItem; + private readonly IBeatmapInfo beatmap; [Resolved] private BeatmapManager beatmapManager { get; set; } @@ -509,10 +497,10 @@ namespace osu.Game.Screens.OnlinePlay private const float width = 50; - public PlaylistDownloadButton(PlaylistItem playlistItem) - : base(playlistItem.Beatmap.Value.BeatmapSet) + public PlaylistDownloadButton(IBeatmapInfo beatmap) + : base(beatmap.BeatmapSet) { - this.playlistItem = playlistItem; + this.beatmap = beatmap; Size = new Vector2(width, 30); Alpha = 0; @@ -532,7 +520,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 == beatmap.MD5Hash) == null) State.Value = DownloadState.NotDownloaded; else {