From ed45efbb9e768377c06917619e25ee9a20186ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 21 Aug 2024 13:47:27 +0200 Subject: [PATCH] Preload song select instances in multiplayer / playlists Off the back of some very old feedback: https://www.reddit.com/r/osugame/comments/1dga6m5/comment/l8ot8qy/ Maybe resolves some of https://github.com/ppy/osu/issues/21952, too (definitely not all of it, state is still lost even with this). Mirrors the setup `MainMenu` does. It's not really possible to just keep one instance around since `ScreenStack` protests when trying to push an already-loaded screen. --- .../Match/MultiplayerMatchSettingsOverlay.cs | 7 +--- .../Multiplayer/MultiplayerMatchSongSelect.cs | 11 +++---- .../Multiplayer/MultiplayerMatchSubScreen.cs | 32 ++++++++++++++++++- .../OnlinePlay/OnlinePlaySongSelect.cs | 23 +++++++++---- .../Playlists/PlaylistsRoomSubScreen.cs | 26 ++++++++++++++- 5 files changed, 77 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs index 5446211ced3f..ab36366edc0d 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/MultiplayerMatchSettingsOverlay.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Screens; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; @@ -277,11 +276,7 @@ private void load(OverlayColourProvider colourProvider, OsuColour colours) RelativeSizeAxes = Axes.X, Height = 40, Text = "Select beatmap", - Action = () => - { - if (matchSubScreen.IsCurrentScreen()) - matchSubScreen.Push(new MultiplayerMatchSongSelect(matchSubScreen.Room)); - } + Action = () => matchSubScreen.OpenSongSelection() } } } diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs index 873a1b0d505e..6e9f141a3975 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs @@ -25,7 +25,6 @@ public partial class MultiplayerMatchSongSelect : OnlinePlaySongSelect private OngoingOperationTracker operationTracker { get; set; } = null!; private readonly IBindable operationInProgress = new Bindable(); - private readonly PlaylistItem? itemToEdit; private LoadingLayer loadingLayer = null!; private IDisposable? selectionOperation; @@ -34,11 +33,9 @@ public partial class MultiplayerMatchSongSelect : OnlinePlaySongSelect /// Construct a new instance of multiplayer song select. /// /// The room. - /// The item to be edited. May be null, in which case a new item will be added to the playlist. - public MultiplayerMatchSongSelect(Room room, PlaylistItem? itemToEdit = null) - : base(room, itemToEdit) + public MultiplayerMatchSongSelect(Room room) + : base(room) { - this.itemToEdit = itemToEdit; } [BackgroundDependencyLoader] @@ -79,7 +76,7 @@ protected override bool SelectItem(PlaylistItem item) var multiplayerItem = new MultiplayerPlaylistItem { - ID = itemToEdit?.ID ?? 0, + ID = PlaylistItem?.ID ?? 0, BeatmapID = item.Beatmap.OnlineID, BeatmapChecksum = item.Beatmap.MD5Hash, RulesetID = item.RulesetID, @@ -87,7 +84,7 @@ protected override bool SelectItem(PlaylistItem item) AllowedMods = item.AllowedMods.ToArray() }; - Task task = itemToEdit != null ? client.EditPlaylistItem(multiplayerItem) : client.AddPlaylistItem(multiplayerItem); + Task task = PlaylistItem != null ? client.EditPlaylistItem(multiplayerItem) : client.AddPlaylistItem(multiplayerItem); task.FireAndForget(onSuccess: () => { diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs index a37314de0ec7..c86172b1b7ae 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -51,6 +52,7 @@ public partial class MultiplayerMatchSubScreen : RoomSubScreen, IHandlePresentBe private OsuGame game { get; set; } private AddItemButton addItemButton; + private MultiplayerMatchSongSelect songSelect; public MultiplayerMatchSubScreen(Room room) : base(room) @@ -59,6 +61,28 @@ public MultiplayerMatchSubScreen(Room room) Activity.Value = new UserActivity.InLobby(room); } + [BackgroundDependencyLoader] + private void load() + { + preloadSongSelect(); + } + + private void preloadSongSelect() + { + LoadComponentAsync(songSelect = new MultiplayerMatchSongSelect(Room)); + } + + private MultiplayerMatchSongSelect consumeSongSelect([CanBeNull] PlaylistItem initialItem = null) + { + var s = songSelect; + Debug.Assert(s != null); + + songSelect = null; + + s.PlaylistItem = initialItem; + return s; + } + protected override void LoadComplete() { base.LoadComplete(); @@ -225,7 +249,7 @@ internal void OpenSongSelection(PlaylistItem itemToEdit = null) if (!this.IsCurrentScreen()) return; - this.Push(new MultiplayerMatchSongSelect(Room, itemToEdit)); + this.Push(consumeSongSelect(itemToEdit)); } protected override Drawable CreateFooter() => new MultiplayerMatchFooter(); @@ -244,6 +268,12 @@ protected override void UpdateMods() Mods.Value = client.LocalUser.Mods.Select(m => m.ToMod(rulesetInstance)).Concat(SelectedItem.Value.RequiredMods.Select(m => m.ToMod(rulesetInstance))).ToList(); } + public override void OnResuming(ScreenTransitionEvent e) + { + base.OnResuming(e); + preloadSongSelect(); + } + [Resolved(canBeNull: true)] private IDialogOverlay dialogOverlay { get; set; } diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs index a8dfece91694..fcc898e2b40d 100644 --- a/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs +++ b/osu.Game/Screens/OnlinePlay/OnlinePlaySongSelect.cs @@ -35,6 +35,12 @@ public abstract partial class OnlinePlaySongSelect : SongSelect, IOnlinePlaySubS [Resolved(typeof(Room), nameof(Room.Playlist))] protected BindableList Playlist { get; private set; } = null!; + /// + /// An optional initial to use for the initial beatmap/ruleset/mods. + /// If , the last in the room will be used. + /// + public PlaylistItem? PlaylistItem { get; set; } + [Resolved] private RulesetStore rulesets { get; set; } = null!; @@ -46,21 +52,19 @@ public abstract partial class OnlinePlaySongSelect : SongSelect, IOnlinePlaySubS protected readonly Bindable> FreeMods = new Bindable>(Array.Empty()); private readonly Room room; - private readonly PlaylistItem? initialItem; private readonly FreeModSelectOverlay freeModSelectOverlay; + private PlaylistItem? initialItem => PlaylistItem ?? room.Playlist.LastOrDefault(); + private IDisposable? freeModSelectOverlayRegistration; /// /// Creates a new . /// /// The room. - /// An optional initial to use for the initial beatmap/ruleset/mods. - /// If null, the last in the room will be used. - protected OnlinePlaySongSelect(Room room, PlaylistItem? initialItem = null) + protected OnlinePlaySongSelect(Room room) { this.room = room; - this.initialItem = initialItem ?? room.Playlist.LastOrDefault(); Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING }; @@ -82,6 +86,13 @@ protected override void LoadComplete() { base.LoadComplete(); + freeModSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(freeModSelectOverlay); + } + + public override void OnEntering(ScreenTransitionEvent e) + { + base.OnEntering(e); + if (initialItem != null) { // Prefer using a local databased beatmap lookup since OnlineId may be -1 for an invalid beatmap selection. @@ -115,8 +126,6 @@ protected override void LoadComplete() Mods.BindValueChanged(onModsChanged); Ruleset.BindValueChanged(onRulesetChanged); - - freeModSelectOverlayRegistration = OverlayManager?.RegisterBlockingOverlay(freeModSelectOverlay); } private void onModsChanged(ValueChangedEvent> mods) diff --git a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs index 3126bbf2ebc5..27dbfbd360b8 100644 --- a/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs +++ b/osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs @@ -35,6 +35,7 @@ public partial class PlaylistsRoomSubScreen : RoomSubScreen private MatchLeaderboard leaderboard; private SelectionPollingComponent selectionPollingComponent; + private PlaylistsSongSelect songSelect; private FillFlowContainer progressSection; @@ -52,6 +53,22 @@ private void load([CanBeNull] IdleTracker idleTracker) isIdle.BindTo(idleTracker.IsIdle); AddInternal(selectionPollingComponent = new SelectionPollingComponent(Room)); + preloadSongSelect(); + } + + private void preloadSongSelect() + { + if (songSelect == null) + LoadComponentAsync(songSelect = new PlaylistsSongSelect(Room)); + } + + private PlaylistsSongSelect consumeSongSelect() + { + var s = songSelect; + Debug.Assert(s != null); + + songSelect = null; + return s; } protected override void LoadComplete() @@ -234,7 +251,7 @@ protected override void LoadComplete() EditPlaylist = () => { if (this.IsCurrentScreen()) - this.Push(new PlaylistsSongSelect(Room)); + this.Push(consumeSongSelect()); }, }; @@ -248,5 +265,12 @@ private void updatePollingRate() { Exited = () => leaderboard.RefetchScores() }); + + public override void OnResuming(ScreenTransitionEvent e) + { + base.OnResuming(e); + + preloadSongSelect(); + } } }