1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-13 20:33:35 +08:00

Merge pull request #32460 from smoogipoo/refactor-match-footer

Refactor multiplayer match footer
This commit is contained in:
Bartłomiej Dach
2025-03-24 12:14:57 +01:00
committed by GitHub
Unverified
8 changed files with 25 additions and 56 deletions
@@ -101,15 +101,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
[SetUpSteps]
public void SetUpSteps()
{
PlaylistItem item = null!;
AddStep("reset state", () =>
{
multiplayerClient.Invocations.Clear();
beatmapAvailability.Value = BeatmapAvailability.LocallyAvailable();
item = new PlaylistItem(Beatmap.Value.BeatmapInfo)
PlaylistItem item = new PlaylistItem(Beatmap.Value.BeatmapInfo)
{
RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID
};
@@ -139,8 +137,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(250, 50),
SelectedItem = new Bindable<PlaylistItem?>(item)
Size = new Vector2(250, 50)
};
});
}
@@ -1,11 +1,9 @@
// 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.
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
namespace osu.Game.Tests.Visual.Multiplayer
@@ -29,10 +27,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.X,
Height = 50,
Child = new MultiplayerMatchFooter
{
SelectedItem = new Bindable<PlaylistItem?>()
}
Child = new MultiplayerMatchFooter()
}
};
});
@@ -5,7 +5,6 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -71,15 +70,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200, 50),
SelectedItem = new Bindable<PlaylistItem?>(room.Playlist.First())
Size = new Vector2(200, 50)
},
startControl = new MatchStartControl
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200, 50),
SelectedItem = new Bindable<PlaylistItem?>(room.Playlist.First())
Size = new Vector2(200, 50)
}
}
}
@@ -81,6 +81,18 @@ namespace osu.Game.Online.Multiplayer
Playlist = room.Playlist.Select(p => new MultiplayerPlaylistItem(p)).ToArray();
}
/// <summary>
/// Retrieves the active <see cref="MultiplayerPlaylistItem"/> as determined by the room's current settings.
/// </summary>
[IgnoreMember]
public MultiplayerPlaylistItem CurrentPlaylistItem => Playlist.Single(item => item.ID == Settings.PlaylistItemId);
/// <summary>
/// Determines whether a user is able to add playlist items to this room.
/// </summary>
/// <param name="user">The user to check.</param>
public bool CanAddPlaylistItems(MultiplayerRoomUser user) => user.Equals(Host) || Settings.QueueMode != QueueMode.HostOnly;
public override string ToString() => $"RoomID:{RoomID} Host:{Host?.UserID} Users:{Users.Count} State:{State} Settings: [{Settings}]";
}
}
@@ -14,7 +14,6 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Threading;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Multiplayer.Countdown;
using osu.Game.Online.Rooms;
using osu.Game.Overlays;
using osu.Game.Overlays.Dialog;
using osuTK;
@@ -23,22 +22,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
public partial class MatchStartControl : CompositeDrawable
{
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!;
[Resolved(canBeNull: true)]
[Resolved]
private IDialogOverlay? dialogOverlay { get; set; }
[Resolved]
private MultiplayerClient client { get; set; } = null!;
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
private readonly MultiplayerReadyButton readyButton;
private readonly MultiplayerCountdownButton countdownButton;
@@ -98,9 +90,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
base.LoadComplete();
SelectedItem.BindValueChanged(_ => updateState());
client.RoomUpdated += onRoomUpdated;
client.LoadRequested += onLoadRequested;
updateState();
}
@@ -214,8 +206,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
readyButton.Enabled.Value = countdownButton.Enabled.Value =
client.Room.State != MultiplayerRoomState.Closed
&& SelectedItem.Value?.ID == client.Room.Settings.PlaylistItemId
&& !client.Room.Playlist.Single(i => i.ID == client.Room.Settings.PlaylistItemId).Expired
&& !client.Room.CurrentPlaylistItem.Expired
&& !operationInProgress.Value;
// When the local user is the host and spectating the match, the ready button should be enabled only if any users are ready.
@@ -1,10 +1,8 @@
// 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.
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
@@ -13,14 +11,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private const float ready_button_width = 600;
private const float spectate_button_width = 200;
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
public MultiplayerMatchFooter()
{
RelativeSizeAxes = Axes.Both;
@@ -36,13 +26,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
new MultiplayerSpectateButton
{
RelativeSizeAxes = Axes.Both,
SelectedItem = selectedItem
},
null,
new MatchStartControl
{
RelativeSizeAxes = Axes.Both,
SelectedItem = selectedItem
},
null
}
@@ -21,12 +21,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
public partial class MultiplayerSpectateButton : CompositeDrawable
{
public required Bindable<PlaylistItem?> SelectedItem
{
get => selectedItem;
set => selectedItem.Current = value;
}
[Resolved]
private OngoingOperationTracker ongoingOperationTracker { get; set; } = null!;
@@ -36,7 +30,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
[Resolved]
private MultiplayerClient client { get; set; } = null!;
private readonly BindableWithCurrent<PlaylistItem?> selectedItem = new BindableWithCurrent<PlaylistItem?>();
private readonly RoundedButton button;
private IBindable<bool> operationInProgress = null!;
@@ -75,7 +68,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
{
base.LoadComplete();
SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(checkForAutomaticDownload), true);
client.RoomUpdated += onRoomUpdated;
updateState();
}
@@ -121,11 +113,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
private void checkForAutomaticDownload()
{
PlaylistItem? item = SelectedItem.Value;
downloadCheckCancellation?.Cancel();
if (item == null)
if (client.Room == null)
return;
if (!automaticallyDownload.Value)
@@ -140,10 +130,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
if (client.LocalUser?.State != MultiplayerUserState.Spectating)
return;
MultiplayerPlaylistItem item = client.Room.CurrentPlaylistItem;
// 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(item.Beatmap.OnlineID, (downloadCheckCancellation = new CancellationTokenSource()).Token)
.GetBeatmapAsync(item.BeatmapID, (downloadCheckCancellation = new CancellationTokenSource()).Token)
.ContinueWith(resolved => Schedule(() =>
{
var beatmapSet = resolved.GetResultSafely()?.BeatmapSet;
@@ -254,10 +254,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
this.Push(new MultiplayerMatchFreestyleSelect(Room, item));
}
protected override Drawable CreateFooter() => new MultiplayerMatchFooter
{
SelectedItem = SelectedItem
};
protected override Drawable CreateFooter() => new MultiplayerMatchFooter();
protected override RoomSettingsOverlay CreateRoomSettingsOverlay(Room room) => new MultiplayerMatchSettingsOverlay(room);