diff --git a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs
index 65467e6ba9..73fda78d00 100644
--- a/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs
+++ b/osu.Game/Online/Multiplayer/IMultiplayerRoomServer.cs
@@ -83,6 +83,12 @@ namespace osu.Game.Online.Multiplayer
/// The item to add.
Task AddPlaylistItem(MultiplayerPlaylistItem item);
+ ///
+ /// Edits an existing playlist item with new values.
+ ///
+ /// The item to edit, containing new properties. Must have an ID.
+ Task EditPlaylistItem(MultiplayerPlaylistItem item);
+
///
/// Removes an item from the playlist.
///
diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
index 34dc7ea5ea..55b4def908 100644
--- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs
@@ -335,6 +335,8 @@ namespace osu.Game.Online.Multiplayer
public abstract Task AddPlaylistItem(MultiplayerPlaylistItem item);
+ public abstract Task EditPlaylistItem(MultiplayerPlaylistItem item);
+
public abstract Task RemovePlaylistItem(long playlistItemId);
Task IMultiplayerClient.RoomStateChanged(MultiplayerRoomState state)
diff --git a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
index 7314603603..d268d2bf69 100644
--- a/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
+++ b/osu.Game/Online/Multiplayer/OnlineMultiplayerClient.cs
@@ -162,6 +162,14 @@ namespace osu.Game.Online.Multiplayer
return connection.InvokeAsync(nameof(IMultiplayerServer.AddPlaylistItem), item);
}
+ public override Task EditPlaylistItem(MultiplayerPlaylistItem item)
+ {
+ if (!IsConnected.Value)
+ return Task.CompletedTask;
+
+ return connection.InvokeAsync(nameof(IMultiplayerServer.EditPlaylistItem), item);
+ }
+
public override Task RemovePlaylistItem(long playlistItemId)
{
if (!IsConnected.Value)
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
index 80a0289ba9..8d3686dd6d 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSongSelect.cs
@@ -4,6 +4,7 @@
using System;
using System.Diagnostics;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using osu.Framework.Allocation;
using osu.Framework.Logging;
@@ -64,7 +65,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
loadingLayer.Show();
- client.AddPlaylistItem(new MultiplayerPlaylistItem
+ var multiplayerItem = new MultiplayerPlaylistItem
{
ID = itemToEdit?.ID ?? 0,
BeatmapID = item.BeatmapID,
@@ -72,7 +73,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
RulesetID = item.RulesetID,
RequiredMods = item.RequiredMods.Select(m => new APIMod(m)).ToArray(),
AllowedMods = item.AllowedMods.Select(m => new APIMod(m)).ToArray()
- }).ContinueWith(t =>
+ };
+
+ Task task = itemToEdit != null ? client.EditPlaylistItem(multiplayerItem) : client.AddPlaylistItem(multiplayerItem);
+
+ task.ContinueWith(t =>
{
Schedule(() =>
{
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
index 1516d0e473..d22f0415e6 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
@@ -309,49 +309,51 @@ namespace osu.Game.Tests.Visual.Multiplayer
Debug.Assert(APIRoom != null);
Debug.Assert(currentItem != null);
- bool isNewAddition = item.ID == 0;
-
if (Room.Settings.QueueMode == QueueMode.HostOnly && Room.Host?.UserID != LocalUser?.UserID)
throw new InvalidOperationException("Local user is not the room host.");
item.OwnerID = userId;
- if (isNewAddition)
- {
- await addItem(item).ConfigureAwait(false);
- await updateCurrentItem(Room).ConfigureAwait(false);
- }
- else
- {
- var existingItem = serverSidePlaylist.SingleOrDefault(i => i.ID == item.ID);
-
- if (existingItem == null)
- throw new InvalidOperationException("Attempted to change an item that doesn't exist.");
-
- if (existingItem.OwnerID != userId && Room.Host?.UserID != LocalUser?.UserID)
- throw new InvalidOperationException("Attempted to change an item which is not owned by the user.");
-
- if (existingItem.Expired)
- throw new InvalidOperationException("Attempted to change an item which has already been played.");
-
- // Ensure the playlist order doesn't change.
- item.PlaylistOrder = existingItem.PlaylistOrder;
-
- serverSidePlaylist[serverSidePlaylist.IndexOf(existingItem)] = item;
- await ((IMultiplayerClient)this).PlaylistItemChanged(item).ConfigureAwait(false);
- }
+ await addItem(item).ConfigureAwait(false);
+ await updateCurrentItem(Room).ConfigureAwait(false);
}
public override Task AddPlaylistItem(MultiplayerPlaylistItem item) => AddUserPlaylistItem(api.LocalUser.Value.OnlineID, item);
+ public async Task EditUserPlaylistItem(int userId, MultiplayerPlaylistItem item)
+ {
+ Debug.Assert(Room != null);
+ Debug.Assert(APIRoom != null);
+ Debug.Assert(currentItem != null);
+
+ item.OwnerID = userId;
+
+ var existingItem = serverSidePlaylist.SingleOrDefault(i => i.ID == item.ID);
+
+ if (existingItem == null)
+ throw new InvalidOperationException("Attempted to change an item that doesn't exist.");
+
+ if (existingItem.OwnerID != userId && Room.Host?.UserID != LocalUser?.UserID)
+ throw new InvalidOperationException("Attempted to change an item which is not owned by the user.");
+
+ if (existingItem.Expired)
+ throw new InvalidOperationException("Attempted to change an item which has already been played.");
+
+ // Ensure the playlist order doesn't change.
+ item.PlaylistOrder = existingItem.PlaylistOrder;
+
+ serverSidePlaylist[serverSidePlaylist.IndexOf(existingItem)] = item;
+
+ await ((IMultiplayerClient)this).PlaylistItemChanged(item).ConfigureAwait(false);
+ }
+
+ public override Task EditPlaylistItem(MultiplayerPlaylistItem item) => EditUserPlaylistItem(api.LocalUser.Value.OnlineID, item);
+
public async Task RemoveUserPlaylistItem(int userId, long playlistItemId)
{
Debug.Assert(Room != null);
Debug.Assert(APIRoom != null);
- if (Room.Settings.QueueMode == QueueMode.HostOnly)
- throw new InvalidOperationException("Items cannot be removed in host-only mode.");
-
var item = serverSidePlaylist.Find(i => i.ID == playlistItemId);
if (item == null)