2020-12-19 01:59:11 +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.
2022-03-17 18:26:42 +08:00
using System ;
2020-12-19 01:59:11 +08:00
using System.Linq ;
2022-04-13 19:28:53 +08:00
using System.Threading.Tasks ;
2022-04-13 16:02:53 +08:00
using Moq ;
2020-12-19 01:59:11 +08:00
using NUnit.Framework ;
using osu.Framework.Allocation ;
2021-01-17 04:04:28 +08:00
using osu.Framework.Bindables ;
2022-01-03 16:02:15 +08:00
using osu.Framework.Extensions ;
2020-12-19 01:59:11 +08:00
using osu.Framework.Graphics ;
2022-03-17 18:05:28 +08:00
using osu.Framework.Graphics.Cursor ;
2022-03-24 13:26:31 +08:00
using osu.Framework.Graphics.UserInterface ;
2022-04-13 19:28:53 +08:00
using osu.Framework.Logging ;
2020-12-29 03:59:38 +08:00
using osu.Framework.Testing ;
2020-12-24 16:17:45 +08:00
using osu.Framework.Utils ;
2020-12-29 03:59:38 +08:00
using osu.Game.Graphics.UserInterface ;
2021-11-04 17:02:44 +08:00
using osu.Game.Online.API.Requests.Responses ;
2020-12-19 01:59:11 +08:00
using osu.Game.Online.Multiplayer ;
2022-03-17 18:26:42 +08:00
using osu.Game.Online.Multiplayer.Countdown ;
2020-12-25 12:38:11 +08:00
using osu.Game.Online.Rooms ;
2022-04-13 16:02:53 +08:00
using osu.Game.Screens.OnlinePlay ;
2020-12-25 23:50:00 +08:00
using osu.Game.Screens.OnlinePlay.Multiplayer.Match ;
2020-12-19 01:59:11 +08:00
using osuTK ;
2022-03-17 18:26:42 +08:00
using osuTK.Input ;
2020-12-19 01:59:11 +08:00
2020-12-25 12:20:37 +08:00
namespace osu.Game.Tests.Visual.Multiplayer
2020-12-19 01:59:11 +08:00
{
2022-04-13 16:02:53 +08:00
public class TestSceneMatchStartControl : OsuManualInputManagerTestScene
2020-12-19 01:59:11 +08:00
{
2022-04-13 16:02:53 +08:00
private readonly Mock < MultiplayerClient > multiplayerClient = new Mock < MultiplayerClient > ( ) ;
private readonly Mock < OnlinePlayBeatmapAvailabilityTracker > availabilityTracker = new Mock < OnlinePlayBeatmapAvailabilityTracker > ( ) ;
private readonly Bindable < BeatmapAvailability > beatmapAvailability = new Bindable < BeatmapAvailability > ( ) ;
private readonly Bindable < Room > room = new Bindable < Room > ( ) ;
2020-12-19 01:59:11 +08:00
2022-04-13 16:02:53 +08:00
private MultiplayerRoom multiplayerRoom ;
private MultiplayerRoomUser localUser ;
private OngoingOperationTracker ongoingOperationTracker ;
private PopoverContainer content ;
private MatchStartControl control ;
2021-01-17 04:04:28 +08:00
2022-04-13 16:02:53 +08:00
protected override IReadOnlyDependencyContainer CreateChildDependencies ( IReadOnlyDependencyContainer parent ) = >
new CachedModelDependencyContainer < Room > ( base . CreateChildDependencies ( parent ) ) { Model = { BindTarget = room } } ;
2020-12-19 01:59:11 +08:00
[BackgroundDependencyLoader]
2022-04-13 16:02:53 +08:00
private void load ( )
2020-12-19 01:59:11 +08:00
{
2022-04-13 16:02:53 +08:00
Dependencies . CacheAs ( multiplayerClient . Object ) ;
Dependencies . CacheAs ( ongoingOperationTracker = new OngoingOperationTracker ( ) ) ;
2020-12-19 01:59:11 +08:00
2022-04-13 16:02:53 +08:00
availabilityTracker . SetupGet ( a = > a . Availability ) . Returns ( beatmapAvailability ) ;
Dependencies . CacheAs ( availabilityTracker . Object ) ;
multiplayerClient . SetupGet ( m = > m . LocalUser ) . Returns ( ( ) = > localUser ) ;
multiplayerClient . SetupGet ( m = > m . Room ) . Returns ( ( ) = > multiplayerRoom ) ;
// By default, the local user is to be the host.
multiplayerClient . SetupGet ( m = > m . IsHost ) . Returns ( true ) ;
2021-06-25 14:00:10 +08:00
2022-04-13 16:02:53 +08:00
// Assume all state changes are accepted by the server.
multiplayerClient . Setup ( m = > m . ChangeState ( It . IsAny < MultiplayerUserState > ( ) ) )
. Callback ( ( MultiplayerUserState r ) = >
{
2022-04-13 19:28:53 +08:00
Logger . Log ( $"Changing local user state from {localUser.State} to {r}" ) ;
2022-04-13 16:02:53 +08:00
localUser . State = r ;
raiseRoomUpdated ( ) ;
} ) ;
2022-03-08 23:48:03 +08:00
2022-04-13 19:28:53 +08:00
// We don't want to have to handle entering into actual gameplay in this test.
// Returning a failed task should always allow the button to always stay in a clickable state.
multiplayerClient . Setup ( m = > m . StartMatch ( ) ) . Returns ( Task . FromException < InvalidOperationException > ( new InvalidOperationException ( ) ) ) ;
2022-04-13 16:32:04 +08:00
multiplayerClient . Setup ( m = > m . SendMatchRequest ( It . IsAny < MatchUserRequest > ( ) ) )
. Callback ( ( MatchUserRequest request ) = >
{
switch ( request )
{
case StartMatchCountdownRequest countdownStart :
2022-04-13 19:28:53 +08:00
setRoomCountdown ( countdownStart . Duration ) ;
2022-04-13 16:32:04 +08:00
break ;
case StopCountdownRequest _ :
multiplayerRoom . Countdown = null ;
raiseRoomUpdated ( ) ;
break ;
}
} ) ;
2022-04-13 16:02:53 +08:00
Children = new Drawable [ ]
2021-01-17 04:04:28 +08:00
{
2022-04-13 16:02:53 +08:00
ongoingOperationTracker ,
content = new PopoverContainer { RelativeSizeAxes = Axes . Both }
2021-01-17 04:04:28 +08:00
} ;
2022-04-13 16:02:53 +08:00
}
[SetUpSteps]
public void SetUpSteps ( )
{
AddStep ( "reset state" , ( ) = >
{
multiplayerClient . Invocations . Clear ( ) ;
beatmapAvailability . Value = BeatmapAvailability . LocallyAvailable ( ) ;
var playlistItem = new PlaylistItem ( Beatmap . Value . BeatmapInfo )
{
RulesetID = Beatmap . Value . BeatmapInfo . Ruleset . OnlineID
} ;
room . Value = new Room
{
Playlist = { playlistItem } ,
CurrentPlaylistItem = { Value = playlistItem }
} ;
2022-04-13 19:28:53 +08:00
localUser = new MultiplayerRoomUser ( API . LocalUser . Value . Id ) { User = API . LocalUser . Value } ;
2022-04-13 16:02:53 +08:00
multiplayerRoom = new MultiplayerRoom ( 0 )
{
Playlist =
{
new MultiplayerPlaylistItem ( playlistItem ) ,
} ,
2022-04-13 19:28:53 +08:00
Users = { localUser } ,
Host = localUser ,
2022-04-13 16:02:53 +08:00
} ;
} ) ;
2020-12-19 01:59:11 +08:00
2022-04-13 16:02:53 +08:00
AddStep ( "create control" , ( ) = >
2020-12-19 01:59:11 +08:00
{
2022-04-13 16:02:53 +08:00
content . Child = control = new MatchStartControl
2022-03-17 18:05:28 +08:00
{
Anchor = Anchor . Centre ,
Origin = Anchor . Centre ,
2022-03-26 13:29:31 +08:00
Size = new Vector2 ( 250 , 50 ) ,
2022-04-13 16:02:53 +08:00
} ;
} ) ;
}
2020-12-19 01:59:11 +08:00
2022-03-17 18:26:42 +08:00
[Test]
public void TestStartWithCountdown ( )
{
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
AddUntilStep ( "countdown button shown" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . SingleOrDefault ( ) ? . IsPresent = = true ) ;
ClickButtonWhenEnabled < MultiplayerCountdownButton > ( ) ;
2022-03-17 18:26:42 +08:00
AddStep ( "click the first countdown button" , ( ) = >
{
2022-03-24 13:26:31 +08:00
var popoverButton = this . ChildrenOfType < Popover > ( ) . Single ( ) . ChildrenOfType < OsuButton > ( ) . First ( ) ;
2022-03-17 18:26:42 +08:00
InputManager . MoveMouseTo ( popoverButton ) ;
InputManager . Click ( MouseButton . Left ) ;
} ) ;
2022-04-13 16:02:53 +08:00
AddStep ( "check request received" , ( ) = >
{
multiplayerClient . Verify ( m = > m . SendMatchRequest ( It . Is < StartMatchCountdownRequest > ( req = >
req . Duration = = TimeSpan . FromSeconds ( 10 )
) ) , Times . Once ) ;
} ) ;
2022-03-17 18:26:42 +08:00
}
[Test]
public void TestCancelCountdown ( )
{
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
AddUntilStep ( "countdown button shown" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . SingleOrDefault ( ) ? . IsPresent = = true ) ;
2022-04-13 19:28:53 +08:00
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerCountdownButton > ( ) ;
2022-03-17 18:26:42 +08:00
AddStep ( "click the first countdown button" , ( ) = >
{
2022-03-24 13:26:31 +08:00
var popoverButton = this . ChildrenOfType < Popover > ( ) . Single ( ) . ChildrenOfType < OsuButton > ( ) . First ( ) ;
2022-03-17 18:26:42 +08:00
InputManager . MoveMouseTo ( popoverButton ) ;
InputManager . Click ( MouseButton . Left ) ;
} ) ;
2022-04-13 16:32:04 +08:00
AddStep ( "check request received" , ( ) = >
{
multiplayerClient . Verify ( m = > m . SendMatchRequest ( It . Is < StartMatchCountdownRequest > ( req = >
req . Duration = = TimeSpan . FromSeconds ( 10 )
) ) , Times . Once ) ;
} ) ;
2022-03-26 13:43:41 +08:00
ClickButtonWhenEnabled < MultiplayerCountdownButton > ( ) ;
AddStep ( "click the cancel button" , ( ) = >
{
var popoverButton = this . ChildrenOfType < Popover > ( ) . Single ( ) . ChildrenOfType < OsuButton > ( ) . Last ( ) ;
InputManager . MoveMouseTo ( popoverButton ) ;
InputManager . Click ( MouseButton . Left ) ;
} ) ;
2022-03-17 18:26:42 +08:00
2022-04-13 16:32:04 +08:00
AddStep ( "check request received" , ( ) = >
{
multiplayerClient . Verify ( m = > m . SendMatchRequest ( It . IsAny < StopCountdownRequest > ( ) ) , Times . Once ) ;
} ) ;
2022-03-17 18:26:42 +08:00
}
[Test]
public void TestReadyAndUnReadyDuringCountdown ( )
{
2022-04-13 19:28:53 +08:00
AddStep ( "add second user as host" , ( ) = > addUser ( new APIUser { Id = 2 , Username = "Another user" } , true ) ) ;
2022-03-17 18:26:42 +08:00
2022-04-13 19:28:53 +08:00
AddStep ( "start countdown" , ( ) = > setRoomCountdown ( TimeSpan . FromMinutes ( 1 ) ) ) ;
2022-03-17 18:26:42 +08:00
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:28:53 +08:00
AddUntilStep ( "user is ready" , ( ) = > localUser . State = = MultiplayerUserState . Ready ) ;
2022-03-17 18:26:42 +08:00
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:28:53 +08:00
AddUntilStep ( "user is idle" , ( ) = > localUser . State = = MultiplayerUserState . Idle ) ;
2022-03-17 18:26:42 +08:00
}
[Test]
2022-03-26 13:43:41 +08:00
public void TestCountdownWhileSpectating ( )
2022-03-17 18:26:42 +08:00
{
2022-04-13 16:02:53 +08:00
AddStep ( "set spectating" , ( ) = > changeUserState ( API . LocalUser . Value . OnlineID , MultiplayerUserState . Spectating ) ) ;
AddUntilStep ( "local user is spectating" , ( ) = > multiplayerClient . Object . LocalUser ? . State = = MultiplayerUserState . Spectating ) ;
2022-03-17 18:26:42 +08:00
2022-03-24 13:28:38 +08:00
AddAssert ( "countdown button is visible" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . Single ( ) . IsPresent ) ;
2022-03-26 13:43:41 +08:00
AddAssert ( "countdown button enabled" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . Single ( ) . Enabled . Value ) ;
2022-03-17 18:26:42 +08:00
2022-04-13 16:02:53 +08:00
AddStep ( "add second user" , ( ) = > addUser ( new APIUser { Id = 2 , Username = "Another user" } ) ) ;
2022-03-24 13:28:38 +08:00
AddAssert ( "countdown button enabled" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . Single ( ) . Enabled . Value ) ;
2022-03-17 18:26:42 +08:00
2022-04-13 16:02:53 +08:00
AddStep ( "set second user ready" , ( ) = > changeUserState ( 2 , MultiplayerUserState . Ready ) ) ;
2022-03-26 13:43:41 +08:00
AddAssert ( "countdown button enabled" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . Single ( ) . Enabled . Value ) ;
2022-03-17 18:26:42 +08:00
}
[Test]
public void TestBecomeHostDuringCountdownAndReady ( )
{
AddStep ( "add second user as host" , ( ) = >
{
2022-04-13 19:38:39 +08:00
addUser ( new APIUser { Id = 2 , Username = "Another user" } , true ) ;
2022-03-17 18:26:42 +08:00
} ) ;
2022-04-13 16:02:53 +08:00
AddStep ( "start countdown" , ( ) = > multiplayerClient . Object . SendMatchRequest ( new StartMatchCountdownRequest { Duration = TimeSpan . FromMinutes ( 1 ) } ) . WaitSafely ( ) ) ;
AddUntilStep ( "countdown started" , ( ) = > multiplayerClient . Object . Room ? . Countdown ! = null ) ;
2022-03-17 18:26:42 +08:00
2022-04-13 19:38:39 +08:00
AddStep ( "transfer host to local user" , ( ) = > transferHost ( localUser ) ) ;
2022-04-13 16:02:53 +08:00
AddUntilStep ( "local user is host" , ( ) = > multiplayerClient . Object . Room ? . Host ? . Equals ( multiplayerClient . Object . LocalUser ) = = true ) ;
2022-03-17 18:26:42 +08:00
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 16:02:53 +08:00
AddUntilStep ( "local user became ready" , ( ) = > multiplayerClient . Object . LocalUser ? . State = = MultiplayerUserState . Ready ) ;
AddAssert ( "countdown still active" , ( ) = > multiplayerClient . Object . Room ? . Countdown ! = null ) ;
2022-03-17 18:26:42 +08:00
}
2022-03-25 16:12:00 +08:00
[Test]
public void TestCountdownButtonVisibilityWithAutoStartEnablement ( )
{
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 16:02:53 +08:00
AddUntilStep ( "local user became ready" , ( ) = > multiplayerClient . Object . LocalUser ? . State = = MultiplayerUserState . Ready ) ;
2022-03-25 16:12:00 +08:00
AddUntilStep ( "countdown button visible" , ( ) = > this . ChildrenOfType < MultiplayerCountdownButton > ( ) . Single ( ) . IsPresent ) ;
2022-04-13 16:02:53 +08:00
AddStep ( "enable auto start" , ( ) = > multiplayerClient . Object . ChangeSettings ( new MultiplayerRoomSettings { AutoStartDuration = TimeSpan . FromMinutes ( 1 ) } ) . WaitSafely ( ) ) ;
2022-03-25 16:12:00 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 16:02:53 +08:00
AddUntilStep ( "local user became ready" , ( ) = > multiplayerClient . Object . LocalUser ? . State = = MultiplayerUserState . Ready ) ;
2022-03-25 16:12:00 +08:00
AddUntilStep ( "countdown button not visible" , ( ) = > ! this . ChildrenOfType < MultiplayerCountdownButton > ( ) . Single ( ) . IsPresent ) ;
}
[Test]
public void TestClickingReadyButtonUnReadiesDuringAutoStart ( )
{
2022-04-13 16:02:53 +08:00
AddStep ( "enable auto start" , ( ) = > multiplayerClient . Object . ChangeSettings ( new MultiplayerRoomSettings { AutoStartDuration = TimeSpan . FromMinutes ( 1 ) } ) . WaitSafely ( ) ) ;
2022-03-25 16:12:00 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 16:02:53 +08:00
AddUntilStep ( "local user became ready" , ( ) = > multiplayerClient . Object . LocalUser ? . State = = MultiplayerUserState . Ready ) ;
2022-03-25 16:12:00 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 16:02:53 +08:00
AddUntilStep ( "local user became idle" , ( ) = > multiplayerClient . Object . LocalUser ? . State = = MultiplayerUserState . Idle ) ;
2022-03-25 16:12:00 +08:00
}
2021-01-05 11:00:15 +08:00
[Test]
public void TestDeletedBeatmapDisableReady ( )
{
OsuButton readyButton = null ;
2022-03-08 23:48:12 +08:00
AddUntilStep ( "ensure ready button enabled" , ( ) = >
2021-01-05 11:00:15 +08:00
{
2022-03-23 09:37:53 +08:00
readyButton = control . ChildrenOfType < OsuButton > ( ) . Single ( ) ;
2021-01-05 11:00:15 +08:00
return readyButton . Enabled . Value ;
} ) ;
2022-04-13 19:41:56 +08:00
AddStep ( "mark beatmap not available" , ( ) = > beatmapAvailability . Value = BeatmapAvailability . NotDownloaded ( ) ) ;
2022-03-08 23:48:12 +08:00
AddUntilStep ( "ready button disabled" , ( ) = > ! readyButton . Enabled . Value ) ;
2022-04-13 19:41:56 +08:00
AddStep ( "mark beatmap available" , ( ) = > beatmapAvailability . Value = BeatmapAvailability . LocallyAvailable ( ) ) ;
2022-03-08 23:48:12 +08:00
AddUntilStep ( "ready button enabled back" , ( ) = > readyButton . Enabled . Value ) ;
2021-01-05 11:00:15 +08:00
}
2020-12-19 01:59:11 +08:00
[Test]
public void TestToggleStateWhenNotHost ( )
{
AddStep ( "add second user as host" , ( ) = >
{
2022-04-13 19:38:39 +08:00
addUser ( new APIUser { Id = 2 , Username = "Another user" } , true ) ;
2020-12-19 01:59:11 +08:00
} ) ;
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user is ready" , ( ) = > localUser . State = = MultiplayerUserState . Ready ) ;
2020-12-19 01:59:11 +08:00
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user is idle" , ( ) = > localUser . State = = MultiplayerUserState . Idle ) ;
2020-12-19 01:59:11 +08:00
}
[TestCase(true)]
[TestCase(false)]
public void TestToggleStateWhenHost ( bool allReady )
{
AddStep ( "setup" , ( ) = >
{
2022-04-13 19:38:39 +08:00
transferHost ( multiplayerRoom . Users [ 0 ] ) ;
2020-12-19 01:59:11 +08:00
if ( ! allReady )
2022-04-13 16:02:53 +08:00
addUser ( new APIUser { Id = 2 , Username = "Another user" } ) ;
2020-12-19 01:59:11 +08:00
} ) ;
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user is ready" , ( ) = > localUser . State = = MultiplayerUserState . Ready ) ;
2020-12-19 01:59:11 +08:00
2020-12-29 03:59:38 +08:00
verifyGameplayStartFlow ( ) ;
2020-12-19 01:59:11 +08:00
}
[Test]
public void TestBecomeHostWhileReady ( )
{
2020-12-20 17:44:41 +08:00
AddStep ( "add host" , ( ) = >
{
2022-04-13 19:38:39 +08:00
addUser ( new APIUser { Id = 2 , Username = "Another user" } , true ) ;
2020-12-20 17:44:41 +08:00
} ) ;
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddStep ( "make user host" , ( ) = > transferHost ( localUser ) ) ;
2020-12-19 01:59:11 +08:00
2020-12-29 03:59:38 +08:00
verifyGameplayStartFlow ( ) ;
2020-12-19 01:59:11 +08:00
}
[Test]
public void TestLoseHostWhileReady ( )
{
AddStep ( "setup" , ( ) = >
{
2022-04-13 16:02:53 +08:00
addUser ( new APIUser { Id = 2 , Username = "Another user" } ) ;
2020-12-19 01:59:11 +08:00
} ) ;
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user is ready" , ( ) = > localUser . State = = MultiplayerUserState . Ready ) ;
2021-12-20 16:46:20 +08:00
2022-04-13 19:38:39 +08:00
AddStep ( "transfer host" , ( ) = > transferHost ( multiplayerRoom . Users [ 1 ] ) ) ;
2020-12-19 01:59:11 +08:00
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user is idle (match not started)" , ( ) = > localUser . State = = MultiplayerUserState . Idle ) ;
2022-03-23 14:40:50 +08:00
AddUntilStep ( "ready button enabled" , ( ) = > control . ChildrenOfType < OsuButton > ( ) . Single ( ) . Enabled . Value ) ;
2020-12-19 01:59:11 +08:00
}
2020-12-24 16:17:45 +08:00
[TestCase(true)]
[TestCase(false)]
public void TestManyUsersChangingState ( bool isHost )
{
const int users = 10 ;
AddStep ( "setup" , ( ) = >
{
2022-04-13 19:38:39 +08:00
transferHost ( localUser ) ;
2020-12-24 16:17:45 +08:00
for ( int i = 0 ; i < users ; i + + )
2022-04-13 19:38:39 +08:00
addUser ( new APIUser { Id = i , Username = "Another user" } , ! isHost & & i = = 2 ) ;
2020-12-24 16:17:45 +08:00
} ) ;
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2020-12-24 16:17:45 +08:00
AddRepeatStep ( "change user ready state" , ( ) = >
{
2022-04-13 16:02:53 +08:00
changeUserState ( RNG . Next ( 0 , users ) , RNG . NextBool ( ) ? MultiplayerUserState . Ready : MultiplayerUserState . Idle ) ;
2020-12-24 16:17:45 +08:00
} , 20 ) ;
AddRepeatStep ( "ready all users" , ( ) = >
{
2022-04-13 16:02:53 +08:00
var nextUnready = multiplayerClient . Object . Room ? . Users . FirstOrDefault ( c = > c . State = = MultiplayerUserState . Idle ) ;
2020-12-24 16:17:45 +08:00
if ( nextUnready ! = null )
2022-04-13 16:02:53 +08:00
changeUserState ( nextUnready . UserID , MultiplayerUserState . Ready ) ;
2020-12-24 16:17:45 +08:00
} , users ) ;
}
2020-12-29 03:59:38 +08:00
private void verifyGameplayStartFlow ( )
{
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user is ready" , ( ) = > localUser . State = = MultiplayerUserState . Ready ) ;
2022-03-24 13:28:38 +08:00
ClickButtonWhenEnabled < MultiplayerReadyButton > ( ) ;
2022-04-13 19:38:39 +08:00
AddUntilStep ( "user waiting for load" , ( ) = > localUser . State = = MultiplayerUserState . WaitingForLoad ) ;
2020-12-29 03:59:38 +08:00
2021-04-08 15:29:11 +08:00
AddStep ( "finish gameplay" , ( ) = >
{
2022-04-13 19:38:39 +08:00
changeUserState ( localUser . UserID , MultiplayerUserState . Loaded ) ;
changeUserState ( localUser . UserID , MultiplayerUserState . FinishedPlay ) ;
2021-04-08 15:29:11 +08:00
} ) ;
2022-03-23 09:37:53 +08:00
AddUntilStep ( "ready button enabled" , ( ) = > control . ChildrenOfType < OsuButton > ( ) . Single ( ) . Enabled . Value ) ;
2020-12-29 03:59:38 +08:00
}
2022-04-13 16:02:53 +08:00
2022-04-13 19:28:53 +08:00
private void setRoomCountdown ( TimeSpan duration )
{
multiplayerRoom . Countdown = new MatchStartCountdown { TimeRemaining = duration } ;
raiseRoomUpdated ( ) ;
}
2022-04-13 16:02:53 +08:00
private void changeUserState ( int userId , MultiplayerUserState newState )
{
multiplayerRoom . Users . Single ( u = > u . UserID = = userId ) . State = newState ;
raiseRoomUpdated ( ) ;
}
2022-04-13 19:28:53 +08:00
private void addUser ( APIUser user , bool asHost = false )
2022-04-13 16:02:53 +08:00
{
2022-04-13 19:28:53 +08:00
var multiplayerRoomUser = new MultiplayerRoomUser ( user . Id ) { User = user } ;
multiplayerRoom . Users . Add ( multiplayerRoomUser ) ;
if ( asHost )
2022-04-13 19:38:39 +08:00
transferHost ( multiplayerRoomUser ) ;
2022-04-13 19:28:53 +08:00
2022-04-13 16:02:53 +08:00
raiseRoomUpdated ( ) ;
}
2022-04-13 19:38:39 +08:00
private void transferHost ( MultiplayerRoomUser user )
{
multiplayerRoom . Host = user ;
raiseRoomUpdated ( ) ;
}
2022-04-13 16:02:53 +08:00
private void raiseRoomUpdated ( ) = > multiplayerClient . Raise ( m = > m . RoomUpdated - = null ) ;
2020-12-19 01:59:11 +08:00
}
}