2021-11-22 17:39:50 +08:00
// 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.
2021-12-03 19:05:25 +08:00
using System ;
2021-11-22 17:39:50 +08:00
using System.Linq ;
using NUnit.Framework ;
using osu.Framework.Allocation ;
using osu.Framework.Audio ;
2024-11-06 15:35:11 +08:00
using osu.Framework.Bindables ;
2022-01-03 16:02:15 +08:00
using osu.Framework.Extensions ;
2021-11-22 17:39:50 +08:00
using osu.Framework.Graphics ;
using osu.Framework.Platform ;
using osu.Framework.Testing ;
using osu.Game.Beatmaps ;
2022-03-21 09:37:02 +08:00
using osu.Game.Graphics.Sprites ;
2022-03-21 04:24:41 +08:00
using osu.Game.Graphics.UserInterface ;
2022-04-01 16:05:11 +08:00
using osu.Game.Online.API.Requests.Responses ;
2021-11-22 17:39:50 +08:00
using osu.Game.Online.Multiplayer ;
using osu.Game.Online.Rooms ;
using osu.Game.Rulesets ;
using osu.Game.Screens.OnlinePlay ;
2021-11-26 18:24:49 +08:00
using osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist ;
2021-12-01 18:02:17 +08:00
using osu.Game.Tests.Beatmaps ;
2021-11-22 17:39:50 +08:00
using osu.Game.Tests.Resources ;
using osuTK ;
namespace osu.Game.Tests.Visual.Multiplayer
{
public partial class TestSceneMultiplayerPlaylist : MultiplayerTestScene
{
2024-11-06 15:35:11 +08:00
private MultiplayerPlaylist list = null ! ;
private BeatmapManager beatmaps = null ! ;
private BeatmapSetInfo importedSet = null ! ;
private BeatmapInfo importedBeatmap = null ! ;
2021-11-22 17:39:50 +08:00
[BackgroundDependencyLoader]
private void load ( GameHost host , AudioManager audio )
{
2022-07-28 15:19:05 +08:00
Dependencies . Cache ( new RealmRulesetStore ( Realm ) ) ;
Dependencies . Cache ( beatmaps = new BeatmapManager ( LocalStorage , Realm , null , audio , Resources , host , Beatmap . Default ) ) ;
2022-01-25 11:58:15 +08:00
Dependencies . Cache ( Realm ) ;
2021-11-22 17:39:50 +08:00
}
2022-07-29 14:27:39 +08:00
[SetUpSteps]
public override void SetUpSteps ( )
2021-11-22 17:39:50 +08:00
{
2022-07-29 14:27:39 +08:00
base . SetUpSteps ( ) ;
AddStep ( "create list" , ( ) = >
2021-11-22 17:39:50 +08:00
{
2024-11-21 19:26:44 +08:00
Child = list = new MultiplayerPlaylist ( SelectedRoom . Value ! )
2022-07-29 14:27:39 +08:00
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
RelativeSizeAxes = Axes . Both ,
2024-11-12 00:38:31 +08:00
Size = new Vector2 ( 0.4f , 0.8f ) ,
SelectedItem = new Bindable < PlaylistItem ? > ( )
2022-07-29 14:27:39 +08:00
} ;
} ) ;
2021-11-22 17:39:50 +08:00
AddStep ( "import beatmap" , ( ) = >
{
2022-01-03 16:02:15 +08:00
beatmaps . Import ( TestResources . GetQuickTestBeatmapForImport ( ) ) . WaitSafely ( ) ;
2021-12-17 17:26:12 +08:00
importedSet = beatmaps . GetAllUsableBeatmapSets ( ) . First ( ) ;
2022-01-27 14:19:48 +08:00
importedBeatmap = importedSet . Beatmaps . First ( b = > b . Ruleset . OnlineID = = 0 ) ;
2021-11-22 17:39:50 +08:00
} ) ;
2021-12-01 17:44:46 +08:00
2022-02-16 08:43:28 +08:00
AddStep ( "change to all players mode" , ( ) = > MultiplayerClient . ChangeSettings ( new MultiplayerRoomSettings { QueueMode = QueueMode . AllPlayers } ) . WaitSafely ( ) ) ;
2021-11-22 17:39:50 +08:00
}
[Test]
2021-12-01 17:44:46 +08:00
public void TestNonExpiredItemsAddedToQueueList ( )
2021-11-22 17:39:50 +08:00
{
2021-12-01 17:44:46 +08:00
assertItemInQueueListStep ( 1 , 0 ) ;
addItemStep ( ) ;
assertItemInQueueListStep ( 2 , 1 ) ;
addItemStep ( ) ;
assertItemInQueueListStep ( 3 , 2 ) ;
}
[Test]
public void TestExpiredItemsAddedToHistoryList ( )
{
assertItemInQueueListStep ( 1 , 0 ) ;
addItemStep ( true ) ;
assertItemInHistoryListStep ( 2 , 0 ) ;
addItemStep ( true ) ;
assertItemInHistoryListStep ( 3 , 0 ) ;
assertItemInHistoryListStep ( 2 , 1 ) ;
// Initial item is still in the queue.
assertItemInQueueListStep ( 1 , 0 ) ;
}
[Test]
public void TestExpiredItemsMoveToQueueList ( )
{
addItemStep ( ) ;
addItemStep ( ) ;
2022-02-16 08:43:28 +08:00
AddStep ( "finish current item" , ( ) = > MultiplayerClient . FinishCurrentItem ( ) . WaitSafely ( ) ) ;
2021-12-01 17:44:46 +08:00
assertItemInHistoryListStep ( 1 , 0 ) ;
assertItemInQueueListStep ( 2 , 0 ) ;
assertItemInQueueListStep ( 3 , 1 ) ;
2022-02-16 08:43:28 +08:00
AddStep ( "finish current item" , ( ) = > MultiplayerClient . FinishCurrentItem ( ) . WaitSafely ( ) ) ;
2021-12-01 17:44:46 +08:00
assertItemInHistoryListStep ( 2 , 0 ) ;
assertItemInHistoryListStep ( 1 , 1 ) ;
assertItemInQueueListStep ( 3 , 0 ) ;
2022-02-16 08:43:28 +08:00
AddStep ( "finish current item" , ( ) = > MultiplayerClient . FinishCurrentItem ( ) . WaitSafely ( ) ) ;
2021-12-01 17:44:46 +08:00
assertItemInHistoryListStep ( 3 , 0 ) ;
assertItemInHistoryListStep ( 2 , 1 ) ;
assertItemInHistoryListStep ( 1 , 2 ) ;
}
2021-12-01 17:57:29 +08:00
[Test]
public void TestListsClearedWhenRoomLeft ( )
{
addItemStep ( ) ;
2022-02-16 08:43:28 +08:00
AddStep ( "finish current item" , ( ) = > MultiplayerClient . FinishCurrentItem ( ) . WaitSafely ( ) ) ;
2021-12-01 17:57:29 +08:00
AddStep ( "leave room" , ( ) = > RoomManager . PartRoom ( ) ) ;
2021-12-22 11:55:37 +08:00
AddUntilStep ( "wait for room part" , ( ) = > ! RoomJoined ) ;
2021-12-01 17:57:29 +08:00
AddUntilStep ( "item 0 not in lists" , ( ) = > ! inHistoryList ( 0 ) & & ! inQueueList ( 0 ) ) ;
AddUntilStep ( "item 1 not in lists" , ( ) = > ! inHistoryList ( 0 ) & & ! inQueueList ( 0 ) ) ;
}
2022-03-21 04:24:41 +08:00
[Test]
2022-03-21 04:28:05 +08:00
public void TestQueueTabCount ( )
2022-03-21 04:24:41 +08:00
{
assertQueueTabCount ( 1 ) ;
addItemStep ( ) ;
assertQueueTabCount ( 2 ) ;
addItemStep ( ) ;
assertQueueTabCount ( 3 ) ;
AddStep ( "finish current item" , ( ) = > MultiplayerClient . FinishCurrentItem ( ) . WaitSafely ( ) ) ;
assertQueueTabCount ( 2 ) ;
AddStep ( "leave room" , ( ) = > RoomManager . PartRoom ( ) ) ;
AddUntilStep ( "wait for room part" , ( ) = > ! RoomJoined ) ;
assertQueueTabCount ( 0 ) ;
}
2021-12-01 18:22:21 +08:00
[Ignore("Expired items are initially removed from the room.")]
2021-12-01 17:44:46 +08:00
[Test]
public void TestJoinRoomWithMixedItemsAddedInCorrectLists ( )
{
AddStep ( "leave room" , ( ) = > RoomManager . PartRoom ( ) ) ;
2021-12-22 11:55:37 +08:00
AddUntilStep ( "wait for room part" , ( ) = > ! RoomJoined ) ;
2021-12-01 18:02:17 +08:00
AddStep ( "join room with items" , ( ) = >
{
RoomManager . CreateRoom ( new Room
{
2024-11-13 15:55:18 +08:00
Name = "test name" ,
2021-12-01 18:02:17 +08:00
Playlist =
2024-11-14 16:57:32 +08:00
[
2022-02-15 22:33:26 +08:00
new PlaylistItem ( new TestBeatmap ( Ruleset . Value ) . BeatmapInfo )
2021-12-01 18:02:17 +08:00
{
2022-02-15 22:33:26 +08:00
RulesetID = Ruleset . Value . OnlineID
2021-12-01 18:02:17 +08:00
} ,
2022-02-15 22:33:26 +08:00
new PlaylistItem ( new TestBeatmap ( Ruleset . Value ) . BeatmapInfo )
2021-12-01 18:02:17 +08:00
{
2022-02-15 15:01:14 +08:00
RulesetID = Ruleset . Value . OnlineID ,
2021-12-01 18:02:17 +08:00
Expired = true
}
2024-11-14 16:57:32 +08:00
]
2021-12-01 18:02:17 +08:00
} ) ;
} ) ;
AddUntilStep ( "wait for room join" , ( ) = > RoomJoined ) ;
assertItemInQueueListStep ( 1 , 0 ) ;
assertItemInHistoryListStep ( 2 , 0 ) ;
2021-12-01 17:44:46 +08:00
}
2022-04-01 16:05:11 +08:00
[Test]
public void TestInsertedItemDoesNotRefreshAllOthers ( )
{
AddStep ( "change to round robin queue mode" , ( ) = > MultiplayerClient . ChangeSettings ( new MultiplayerRoomSettings { QueueMode = QueueMode . AllPlayersRoundRobin } ) . WaitSafely ( ) ) ;
// Add a few items for the local user.
addItemStep ( ) ;
addItemStep ( ) ;
addItemStep ( ) ;
addItemStep ( ) ;
addItemStep ( ) ;
2024-11-06 15:35:11 +08:00
DrawableRoomPlaylistItem [ ] drawableItems = null ! ;
2022-04-01 16:05:11 +08:00
AddStep ( "get drawable items" , ( ) = > drawableItems = this . ChildrenOfType < DrawableRoomPlaylistItem > ( ) . ToArray ( ) ) ;
// Add 1 item for another user.
AddStep ( "join second user" , ( ) = > MultiplayerClient . AddUser ( new APIUser { Id = 10 } ) ) ;
addItemStep ( userId : 10 ) ;
// New item inserted towards the top of the list.
assertItemInQueueListStep ( 7 , 1 ) ;
AddAssert ( "all previous playlist items remained" , ( ) = > drawableItems . All ( this . ChildrenOfType < DrawableRoomPlaylistItem > ( ) . Contains ) ) ;
}
2021-12-01 17:44:46 +08:00
/// <summary>
/// Adds a step to create a new playlist item.
/// </summary>
2022-04-01 16:05:11 +08:00
private void addItemStep ( bool expired = false , int? userId = null ) = > AddStep ( "add item" , ( ) = >
2021-12-01 17:44:46 +08:00
{
2023-05-25 19:09:40 +08:00
MultiplayerClient . AddUserPlaylistItem ( userId ? ? API . LocalUser . Value . OnlineID , TestMultiplayerClient . CreateMultiplayerPlaylistItem ( new PlaylistItem ( importedBeatmap )
2022-04-01 16:05:11 +08:00
{
Expired = expired ,
PlayedAt = DateTimeOffset . Now
} ) ) . WaitSafely ( ) ;
} ) ;
2021-12-01 17:44:46 +08:00
/// <summary>
/// Asserts the position of a given playlist item in the queue list.
/// </summary>
/// <param name="playlistItemId">The item id.</param>
/// <param name="visualIndex">The index at which the item should appear visually. The item with index 0 is at the top of the list.</param>
2021-12-01 18:54:39 +08:00
private void assertItemInQueueListStep ( int playlistItemId , int visualIndex )
2021-12-01 17:44:46 +08:00
{
2021-12-01 18:54:39 +08:00
changeDisplayModeStep ( MultiplayerPlaylistDisplayMode . Queue ) ;
AddUntilStep ( $"{playlistItemId} in queue at pos = {visualIndex}" , ( ) = >
{
return ! inHistoryList ( playlistItemId )
& & this . ChildrenOfType < MultiplayerQueueList > ( )
. Single ( )
. ChildrenOfType < DrawableRoomPlaylistItem > ( )
. OrderBy ( drawable = > drawable . Position . Y )
. TakeWhile ( drawable = > drawable . Item . ID ! = playlistItemId )
. Count ( ) = = visualIndex ;
} ) ;
}
2021-12-01 17:44:46 +08:00
/// <summary>
/// Asserts the position of a given playlist item in the history list.
/// </summary>
/// <param name="playlistItemId">The item id.</param>
/// <param name="visualIndex">The index at which the item should appear visually. The item with index 0 is at the top of the list.</param>
2021-12-01 18:54:39 +08:00
private void assertItemInHistoryListStep ( int playlistItemId , int visualIndex )
2021-12-01 17:44:46 +08:00
{
2021-12-01 18:54:39 +08:00
changeDisplayModeStep ( MultiplayerPlaylistDisplayMode . History ) ;
AddUntilStep ( $"{playlistItemId} in history at pos = {visualIndex}" , ( ) = >
{
return ! inQueueList ( playlistItemId )
& & this . ChildrenOfType < MultiplayerHistoryList > ( )
. Single ( )
. ChildrenOfType < DrawableRoomPlaylistItem > ( )
. OrderBy ( drawable = > drawable . Position . Y )
. TakeWhile ( drawable = > drawable . Item . ID ! = playlistItemId )
. Count ( ) = = visualIndex ;
} ) ;
}
2022-03-21 04:24:41 +08:00
private void assertQueueTabCount ( int count )
{
string queueTabText = count > 0 ? $"Queue ({count})" : "Queue" ;
AddUntilStep ( $"Queue tab shows \" { queueTabText } \ "" , ( ) = >
{
return this . ChildrenOfType < OsuTabControl < MultiplayerPlaylistDisplayMode > . OsuTabItem > ( )
2022-03-21 09:37:02 +08:00
. Single ( t = > t . Value = = MultiplayerPlaylistDisplayMode . Queue )
. ChildrenOfType < OsuSpriteText > ( ) . Single ( ) . Text = = queueTabText ;
2022-03-21 04:24:41 +08:00
} ) ;
}
2021-12-01 18:54:39 +08:00
private void changeDisplayModeStep ( MultiplayerPlaylistDisplayMode mode ) = > AddStep ( $"change list to {mode}" , ( ) = > list . DisplayMode . Value = mode ) ;
2021-12-01 17:44:46 +08:00
private bool inQueueList ( int playlistItemId )
{
return this . ChildrenOfType < MultiplayerQueueList > ( )
. Single ( )
2021-12-01 18:54:39 +08:00
. Items . Any ( i = > i . ID = = playlistItemId ) ;
2021-12-01 17:44:46 +08:00
}
private bool inHistoryList ( int playlistItemId )
{
return this . ChildrenOfType < MultiplayerHistoryList > ( )
. Single ( )
2021-12-01 18:54:39 +08:00
. Items . Any ( i = > i . ID = = playlistItemId ) ;
2021-11-22 17:39:50 +08:00
}
}
}