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)]
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)
=> BeatmapID == other.BeatmapID
&& BeatmapChecksum == other.BeatmapChecksum
&& RequiredMods.SequenceEqual(other.RequiredMods)
&& AllowedMods.SequenceEqual(other.AllowedMods)
&& RulesetID == other.RulesetID
&& Name.Equals(other.Name, StringComparison.Ordinal);
&& Name.Equals(other.Name, StringComparison.Ordinal)
&& PlaylistItemId == other.PlaylistItemId;
public override string ToString() => $"Name:{Name}"
+ $" Beatmap:{BeatmapID} ({BeatmapChecksum})"
+ $" RequiredMods:{string.Join(',', RequiredMods)}"
+ $" AllowedMods:{string.Join(',', AllowedMods)}"
+ $" Ruleset:{RulesetID}";
+ $" Ruleset:{RulesetID}"
+ $" Item:{PlaylistItemId}";
}
}

View File

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

View File

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

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using JetBrains.Annotations;
@ -269,7 +268,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
base.LoadComplete();
Playlist.BindCollectionChanged(onPlaylistChanged, true);
SelectedItem.BindValueChanged(onSelectedItemChanged);
SelectedItem.BindTo(client.CurrentMatchPlayingItem);
BeatmapAvailability.BindValueChanged(updateBeatmapAvailability, true);
UserMods.BindValueChanged(onUserModsChanged);
@ -300,11 +301,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return base.OnBackButton();
}
private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e)
private void onSelectedItemChanged(ValueChangedEvent<PlaylistItem> item)
{
SelectedItem.Value = Playlist.LastOrDefault();
if (SelectedItem.Value?.AllowedMods.Any() != true)
if (item.NewValue?.AllowedMods.Any() != true)
{
userModsSection.Hide();
userModsSelectOverlay.Hide();
@ -313,7 +312,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
else
{
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))]
private Bindable<int?> roomId { get; set; }
[Resolved(typeof(Room), nameof(Room.Playlist))]
private BindableList<PlaylistItem> playlist { get; set; }
private MatchSettingsOverlay settingsOverlay;
private MatchLeaderboard leaderboard;
@ -117,7 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
new DrawableRoomPlaylistWithResults
{
RelativeSizeAxes = Axes.Both,
Items = { BindTarget = Playlist },
Items = { BindTarget = playlist },
SelectedItem = { BindTarget = SelectedItem },
RequestShowResults = item =>
{
@ -222,7 +225,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
// Set the first playlist item.
// 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);
}