2019-01-24 16:43:03 +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.
2018-12-11 16:32:01 +08:00
2018-12-27 20:12:32 +08:00
using System ;
2018-12-17 10:51:12 +08:00
using System.Diagnostics ;
2019-02-28 13:58:44 +08:00
using System.Linq ;
2018-12-17 10:51:12 +08:00
using System.Threading ;
2020-12-18 15:51:59 +08:00
using System.Threading.Tasks ;
2018-12-14 20:09:17 +08:00
using osu.Framework.Allocation ;
2019-02-21 18:04:31 +08:00
using osu.Framework.Bindables ;
2018-12-17 10:51:12 +08:00
using osu.Framework.Logging ;
2019-01-23 19:52:00 +08:00
using osu.Framework.Screens ;
2018-12-14 20:09:17 +08:00
using osu.Game.Online.API ;
2018-12-21 17:22:13 +08:00
using osu.Game.Online.Multiplayer ;
2019-02-27 15:17:04 +08:00
using osu.Game.Rulesets ;
2018-12-14 20:09:17 +08:00
using osu.Game.Scoring ;
2020-05-26 17:12:19 +08:00
using osu.Game.Screens.Multi.Ranking ;
2018-12-11 16:32:01 +08:00
using osu.Game.Screens.Play ;
2020-05-26 17:12:19 +08:00
using osu.Game.Screens.Ranking ;
2018-12-11 16:32:01 +08:00
namespace osu.Game.Screens.Multi.Play
{
public class TimeshiftPlayer : Player
{
2019-01-23 19:52:00 +08:00
public Action Exited ;
2019-02-05 18:00:01 +08:00
[Resolved(typeof(Room), nameof(Room.RoomID))]
2020-12-20 23:13:05 +08:00
protected Bindable < int? > RoomId { get ; private set ; }
2019-02-05 18:00:01 +08:00
2020-12-20 23:13:05 +08:00
protected readonly PlaylistItem PlaylistItem ;
protected int? Token { get ; private set ; }
2018-12-14 20:09:17 +08:00
[Resolved]
2019-03-13 11:56:47 +08:00
private IAPIProvider api { get ; set ; }
2018-12-14 20:09:17 +08:00
2019-02-27 15:17:04 +08:00
[Resolved]
private IBindable < RulesetInfo > ruleset { get ; set ; }
2020-12-20 23:06:44 +08:00
public TimeshiftPlayer ( PlaylistItem playlistItem , bool allowPause = true )
: base ( allowPause )
2018-12-14 20:09:17 +08:00
{
2020-12-20 23:13:05 +08:00
PlaylistItem = playlistItem ;
2018-12-14 20:09:17 +08:00
}
[BackgroundDependencyLoader]
private void load ( )
{
2020-12-20 23:13:05 +08:00
Token = null ;
2018-12-17 10:51:12 +08:00
bool failed = false ;
2019-02-27 15:17:04 +08:00
// Sanity checks to ensure that TimeshiftPlayer matches the settings for the current PlaylistItem
2020-12-20 23:13:05 +08:00
if ( Beatmap . Value . BeatmapInfo . OnlineBeatmapID ! = PlaylistItem . Beatmap . Value . OnlineBeatmapID )
2019-02-27 15:17:04 +08:00
throw new InvalidOperationException ( "Current Beatmap does not match PlaylistItem's Beatmap" ) ;
2020-12-20 23:13:05 +08:00
if ( ruleset . Value . ID ! = PlaylistItem . Ruleset . Value . ID )
2019-02-27 15:17:04 +08:00
throw new InvalidOperationException ( "Current Ruleset does not match PlaylistItem's Ruleset" ) ;
2020-12-20 23:13:05 +08:00
if ( ! PlaylistItem . RequiredMods . All ( m = > Mods . Value . Any ( m . Equals ) ) )
2019-02-27 15:17:04 +08:00
throw new InvalidOperationException ( "Current Mods do not match PlaylistItem's RequiredMods" ) ;
2020-12-20 23:13:05 +08:00
var req = new CreateRoomScoreRequest ( RoomId . Value ? ? 0 , PlaylistItem . ID , Game . VersionHash ) ;
req . Success + = r = > Token = r . ID ;
2018-12-17 10:51:12 +08:00
req . Failure + = e = >
{
failed = true ;
2020-08-11 09:59:28 +08:00
Logger . Error ( e , "Failed to retrieve a score submission token.\n\nThis may happen if you are running an old or non-official release of osu! (ie. you are self-compiling)." ) ;
2018-12-17 10:51:12 +08:00
Schedule ( ( ) = >
{
ValidForResume = false ;
2019-01-23 19:52:00 +08:00
this . Exit ( ) ;
2018-12-17 10:51:12 +08:00
} ) ;
} ;
2018-12-14 20:09:17 +08:00
api . Queue ( req ) ;
2018-12-17 10:51:12 +08:00
2020-12-20 23:13:05 +08:00
while ( ! failed & & ! Token . HasValue )
2018-12-17 10:51:12 +08:00
Thread . Sleep ( 1000 ) ;
2018-12-14 20:09:17 +08:00
}
2019-01-23 19:52:00 +08:00
public override bool OnExiting ( IScreen next )
{
if ( base . OnExiting ( next ) )
return true ;
Exited ? . Invoke ( ) ;
return false ;
}
2020-05-26 17:12:19 +08:00
protected override ResultsScreen CreateResults ( ScoreInfo score )
{
2020-12-20 23:13:05 +08:00
Debug . Assert ( RoomId . Value ! = null ) ;
return new TimeshiftResultsScreen ( score , RoomId . Value . Value , PlaylistItem , true ) ;
2020-05-26 17:12:19 +08:00
}
2020-12-18 15:51:59 +08:00
protected override Score CreateScore ( )
2018-12-14 20:09:17 +08:00
{
var score = base . CreateScore ( ) ;
2020-12-18 15:51:59 +08:00
score . ScoreInfo . TotalScore = ( int ) Math . Round ( ScoreProcessor . GetStandardisedScore ( ) ) ;
return score ;
}
2020-12-19 02:32:05 +08:00
protected override async Task SubmitScore ( Score score )
2020-12-18 15:51:59 +08:00
{
2020-12-19 02:32:05 +08:00
await base . SubmitScore ( score ) ;
2020-12-20 23:13:05 +08:00
Debug . Assert ( Token ! = null ) ;
2018-12-17 10:51:12 +08:00
2020-12-19 02:17:04 +08:00
var tcs = new TaskCompletionSource < bool > ( ) ;
2020-12-20 23:13:05 +08:00
var request = new SubmitRoomScoreRequest ( Token . Value , RoomId . Value ? ? 0 , PlaylistItem . ID , score . ScoreInfo ) ;
2020-12-18 15:56:22 +08:00
request . Success + = s = >
{
score . ScoreInfo . OnlineScoreID = s . ID ;
2020-12-19 02:17:04 +08:00
tcs . SetResult ( true ) ;
2020-12-18 15:56:22 +08:00
} ;
request . Failure + = e = >
{
Logger . Error ( e , "Failed to submit score" ) ;
2020-12-19 02:17:04 +08:00
tcs . SetResult ( false ) ;
2020-12-18 15:56:22 +08:00
} ;
2018-12-14 20:09:17 +08:00
api . Queue ( request ) ;
2020-12-19 02:17:04 +08:00
await tcs . Task ;
2018-12-14 20:09:17 +08:00
}
2018-12-21 17:22:13 +08:00
2019-01-23 19:52:00 +08:00
protected override void Dispose ( bool isDisposing )
{
base . Dispose ( isDisposing ) ;
Exited = null ;
}
2018-12-14 20:09:17 +08:00
}
2018-12-11 16:32:01 +08:00
}