Merge pull request #18708 from smoogipoo/multi-song-select-operation

Block multiplayer operations until beatmap selection completes
This commit is contained in:
Bartłomiej Dach
2022-06-18 12:42:04 +02:00
committed by GitHub
3 changed files with 60 additions and 22 deletions

View File

@ -1,11 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
@ -20,11 +20,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
public class MultiplayerMatchSongSelect : OnlinePlaySongSelect public class MultiplayerMatchSongSelect : OnlinePlaySongSelect
{ {
[Resolved] [Resolved]
private MultiplayerClient client { get; set; } private MultiplayerClient client { get; set; } = null!;
[Resolved]
private OngoingOperationTracker operationTracker { get; set; } = null!;
private readonly IBindable<bool> operationInProgress = new Bindable<bool>();
private readonly long? itemToEdit; private readonly long? itemToEdit;
private LoadingLayer loadingLayer; private LoadingLayer loadingLayer = null!;
private IDisposable? selectionOperation;
/// <summary> /// <summary>
/// Construct a new instance of multiplayer song select. /// Construct a new instance of multiplayer song select.
@ -33,7 +38,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
/// <param name="itemToEdit">The item to be edited. May be null, in which case a new item will be added to the playlist.</param> /// <param name="itemToEdit">The item to be edited. May be null, in which case a new item will be added to the playlist.</param>
/// <param name="beatmap">An optional initial beatmap selection to perform.</param> /// <param name="beatmap">An optional initial beatmap selection to perform.</param>
/// <param name="ruleset">An optional initial ruleset selection to perform.</param> /// <param name="ruleset">An optional initial ruleset selection to perform.</param>
public MultiplayerMatchSongSelect(Room room, long? itemToEdit = null, WorkingBeatmap beatmap = null, RulesetInfo ruleset = null) public MultiplayerMatchSongSelect(Room room, long? itemToEdit = null, WorkingBeatmap? beatmap = null, RulesetInfo? ruleset = null)
: base(room) : base(room)
{ {
this.itemToEdit = itemToEdit; this.itemToEdit = itemToEdit;
@ -54,13 +59,32 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
AddInternal(loadingLayer = new LoadingLayer(true)); AddInternal(loadingLayer = new LoadingLayer(true));
} }
protected override void SelectItem(PlaylistItem item) protected override void LoadComplete()
{ {
base.LoadComplete();
operationInProgress.BindTo(operationTracker.InProgress);
operationInProgress.BindValueChanged(_ => updateLoadingLayer(), true);
}
private void updateLoadingLayer()
{
if (operationInProgress.Value)
loadingLayer.Show();
else
loadingLayer.Hide();
}
protected override bool SelectItem(PlaylistItem item)
{
if (operationInProgress.Value)
return false;
// If the client is already in a room, update via the client. // If the client is already in a room, update via the client.
// Otherwise, update the playlist directly in preparation for it to be submitted to the API on match creation. // Otherwise, update the playlist directly in preparation for it to be submitted to the API on match creation.
if (client.Room != null) if (client.Room != null)
{ {
loadingLayer.Show(); selectionOperation = operationTracker.BeginOperation();
var multiplayerItem = new MultiplayerPlaylistItem var multiplayerItem = new MultiplayerPlaylistItem
{ {
@ -74,18 +98,25 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
Task task = itemToEdit != null ? client.EditPlaylistItem(multiplayerItem) : client.AddPlaylistItem(multiplayerItem); Task task = itemToEdit != null ? client.EditPlaylistItem(multiplayerItem) : client.AddPlaylistItem(multiplayerItem);
task.FireAndForget(onSuccess: () => Schedule(() => task.FireAndForget(onSuccess: () =>
{ {
loadingLayer.Hide(); selectionOperation.Dispose();
// If an error or server side trigger occurred this screen may have already exited by external means. Schedule(() =>
if (this.IsCurrentScreen()) {
this.Exit(); // If an error or server side trigger occurred this screen may have already exited by external means.
}), onError: _ => Schedule(() => if (this.IsCurrentScreen())
this.Exit();
});
}, onError: _ =>
{ {
loadingLayer.Hide(); selectionOperation.Dispose();
Carousel.AllowSelection = true;
})); Schedule(() =>
{
Carousel.AllowSelection = true;
});
});
} }
else else
{ {
@ -93,6 +124,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
Playlist.Add(item); Playlist.Add(item);
this.Exit(); this.Exit();
} }
return true;
} }
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea();

View File

@ -118,8 +118,6 @@ namespace osu.Game.Screens.OnlinePlay
protected sealed override bool OnStart() protected sealed override bool OnStart()
{ {
itemSelected = true;
var item = new PlaylistItem(Beatmap.Value.BeatmapInfo) var item = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{ {
RulesetID = Ruleset.Value.OnlineID, RulesetID = Ruleset.Value.OnlineID,
@ -127,15 +125,21 @@ namespace osu.Game.Screens.OnlinePlay
AllowedMods = FreeMods.Value.Select(m => new APIMod(m)).ToArray() AllowedMods = FreeMods.Value.Select(m => new APIMod(m)).ToArray()
}; };
SelectItem(item); if (SelectItem(item))
return true; {
itemSelected = true;
return true;
}
return false;
} }
/// <summary> /// <summary>
/// Invoked when the user has requested a selection of a beatmap. /// Invoked when the user has requested a selection of a beatmap.
/// </summary> /// </summary>
/// <param name="item">The resultant <see cref="PlaylistItem"/>. This item has not yet been added to the <see cref="Room"/>'s.</param> /// <param name="item">The resultant <see cref="PlaylistItem"/>. This item has not yet been added to the <see cref="Room"/>'s.</param>
protected abstract void SelectItem(PlaylistItem item); /// <returns><c>true</c> if a selection occurred.</returns>
protected abstract bool SelectItem(PlaylistItem item);
public override bool OnBackButton() public override bool OnBackButton()
{ {

View File

@ -24,7 +24,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
CreateNewItem = createNewItem CreateNewItem = createNewItem
}; };
protected override void SelectItem(PlaylistItem item) protected override bool SelectItem(PlaylistItem item)
{ {
switch (Playlist.Count) switch (Playlist.Count)
{ {
@ -39,6 +39,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
} }
this.Exit(); this.Exit();
return true;
} }
private void createNewItem() private void createNewItem()