mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 09:07:25 +08:00
Merge pull request #15879 from peppy/multiplayer-delayed-playlist-load-broken
Load playlist panels on demand to reduce initial load time when joining a room
This commit is contained in:
commit
86eacfdbd8
@ -163,7 +163,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
Debug.Assert(joinedRoom != null);
|
||||
|
||||
// Populate playlist items.
|
||||
var playlistItems = await Task.WhenAll(joinedRoom.Playlist.Select(createPlaylistItem)).ConfigureAwait(false);
|
||||
var playlistItems = await Task.WhenAll(joinedRoom.Playlist.Select(item => createPlaylistItem(item, item.ID == joinedRoom.Settings.PlaylistItemId))).ConfigureAwait(false);
|
||||
|
||||
// Populate users.
|
||||
Debug.Assert(joinedRoom.Users != null);
|
||||
@ -470,7 +470,32 @@ namespace osu.Game.Online.Multiplayer
|
||||
|
||||
Task IMultiplayerClient.SettingsChanged(MultiplayerRoomSettings newSettings)
|
||||
{
|
||||
Scheduler.Add(() => updateLocalRoomSettings(newSettings));
|
||||
Debug.Assert(APIRoom != null);
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
Scheduler.Add(() =>
|
||||
{
|
||||
// ensure the new selected item is populated immediately.
|
||||
var playlistItem = APIRoom.Playlist.Single(p => p.ID == newSettings.PlaylistItemId);
|
||||
|
||||
if (playlistItem != null)
|
||||
{
|
||||
GetAPIBeatmap(playlistItem.BeatmapID).ContinueWith(b =>
|
||||
{
|
||||
// Should be called outside of the `Scheduler` logic (and specifically accessing `Exception`) to suppress an exception from firing outwards.
|
||||
bool success = b.Exception == null;
|
||||
|
||||
Scheduler.Add(() =>
|
||||
{
|
||||
if (success)
|
||||
playlistItem.Beatmap.Value = b.Result;
|
||||
|
||||
updateLocalRoomSettings(newSettings);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@ -629,7 +654,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
if (Room == null)
|
||||
return;
|
||||
|
||||
var playlistItem = await createPlaylistItem(item).ConfigureAwait(false);
|
||||
var playlistItem = await createPlaylistItem(item, true).ConfigureAwait(false);
|
||||
|
||||
Scheduler.Add(() =>
|
||||
{
|
||||
@ -673,7 +698,7 @@ namespace osu.Game.Online.Multiplayer
|
||||
if (Room == null)
|
||||
return;
|
||||
|
||||
var playlistItem = await createPlaylistItem(item).ConfigureAwait(false);
|
||||
var playlistItem = await createPlaylistItem(item, true).ConfigureAwait(false);
|
||||
|
||||
Scheduler.Add(() =>
|
||||
{
|
||||
@ -728,10 +753,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
CurrentMatchPlayingItem.Value = APIRoom.Playlist.SingleOrDefault(p => p.ID == settings.PlaylistItemId);
|
||||
}
|
||||
|
||||
private async Task<PlaylistItem> createPlaylistItem(MultiplayerPlaylistItem item)
|
||||
private async Task<PlaylistItem> createPlaylistItem(MultiplayerPlaylistItem item, bool populateBeatmapImmediately)
|
||||
{
|
||||
var apiBeatmap = await GetAPIBeatmap(item.BeatmapID).ConfigureAwait(false);
|
||||
|
||||
var ruleset = Rulesets.GetRuleset(item.RulesetID);
|
||||
|
||||
Debug.Assert(ruleset != null);
|
||||
@ -741,8 +764,8 @@ namespace osu.Game.Online.Multiplayer
|
||||
var playlistItem = new PlaylistItem
|
||||
{
|
||||
ID = item.ID,
|
||||
BeatmapID = item.BeatmapID,
|
||||
OwnerID = item.OwnerID,
|
||||
Beatmap = { Value = apiBeatmap },
|
||||
Ruleset = { Value = ruleset },
|
||||
Expired = item.Expired,
|
||||
PlaylistOrder = item.PlaylistOrder,
|
||||
@ -752,6 +775,9 @@ namespace osu.Game.Online.Multiplayer
|
||||
playlistItem.RequiredMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance)));
|
||||
playlistItem.AllowedMods.AddRange(item.AllowedMods.Select(m => m.ToMod(rulesetInstance)));
|
||||
|
||||
if (populateBeatmapImmediately)
|
||||
playlistItem.Beatmap.Value = await GetAPIBeatmap(item.BeatmapID).ConfigureAwait(false);
|
||||
|
||||
return playlistItem;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
|
||||
private void updateRange(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
var orderedDifficulties = Playlist.Select(p => p.Beatmap.Value).OrderBy(b => b.StarRating).ToArray();
|
||||
var orderedDifficulties = Playlist.Where(p => p.Beatmap.Value != null).Select(p => p.Beatmap.Value).OrderBy(b => b.StarRating).ToArray();
|
||||
|
||||
StarDifficulty minDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[0].StarRating : 0, 0);
|
||||
StarDifficulty maxDifficulty = new StarDifficulty(orderedDifficulties.Length > 0 ? orderedDifficulties[^1].StarRating : 0, 0);
|
||||
|
@ -16,6 +16,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Database;
|
||||
@ -50,6 +51,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
private LinkFlowContainer authorText;
|
||||
private ExplicitContentBeatmapPill explicitContentPill;
|
||||
private ModDisplay modDisplay;
|
||||
private FillFlowContainer buttonsFlow;
|
||||
private UpdateableAvatar ownerAvatar;
|
||||
|
||||
private readonly IBindable<bool> valid = new Bindable<bool>();
|
||||
@ -66,10 +68,19 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
[Resolved]
|
||||
private UserLookupCache userLookupCache { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private BeatmapLookupCache beatmapLookupCache { get; set; }
|
||||
|
||||
private PanelBackground panelBackground;
|
||||
|
||||
private readonly DelayedLoadWrapper onScreenLoader = new DelayedLoadWrapper(Empty) { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
private readonly bool allowEdit;
|
||||
private readonly bool allowSelection;
|
||||
private readonly bool showItemOwner;
|
||||
|
||||
private FillFlowContainer mainFillFlow;
|
||||
|
||||
protected override bool ShouldBeConsideredForInput(Drawable child) => allowEdit || !allowSelection || SelectedItem.Value == Model;
|
||||
|
||||
public DrawableRoomPlaylistItem(PlaylistItem item, bool allowEdit, bool allowSelection, bool showItemOwner)
|
||||
@ -130,10 +141,33 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
valid.BindValueChanged(_ => Scheduler.AddOnce(refresh));
|
||||
requiredMods.CollectionChanged += (_, __) => Scheduler.AddOnce(refresh);
|
||||
|
||||
refresh();
|
||||
onScreenLoader.DelayedLoadStarted += _ =>
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (showItemOwner)
|
||||
{
|
||||
var foundUser = await userLookupCache.GetUserAsync(Item.OwnerID).ConfigureAwait(false);
|
||||
Schedule(() => ownerAvatar.User = foundUser);
|
||||
}
|
||||
|
||||
private PanelBackground panelBackground;
|
||||
if (Item.Beatmap.Value == null)
|
||||
{
|
||||
var foundBeatmap = await beatmapLookupCache.GetBeatmapAsync(Item.BeatmapID).ConfigureAwait(false);
|
||||
Schedule(() => Item.Beatmap.Value = foundBeatmap);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log($"Error while populating playlist item {e}");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
@ -143,22 +177,22 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
maskingContainer.BorderColour = colours.Red;
|
||||
}
|
||||
|
||||
if (showItemOwner)
|
||||
{
|
||||
ownerAvatar.Show();
|
||||
userLookupCache.GetUserAsync(Item.OwnerID)
|
||||
.ContinueWith(u => Schedule(() => ownerAvatar.User = u.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
}
|
||||
|
||||
if (Item.Beatmap.Value != null)
|
||||
difficultyIconContainer.Child = new DifficultyIcon(Item.Beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(ICON_HEIGHT) };
|
||||
else
|
||||
difficultyIconContainer.Clear();
|
||||
|
||||
panelBackground.Beatmap.Value = Item.Beatmap.Value;
|
||||
|
||||
beatmapText.Clear();
|
||||
|
||||
if (Item.Beatmap.Value != null)
|
||||
{
|
||||
beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineID.ToString(), null, text =>
|
||||
{
|
||||
text.Truncate = true;
|
||||
});
|
||||
}
|
||||
|
||||
authorText.Clear();
|
||||
|
||||
@ -168,10 +202,16 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
authorText.AddUserLink(Item.Beatmap.Value.Metadata.Author);
|
||||
}
|
||||
|
||||
bool hasExplicitContent = (Item.Beatmap.Value.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true;
|
||||
bool hasExplicitContent = (Item.Beatmap.Value?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true;
|
||||
explicitContentPill.Alpha = hasExplicitContent ? 1 : 0;
|
||||
|
||||
modDisplay.Current.Value = requiredMods.ToArray();
|
||||
|
||||
buttonsFlow.Clear();
|
||||
buttonsFlow.ChildrenEnumerable = CreateButtons();
|
||||
|
||||
difficultyIconContainer.FadeInFromZero(500, Easing.OutQuint);
|
||||
mainFillFlow.FadeInFromZero(500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override Drawable CreateContent()
|
||||
@ -192,6 +232,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
},
|
||||
onScreenLoader,
|
||||
panelBackground = new PanelBackground
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -217,7 +258,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Left = 8, Right = 8 },
|
||||
},
|
||||
new FillFlowContainer
|
||||
mainFillFlow = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
@ -273,7 +314,7 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
}
|
||||
}
|
||||
},
|
||||
new FillFlowContainer
|
||||
buttonsFlow = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
@ -305,9 +346,9 @@ namespace osu.Game.Screens.OnlinePlay
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<Drawable> CreateButtons() =>
|
||||
new Drawable[]
|
||||
new[]
|
||||
{
|
||||
new PlaylistDownloadButton(Item),
|
||||
Item.Beatmap.Value == null ? Empty() : new PlaylistDownloadButton(Item),
|
||||
new PlaylistRemoveButton
|
||||
{
|
||||
Size = new Vector2(30, 30),
|
||||
|
@ -4,9 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
@ -89,15 +87,6 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
||||
getRoomRequest.TriggerSuccess(createResponseRoom(ServerSideRooms.Single(r => r.RoomID.Value == getRoomRequest.RoomId), true));
|
||||
return true;
|
||||
|
||||
case GetBeatmapSetRequest getBeatmapSetRequest:
|
||||
var onlineReq = new GetBeatmapSetRequest(getBeatmapSetRequest.ID, getBeatmapSetRequest.Type);
|
||||
onlineReq.Success += res => getBeatmapSetRequest.TriggerSuccess(res);
|
||||
onlineReq.Failure += e => getBeatmapSetRequest.TriggerFailure(e);
|
||||
|
||||
// Get the online API from the game's dependencies.
|
||||
game.Dependencies.Get<IAPIProvider>().Queue(onlineReq);
|
||||
return true;
|
||||
|
||||
case CreateRoomScoreRequest createRoomScoreRequest:
|
||||
createRoomScoreRequest.TriggerSuccess(new APIScoreToken { ID = 1 });
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user