1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-14 02:22:56 +08:00

Add support for gameplay abort/force start

This commit is contained in:
Dan Balasescu 2022-04-21 22:55:13 +09:00
parent 59622deb1f
commit 41355384bd
4 changed files with 45 additions and 8 deletions

View File

@ -3,6 +3,7 @@
using System.Diagnostics;
using osu.Framework.Allocation;
using osu.Framework.Logging;
using osu.Framework.Screens;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.OnlinePlay.Components;
@ -20,6 +21,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
base.LoadComplete();
client.RoomUpdated += onRoomUpdated;
client.LoadAborted += onLoadAborted;
onRoomUpdated();
}
@ -35,6 +37,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
transitionFromResults();
}
private void onLoadAborted()
{
// If the server aborts gameplay for this user (due to loading too slow), exit gameplay screens.
if (!this.IsCurrentScreen())
{
Logger.Log("Gameplay aborted because loading the beatmap took too long.", LoggingTarget.Runtime, LogLevel.Important);
this.MakeCurrent();
}
}
public override void OnResuming(IScreen last)
{
base.OnResuming(last);
@ -42,9 +54,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
if (client.Room == null)
return;
Debug.Assert(client.LocalUser != null);
if (!(last is MultiplayerPlayerLoader playerLoader))
return;
// Nothing needs to be done if already in the idle state (e.g. via load being aborted by the server).
if (client.LocalUser.State == MultiplayerUserState.Idle)
return;
// If gameplay wasn't finished, then we have a simple path back to the idle state by aborting gameplay.
if (!playerLoader.GameplayPassed)
{

View File

@ -133,6 +133,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
failAndBail();
}
}), true);
client.ChangeState(MultiplayerUserState.Loaded)
.ContinueWith(task => failAndBail(task.Exception?.Message ?? "Server error"), TaskContinuationOptions.NotOnRanToCompletion);
}
protected override void LoadComplete()
@ -144,10 +147,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
protected override void StartGameplay()
{
// block base call, but let the server know we are ready to start.
loadingDisplay.Show();
client.ChangeState(MultiplayerUserState.Loaded).ContinueWith(task => failAndBail(task.Exception?.Message ?? "Server error"), TaskContinuationOptions.NotOnRanToCompletion);
if (client.LocalUser?.State == MultiplayerUserState.Loaded)
{
// block base call, but let the server know we are ready to start.
loadingDisplay.Show();
client.ChangeState(MultiplayerUserState.ReadyForGameplay);
}
}
private void failAndBail(string message = null)

View File

@ -2,7 +2,9 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Framework.Screens;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.Play;
namespace osu.Game.Screens.OnlinePlay.Multiplayer
@ -11,6 +13,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
public bool GameplayPassed => player?.GameplayState.HasPassed == true;
[Resolved]
private MultiplayerClient multiplayerClient { get; set; }
private Player player;
public MultiplayerPlayerLoader(Func<Player> createPlayer)
@ -18,6 +23,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{
}
protected override bool ReadyForGameplay =>
base.ReadyForGameplay
// The server is forcefully starting gameplay.
|| multiplayerClient.LocalUser?.State == MultiplayerUserState.Playing;
public override void OnSuspending(IScreen next)
{
base.OnSuspending(next);

View File

@ -92,11 +92,15 @@ namespace osu.Game.Screens.Play
!playerConsumed
// don't push unless the player is completely loaded
&& CurrentPlayer?.LoadState == LoadState.Ready
// don't push if the user is hovering one of the panes, unless they are idle.
&& (IsHovered || idleTracker.IsIdle.Value)
// don't push if the user is dragging a slider or otherwise.
// don't push unless the player is ready to start gameplay
&& ReadyForGameplay;
protected virtual bool ReadyForGameplay =>
// not ready if the user is hovering one of the panes, unless they are idle.
(IsHovered || idleTracker.IsIdle.Value)
// not ready if the user is dragging a slider or otherwise.
&& inputManager.DraggedDrawable == null
// don't push if a focused overlay is visible, like settings.
// not ready if a focused overlay is visible, like settings.
&& inputManager.FocusedDrawable == null;
private readonly Func<Player> createPlayer;