2020-12-18 16:14:50 +00: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.
#nullable enable
2021-03-01 08:24:54 +00:00
using System ;
2021-02-01 08:54:56 +00:00
using System.Collections.Generic ;
2020-12-18 16:14:50 +00:00
using System.Diagnostics ;
using System.Linq ;
2021-03-01 08:24:54 +00:00
using System.Threading ;
2020-12-18 16:14:50 +00:00
using System.Threading.Tasks ;
using osu.Framework.Allocation ;
using osu.Framework.Bindables ;
2021-03-01 08:24:54 +00:00
using osu.Game.Beatmaps ;
2020-12-18 16:14:50 +00:00
using osu.Game.Online.API ;
2020-12-25 04:38:11 +00:00
using osu.Game.Online.Multiplayer ;
2021-01-03 01:32:50 +00:00
using osu.Game.Online.Rooms ;
2021-02-01 08:54:56 +00:00
using osu.Game.Rulesets.Mods ;
2020-12-18 16:14:50 +00:00
using osu.Game.Users ;
2020-12-25 04:38:11 +00:00
namespace osu.Game.Tests.Visual.Multiplayer
2020-12-18 16:14:50 +00:00
{
2021-06-25 09:02:53 +00:00
/// <summary>
/// A <see cref="MultiplayerClient"/> for use in multiplayer test scenes. Should generally not be used by itself outside of a <see cref="MultiplayerTestScene"/>.
/// </summary>
2021-05-20 06:39:45 +00:00
public class TestMultiplayerClient : MultiplayerClient
2020-12-18 16:14:50 +00:00
{
2020-12-18 16:16:00 +00:00
public override IBindable < bool > IsConnected = > isConnected ;
private readonly Bindable < bool > isConnected = new Bindable < bool > ( true ) ;
2020-12-18 16:14:50 +00:00
2021-05-11 10:01:41 +00:00
public Room ? APIRoom { get ; private set ; }
2021-04-22 14:22:44 +00:00
public Action < MultiplayerRoom > ? RoomSetupAction ;
2020-12-18 16:14:50 +00:00
[Resolved]
private IAPIProvider api { get ; set ; } = null ! ;
2021-03-01 08:24:54 +00:00
[Resolved]
private BeatmapManager beatmaps { get ; set ; } = null ! ;
2021-03-03 10:40:19 +00:00
private readonly TestMultiplayerRoomManager roomManager ;
public TestMultiplayerClient ( TestMultiplayerRoomManager roomManager )
{
this . roomManager = roomManager ;
}
2020-12-18 16:16:00 +00:00
public void Connect ( ) = > isConnected . Value = true ;
public void Disconnect ( ) = > isConnected . Value = false ;
2020-12-18 16:14:50 +00:00
public void AddUser ( User user ) = > ( ( IMultiplayerClient ) this ) . UserJoined ( new MultiplayerRoomUser ( user . Id ) { User = user } ) ;
2020-12-28 05:56:53 +00:00
public void AddNullUser ( int userId ) = > ( ( IMultiplayerClient ) this ) . UserJoined ( new MultiplayerRoomUser ( userId ) ) ;
2020-12-18 16:14:50 +00:00
public void RemoveUser ( User user )
{
Debug . Assert ( Room ! = null ) ;
2020-12-23 20:00:47 +00:00
( ( IMultiplayerClient ) this ) . UserLeft ( new MultiplayerRoomUser ( user . Id ) ) ;
2020-12-18 16:14:50 +00:00
Schedule ( ( ) = >
{
if ( Room . Users . Any ( ) )
TransferHost ( Room . Users . First ( ) . UserID ) ;
} ) ;
}
2021-04-07 07:35:36 +00:00
public void ChangeRoomState ( MultiplayerRoomState newState )
{
Debug . Assert ( Room ! = null ) ;
( ( IMultiplayerClient ) this ) . RoomStateChanged ( newState ) ;
}
2020-12-18 16:14:50 +00:00
public void ChangeUserState ( int userId , MultiplayerUserState newState )
{
Debug . Assert ( Room ! = null ) ;
( ( IMultiplayerClient ) this ) . UserStateChanged ( userId , newState ) ;
Schedule ( ( ) = >
{
switch ( newState )
{
case MultiplayerUserState . Loaded :
if ( Room . Users . All ( u = > u . State ! = MultiplayerUserState . WaitingForLoad ) )
{
2021-04-07 11:46:30 +00:00
ChangeRoomState ( MultiplayerRoomState . Playing ) ;
2020-12-18 16:14:50 +00:00
foreach ( var u in Room . Users . Where ( u = > u . State = = MultiplayerUserState . Loaded ) )
ChangeUserState ( u . UserID , MultiplayerUserState . Playing ) ;
( ( IMultiplayerClient ) this ) . MatchStarted ( ) ;
}
break ;
case MultiplayerUserState . FinishedPlay :
if ( Room . Users . All ( u = > u . State ! = MultiplayerUserState . Playing ) )
{
2021-04-07 11:46:30 +00:00
ChangeRoomState ( MultiplayerRoomState . Open ) ;
2020-12-18 16:14:50 +00:00
foreach ( var u in Room . Users . Where ( u = > u . State = = MultiplayerUserState . FinishedPlay ) )
ChangeUserState ( u . UserID , MultiplayerUserState . Results ) ;
( ( IMultiplayerClient ) this ) . ResultsReady ( ) ;
}
break ;
}
} ) ;
}
2021-01-03 01:32:50 +00:00
public void ChangeUserBeatmapAvailability ( int userId , BeatmapAvailability newBeatmapAvailability )
{
Debug . Assert ( Room ! = null ) ;
( ( IMultiplayerClient ) this ) . UserBeatmapAvailabilityChanged ( userId , newBeatmapAvailability ) ;
}
2020-12-18 16:14:50 +00:00
protected override Task < MultiplayerRoom > JoinRoom ( long roomId )
{
2021-03-03 10:40:19 +00:00
var apiRoom = roomManager . Rooms . Single ( r = > r . RoomID . Value = = roomId ) ;
2020-12-18 16:14:50 +00:00
2021-04-22 14:22:44 +00:00
var localUser = new MultiplayerRoomUser ( api . LocalUser . Value . Id )
2021-03-01 08:24:32 +00:00
{
User = api . LocalUser . Value
} ;
2020-12-18 16:14:50 +00:00
2021-03-01 08:24:32 +00:00
var room = new MultiplayerRoom ( roomId )
{
Settings =
{
Name = apiRoom . Name . Value ,
BeatmapID = apiRoom . Playlist . Last ( ) . BeatmapID ,
RulesetID = apiRoom . Playlist . Last ( ) . RulesetID ,
BeatmapChecksum = apiRoom . Playlist . Last ( ) . Beatmap . Value . MD5Hash ,
RequiredMods = apiRoom . Playlist . Last ( ) . RequiredMods . Select ( m = > new APIMod ( m ) ) . ToArray ( ) ,
AllowedMods = apiRoom . Playlist . Last ( ) . AllowedMods . Select ( m = > new APIMod ( m ) ) . ToArray ( ) ,
PlaylistItemId = apiRoom . Playlist . Last ( ) . ID
} ,
2021-04-22 14:22:44 +00:00
Users = { localUser } ,
Host = localUser
2021-03-01 08:24:32 +00:00
} ;
2020-12-18 16:14:50 +00:00
2021-04-22 14:22:44 +00:00
RoomSetupAction ? . Invoke ( room ) ;
RoomSetupAction = null ;
2021-05-11 10:01:41 +00:00
APIRoom = apiRoom ;
2020-12-18 16:14:50 +00:00
return Task . FromResult ( room ) ;
}
2021-05-11 10:01:41 +00:00
protected override Task LeaveRoomInternal ( )
{
APIRoom = null ;
return Task . CompletedTask ;
}
2021-01-25 11:41:51 +00:00
2020-12-18 16:14:50 +00:00
public override Task TransferHost ( int userId ) = > ( ( IMultiplayerClient ) this ) . HostChanged ( userId ) ;
public override async Task ChangeSettings ( MultiplayerRoomSettings settings )
{
Debug . Assert ( Room ! = null ) ;
2021-03-08 03:57:16 +00:00
await ( ( IMultiplayerClient ) this ) . SettingsChanged ( settings ) . ConfigureAwait ( false ) ;
2020-12-18 16:14:50 +00:00
foreach ( var user in Room . Users . Where ( u = > u . State = = MultiplayerUserState . Ready ) )
ChangeUserState ( user . UserID , MultiplayerUserState . Idle ) ;
}
public override Task ChangeState ( MultiplayerUserState newState )
{
ChangeUserState ( api . LocalUser . Value . Id , newState ) ;
return Task . CompletedTask ;
}
2021-01-03 01:32:50 +00:00
public override Task ChangeBeatmapAvailability ( BeatmapAvailability newBeatmapAvailability )
{
ChangeUserBeatmapAvailability ( api . LocalUser . Value . Id , newBeatmapAvailability ) ;
return Task . CompletedTask ;
}
2021-02-01 08:57:32 +00:00
public void ChangeUserMods ( int userId , IEnumerable < Mod > newMods )
= > ChangeUserMods ( userId , newMods . Select ( m = > new APIMod ( m ) ) . ToList ( ) ) ;
2021-02-01 08:54:56 +00:00
2021-02-01 08:57:32 +00:00
public void ChangeUserMods ( int userId , IEnumerable < APIMod > newMods )
2021-02-01 08:54:56 +00:00
{
Debug . Assert ( Room ! = null ) ;
2021-02-01 08:57:32 +00:00
( ( IMultiplayerClient ) this ) . UserModsChanged ( userId , newMods . ToList ( ) ) ;
2021-02-01 08:54:56 +00:00
}
2021-02-01 08:57:32 +00:00
public override Task ChangeUserMods ( IEnumerable < APIMod > newMods )
2021-02-01 08:54:56 +00:00
{
2021-02-01 08:57:32 +00:00
ChangeUserMods ( api . LocalUser . Value . Id , newMods ) ;
2021-02-01 08:54:56 +00:00
return Task . CompletedTask ;
}
2020-12-20 09:24:13 +00:00
public override Task StartMatch ( )
2020-12-18 16:14:50 +00:00
{
Debug . Assert ( Room ! = null ) ;
2021-04-07 11:46:30 +00:00
ChangeRoomState ( MultiplayerRoomState . WaitingForLoad ) ;
2020-12-18 16:14:50 +00:00
foreach ( var user in Room . Users . Where ( u = > u . State = = MultiplayerUserState . Ready ) )
ChangeUserState ( user . UserID , MultiplayerUserState . WaitingForLoad ) ;
2020-12-20 09:24:13 +00:00
return ( ( IMultiplayerClient ) this ) . LoadRequested ( ) ;
2020-12-18 16:14:50 +00:00
}
2021-03-01 08:24:54 +00:00
protected override Task < BeatmapSetInfo > GetOnlineBeatmapSet ( int beatmapId , CancellationToken cancellationToken = default )
{
Debug . Assert ( Room ! = null ) ;
2021-03-03 10:40:19 +00:00
var apiRoom = roomManager . Rooms . Single ( r = > r . RoomID . Value = = Room . RoomID ) ;
2021-03-01 08:24:54 +00:00
var set = apiRoom . Playlist . FirstOrDefault ( p = > p . BeatmapID = = beatmapId ) ? . Beatmap . Value . BeatmapSet
? ? beatmaps . QueryBeatmap ( b = > b . OnlineBeatmapID = = beatmapId ) ? . BeatmapSet ;
if ( set = = null )
throw new InvalidOperationException ( "Beatmap not found." ) ;
return Task . FromResult ( set ) ;
}
2020-12-18 16:14:50 +00:00
}
}