-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ppy#29680 from peppy/multiplayer-spectator-auto-do…
…wnload Add automatic downloading support when spectating a multiplayer room
- Loading branch information
Showing
1 changed file
with
78 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,31 @@ | ||
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence. | ||
// See the LICENCE file in the repository root for full licence text. | ||
|
||
#nullable disable | ||
|
||
using System.Threading; | ||
using osu.Framework.Allocation; | ||
using osu.Framework.Bindables; | ||
using osu.Framework.Extensions; | ||
using osu.Framework.Graphics; | ||
using osu.Game.Beatmaps; | ||
using osu.Game.Configuration; | ||
using osu.Game.Database; | ||
using osu.Game.Graphics; | ||
using osu.Game.Graphics.UserInterfaceV2; | ||
using osu.Game.Online.Multiplayer; | ||
using osu.Game.Online.Rooms; | ||
using osuTK; | ||
|
||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match | ||
{ | ||
public partial class MultiplayerSpectateButton : MultiplayerRoomComposite | ||
{ | ||
[Resolved] | ||
private OngoingOperationTracker ongoingOperationTracker { get; set; } | ||
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!; | ||
|
||
[Resolved] | ||
private OsuColour colours { get; set; } | ||
private OsuColour colours { get; set; } = null!; | ||
|
||
private IBindable<bool> operationInProgress; | ||
private IBindable<bool> operationInProgress = null!; | ||
|
||
private readonly RoundedButton button; | ||
|
||
|
@@ -46,10 +50,20 @@ private void onClick() | |
} | ||
|
||
[BackgroundDependencyLoader] | ||
private void load() | ||
private void load(OsuConfigManager config) | ||
{ | ||
operationInProgress = ongoingOperationTracker.InProgress.GetBoundCopy(); | ||
operationInProgress.BindValueChanged(_ => updateState()); | ||
|
||
automaticallyDownload = config.GetBindable<bool>(OsuSetting.AutomaticallyDownloadMissingBeatmaps); | ||
automaticallyDownload.BindValueChanged(_ => Scheduler.AddOnce(checkForAutomaticDownload)); | ||
} | ||
|
||
protected override void LoadComplete() | ||
{ | ||
base.LoadComplete(); | ||
|
||
CurrentPlaylistItem.BindValueChanged(_ => Scheduler.AddOnce(checkForAutomaticDownload), true); | ||
} | ||
|
||
protected override void OnRoomUpdated() | ||
|
@@ -77,6 +91,64 @@ private void updateState() | |
button.Enabled.Value = Client.Room != null | ||
&& Client.Room.State != MultiplayerRoomState.Closed | ||
&& !operationInProgress.Value; | ||
|
||
Scheduler.AddOnce(checkForAutomaticDownload); | ||
} | ||
|
||
#region Automatic download handling | ||
|
||
[Resolved] | ||
private BeatmapLookupCache beatmapLookupCache { get; set; } = null!; | ||
|
||
[Resolved] | ||
private BeatmapModelDownloader beatmapDownloader { get; set; } = null!; | ||
|
||
[Resolved] | ||
private BeatmapManager beatmaps { get; set; } = null!; | ||
|
||
private Bindable<bool> automaticallyDownload = null!; | ||
|
||
private CancellationTokenSource? downloadCheckCancellation; | ||
|
||
private void checkForAutomaticDownload() | ||
{ | ||
PlaylistItem? currentItem = CurrentPlaylistItem.Value; | ||
|
||
downloadCheckCancellation?.Cancel(); | ||
|
||
if (currentItem == null) | ||
return; | ||
|
||
if (!automaticallyDownload.Value) | ||
return; | ||
|
||
// While we can support automatic downloads when not spectating, there are some usability concerns. | ||
// - In host rotate mode, this could potentially be unwanted by some users (even though they want automatic downloads everywhere else). | ||
// - When first joining a room, the expectation should be that the user is checking out the room, and they may not immediately want to download the selected beatmap. | ||
// | ||
// Rather than over-complicating this flow, let's only auto-download when spectating for the time being. | ||
// A potential path forward would be to have a local auto-download checkbox above the playlist item list area. | ||
if (Client.LocalUser?.State != MultiplayerUserState.Spectating) | ||
return; | ||
|
||
// In a perfect world we'd use BeatmapAvailability, but there's no event-driven flow for when a selection changes. | ||
// ie. if selection changes from "not downloaded" to another "not downloaded" we wouldn't get a value changed raised. | ||
beatmapLookupCache | ||
.GetBeatmapAsync(currentItem.Beatmap.OnlineID, (downloadCheckCancellation = new CancellationTokenSource()).Token) | ||
.ContinueWith(resolved => Schedule(() => | ||
{ | ||
var beatmapSet = resolved.GetResultSafely()?.BeatmapSet; | ||
if (beatmapSet == null) | ||
return; | ||
if (beatmaps.IsAvailableLocally(new BeatmapSetInfo { OnlineID = beatmapSet.OnlineID })) | ||
return; | ||
beatmapDownloader.Download(beatmapSet); | ||
})); | ||
} | ||
|
||
#endregion | ||
} | ||
} |