1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-15 05:52:54 +08:00

Make StatefulMultiplayerClient control current playlist item

This commit is contained in:
smoogipoo 2021-02-16 18:56:13 +09:00
parent 855d24dce7
commit 3ff9e14e35
5 changed files with 39 additions and 32 deletions

View File

@ -36,18 +36,26 @@ namespace osu.Game.Online.Multiplayer
[Key(5)] [Key(5)]
public IEnumerable<APIMod> AllowedMods { get; set; } = Enumerable.Empty<APIMod>(); public IEnumerable<APIMod> AllowedMods { get; set; } = Enumerable.Empty<APIMod>();
/// <summary>
/// Only used for client-side mutation.
/// </summary>
[Key(6)]
public int PlaylistItemId { get; set; }
public bool Equals(MultiplayerRoomSettings other) public bool Equals(MultiplayerRoomSettings other)
=> BeatmapID == other.BeatmapID => BeatmapID == other.BeatmapID
&& BeatmapChecksum == other.BeatmapChecksum && BeatmapChecksum == other.BeatmapChecksum
&& RequiredMods.SequenceEqual(other.RequiredMods) && RequiredMods.SequenceEqual(other.RequiredMods)
&& AllowedMods.SequenceEqual(other.AllowedMods) && AllowedMods.SequenceEqual(other.AllowedMods)
&& RulesetID == other.RulesetID && RulesetID == other.RulesetID
&& Name.Equals(other.Name, StringComparison.Ordinal); && Name.Equals(other.Name, StringComparison.Ordinal)
&& PlaylistItemId == other.PlaylistItemId;
public override string ToString() => $"Name:{Name}" public override string ToString() => $"Name:{Name}"
+ $" Beatmap:{BeatmapID} ({BeatmapChecksum})" + $" Beatmap:{BeatmapID} ({BeatmapChecksum})"
+ $" RequiredMods:{string.Join(',', RequiredMods)}" + $" RequiredMods:{string.Join(',', RequiredMods)}"
+ $" AllowedMods:{string.Join(',', AllowedMods)}" + $" AllowedMods:{string.Join(',', AllowedMods)}"
+ $" Ruleset:{RulesetID}"; + $" Ruleset:{RulesetID}"
+ $" Item:{PlaylistItemId}";
} }
} }

View File

@ -66,6 +66,8 @@ namespace osu.Game.Online.Multiplayer
/// </summary> /// </summary>
public readonly BindableList<int> CurrentMatchPlayingUserIds = new BindableList<int>(); public readonly BindableList<int> CurrentMatchPlayingUserIds = new BindableList<int>();
public readonly Bindable<PlaylistItem?> CurrentMatchPlayingItem = new Bindable<PlaylistItem?>();
/// <summary> /// <summary>
/// The <see cref="MultiplayerRoomUser"/> corresponding to the local player, if available. /// The <see cref="MultiplayerRoomUser"/> corresponding to the local player, if available.
/// </summary> /// </summary>
@ -94,9 +96,6 @@ namespace osu.Game.Online.Multiplayer
private Room? apiRoom; private Room? apiRoom;
// Todo: This is temporary, until the multiplayer server returns the item id on match start or otherwise.
private int playlistItemId;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -142,7 +141,6 @@ namespace osu.Game.Online.Multiplayer
{ {
Room = joinedRoom; Room = joinedRoom;
apiRoom = room; apiRoom = room;
playlistItemId = room.Playlist.SingleOrDefault()?.ID ?? 0;
}, cancellationSource.Token); }, cancellationSource.Token);
// Update room settings. // Update room settings.
@ -218,7 +216,8 @@ namespace osu.Game.Online.Multiplayer
BeatmapChecksum = item.GetOr(existingPlaylistItem).Beatmap.Value.MD5Hash, BeatmapChecksum = item.GetOr(existingPlaylistItem).Beatmap.Value.MD5Hash,
RulesetID = item.GetOr(existingPlaylistItem).RulesetID, RulesetID = item.GetOr(existingPlaylistItem).RulesetID,
RequiredMods = item.HasValue ? item.Value.AsNonNull().RequiredMods.Select(m => new APIMod(m)).ToList() : Room.Settings.RequiredMods, RequiredMods = item.HasValue ? item.Value.AsNonNull().RequiredMods.Select(m => new APIMod(m)).ToList() : Room.Settings.RequiredMods,
AllowedMods = item.HasValue ? item.Value.AsNonNull().AllowedMods.Select(m => new APIMod(m)).ToList() : Room.Settings.AllowedMods AllowedMods = item.HasValue ? item.Value.AsNonNull().AllowedMods.Select(m => new APIMod(m)).ToList() : Room.Settings.AllowedMods,
PlaylistItemId = Room.Settings.PlaylistItemId,
}); });
} }
@ -506,14 +505,13 @@ namespace osu.Game.Online.Multiplayer
Room.Settings = settings; Room.Settings = settings;
apiRoom.Name.Value = Room.Settings.Name; apiRoom.Name.Value = Room.Settings.Name;
// The playlist update is delayed until an online beatmap lookup (below) succeeds. // The current item update is delayed until an online beatmap lookup (below) succeeds.
// In-order for the client to not display an outdated beatmap, the playlist is forcefully cleared here. // In-order for the client to not display an outdated beatmap, the current item is forcefully cleared here.
apiRoom.Playlist.Clear(); CurrentMatchPlayingItem.Value = null;
RoomUpdated?.Invoke(); RoomUpdated?.Invoke();
var req = new GetBeatmapSetRequest(settings.BeatmapID, BeatmapSetLookupType.BeatmapId); var req = new GetBeatmapSetRequest(settings.BeatmapID, BeatmapSetLookupType.BeatmapId);
req.Success += res => req.Success += res =>
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
@ -540,18 +538,21 @@ namespace osu.Game.Online.Multiplayer
var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset)); var mods = settings.RequiredMods.Select(m => m.ToMod(ruleset));
var allowedMods = settings.AllowedMods.Select(m => m.ToMod(ruleset)); var allowedMods = settings.AllowedMods.Select(m => m.ToMod(ruleset));
PlaylistItem playlistItem = new PlaylistItem // Update an existing playlist item from the API room, or create a new item.
{ var playlistItem = apiRoom.Playlist.FirstOrDefault(i => i.ID == settings.PlaylistItemId);
ID = playlistItemId,
Beatmap = { Value = beatmap },
Ruleset = { Value = ruleset.RulesetInfo },
};
if (playlistItem == null)
apiRoom.Playlist.Add(playlistItem = new PlaylistItem());
playlistItem.ID = settings.PlaylistItemId;
playlistItem.Beatmap.Value = beatmap;
playlistItem.Ruleset.Value = ruleset.RulesetInfo;
playlistItem.RequiredMods.Clear();
playlistItem.RequiredMods.AddRange(mods); playlistItem.RequiredMods.AddRange(mods);
playlistItem.AllowedMods.Clear();
playlistItem.AllowedMods.AddRange(allowedMods); playlistItem.AllowedMods.AddRange(allowedMods);
apiRoom.Playlist.Clear(); // Clearing should be unnecessary, but here for sanity. CurrentMatchPlayingItem.Value = playlistItem;
apiRoom.Playlist.Add(playlistItem);
} }
/// <summary> /// <summary>

View File

@ -28,9 +28,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
private Sample sampleStart; private Sample sampleStart;
[Resolved(typeof(Room), nameof(Room.Playlist))]
protected BindableList<PlaylistItem> Playlist { get; private set; }
/// <summary> /// <summary>
/// Any mods applied by/to the local user. /// Any mods applied by/to the local user.
/// </summary> /// </summary>
@ -74,7 +71,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
base.LoadComplete(); base.LoadComplete();
SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged)); SelectedItem.BindValueChanged(_ => Scheduler.AddOnce(selectedItemChanged));
SelectedItem.Value = Playlist.FirstOrDefault();
managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy(); managerUpdated = beatmapManager.ItemUpdated.GetBoundCopy();
managerUpdated.BindValueChanged(beatmapUpdated); managerUpdated.BindValueChanged(beatmapUpdated);

View File

@ -3,7 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
@ -269,7 +268,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{ {
base.LoadComplete(); base.LoadComplete();
Playlist.BindCollectionChanged(onPlaylistChanged, true); SelectedItem.BindValueChanged(onSelectedItemChanged);
SelectedItem.BindTo(client.CurrentMatchPlayingItem);
BeatmapAvailability.BindValueChanged(updateBeatmapAvailability, true); BeatmapAvailability.BindValueChanged(updateBeatmapAvailability, true);
UserMods.BindValueChanged(onUserModsChanged); UserMods.BindValueChanged(onUserModsChanged);
@ -300,11 +301,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return base.OnBackButton(); return base.OnBackButton();
} }
private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) private void onSelectedItemChanged(ValueChangedEvent<PlaylistItem> item)
{ {
SelectedItem.Value = Playlist.LastOrDefault(); if (item.NewValue?.AllowedMods.Any() != true)
if (SelectedItem.Value?.AllowedMods.Any() != true)
{ {
userModsSection.Hide(); userModsSection.Hide();
userModsSelectOverlay.Hide(); userModsSelectOverlay.Hide();
@ -313,7 +312,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
else else
{ {
userModsSection.Show(); userModsSection.Show();
userModsSelectOverlay.IsValidMod = m => SelectedItem.Value.AllowedMods.Any(a => a.GetType() == m.GetType()); userModsSelectOverlay.IsValidMod = m => item.NewValue.AllowedMods.Any(a => a.GetType() == m.GetType());
} }
} }

View File

@ -27,6 +27,9 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
[Resolved(typeof(Room), nameof(Room.RoomID))] [Resolved(typeof(Room), nameof(Room.RoomID))]
private Bindable<int?> roomId { get; set; } private Bindable<int?> roomId { get; set; }
[Resolved(typeof(Room), nameof(Room.Playlist))]
private BindableList<PlaylistItem> playlist { get; set; }
private MatchSettingsOverlay settingsOverlay; private MatchSettingsOverlay settingsOverlay;
private MatchLeaderboard leaderboard; private MatchLeaderboard leaderboard;
@ -117,7 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
new DrawableRoomPlaylistWithResults new DrawableRoomPlaylistWithResults
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Items = { BindTarget = Playlist }, Items = { BindTarget = playlist },
SelectedItem = { BindTarget = SelectedItem }, SelectedItem = { BindTarget = SelectedItem },
RequestShowResults = item => RequestShowResults = item =>
{ {
@ -222,7 +225,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
// Set the first playlist item. // Set the first playlist item.
// This is scheduled since updating the room and playlist may happen in an arbitrary order (via Room.CopyFrom()). // This is scheduled since updating the room and playlist may happen in an arbitrary order (via Room.CopyFrom()).
Schedule(() => SelectedItem.Value = Playlist.FirstOrDefault()); Schedule(() => SelectedItem.Value = playlist.FirstOrDefault());
} }
}, true); }, true);
} }