mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 13:37:25 +08:00
Add support for starting/stopping countdowns
This commit is contained in:
parent
3b938865a1
commit
72843a6797
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
@ -16,11 +17,13 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.Countdown;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osuTK;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Multiplayer
|
||||
{
|
||||
@ -68,6 +71,139 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestStartWithCountdown()
|
||||
{
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("countdown button shown", () => this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().SingleOrDefault()?.IsPresent == true);
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.CountdownButton>();
|
||||
AddStep("click the first countdown button", () =>
|
||||
{
|
||||
var popoverButton = this.ChildrenOfType<MultiplayerReadyButton.CountdownButton.PopoverButton>().First();
|
||||
InputManager.MoveMouseTo(popoverButton);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddAssert("countdown button not visible", () => !this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().Single().IsPresent);
|
||||
AddStep("finish countdown", () => MultiplayerClient.FinishCountDown());
|
||||
AddUntilStep("match started", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.WaitingForLoad);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCancelCountdown()
|
||||
{
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("countdown button shown", () => this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().SingleOrDefault()?.IsPresent == true);
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.CountdownButton>();
|
||||
AddStep("click the first countdown button", () =>
|
||||
{
|
||||
var popoverButton = this.ChildrenOfType<MultiplayerReadyButton.CountdownButton.PopoverButton>().First();
|
||||
InputManager.MoveMouseTo(popoverButton);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
|
||||
AddStep("finish countdown", () => MultiplayerClient.FinishCountDown());
|
||||
AddUntilStep("match not started", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestReadyAndUnReadyDuringCountdown()
|
||||
{
|
||||
AddStep("add second user as host", () =>
|
||||
{
|
||||
MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
||||
MultiplayerClient.TransferHost(2);
|
||||
});
|
||||
|
||||
AddStep("start with countdown", () => MultiplayerClient.SendMatchRequest(new MatchStartCountdownRequest { Delay = TimeSpan.FromMinutes(2) }));
|
||||
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready);
|
||||
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCountdownButtonEnablementAndVisibilityWhileSpectating()
|
||||
{
|
||||
AddStep("set spectating", () => MultiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
||||
AddUntilStep("local user is spectating", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||
|
||||
AddAssert("countdown button is visible", () => this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().Single().IsPresent);
|
||||
AddAssert("countdown button disabled", () => !this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().Single().Enabled.Value);
|
||||
|
||||
AddStep("add second user", () => MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }));
|
||||
AddAssert("countdown button disabled", () => !this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().Single().Enabled.Value);
|
||||
|
||||
AddStep("set second user ready", () => MultiplayerClient.ChangeUserState(2, MultiplayerUserState.Ready));
|
||||
AddAssert("countdown button enabled", () => this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().Single().Enabled.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSpectatingDuringCountdownWithNoReadyUsersCancelsCountdown()
|
||||
{
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("countdown button shown", () => this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().SingleOrDefault()?.IsPresent == true);
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.CountdownButton>();
|
||||
AddStep("click the first countdown button", () =>
|
||||
{
|
||||
var popoverButton = this.ChildrenOfType<MultiplayerReadyButton.CountdownButton.PopoverButton>().First();
|
||||
InputManager.MoveMouseTo(popoverButton);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("set spectating", () => MultiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
||||
AddUntilStep("local user is spectating", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||
|
||||
AddStep("finish countdown", () => MultiplayerClient.FinishCountDown());
|
||||
AddUntilStep("match not started", () => MultiplayerClient.Room?.State == MultiplayerRoomState.Open);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestReadyButtonEnabledWhileSpectatingDuringCountdown()
|
||||
{
|
||||
AddStep("add second user", () => MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }));
|
||||
AddStep("set second user ready", () => MultiplayerClient.ChangeUserState(2, MultiplayerUserState.Ready));
|
||||
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("countdown button shown", () => this.ChildrenOfType<MultiplayerReadyButton.CountdownButton>().SingleOrDefault()?.IsPresent == true);
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.CountdownButton>();
|
||||
AddStep("click the first countdown button", () =>
|
||||
{
|
||||
var popoverButton = this.ChildrenOfType<MultiplayerReadyButton.CountdownButton.PopoverButton>().First();
|
||||
InputManager.MoveMouseTo(popoverButton);
|
||||
InputManager.Click(MouseButton.Left);
|
||||
});
|
||||
|
||||
AddStep("set spectating", () => MultiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating));
|
||||
AddUntilStep("local user is spectating", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating);
|
||||
|
||||
AddAssert("ready button enabled", () => this.ChildrenOfType<MultiplayerReadyButton.ReadyButton>().Single().Enabled.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBecomeHostDuringCountdownAndReady()
|
||||
{
|
||||
AddStep("add second user as host", () =>
|
||||
{
|
||||
MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" });
|
||||
MultiplayerClient.TransferHost(2);
|
||||
});
|
||||
|
||||
AddStep("start countdown", () => MultiplayerClient.SendMatchRequest(new MatchStartCountdownRequest { Delay = TimeSpan.FromMinutes(1) }));
|
||||
AddUntilStep("countdown started", () => MultiplayerClient.Room?.Countdown != null);
|
||||
|
||||
AddStep("transfer host to local user", () => MultiplayerClient.TransferHost(API.LocalUser.Value.OnlineID));
|
||||
AddUntilStep("local user is host", () => MultiplayerClient.Room?.Host?.Equals(MultiplayerClient.LocalUser) == true);
|
||||
|
||||
ClickButtonWhenEnabled<MultiplayerReadyButton.ReadyButton>();
|
||||
AddUntilStep("local user became ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready);
|
||||
AddAssert("countdown still active", () => MultiplayerClient.Room?.Countdown != null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeletedBeatmapDisableReady()
|
||||
{
|
||||
|
@ -16,6 +16,7 @@ using osu.Framework.Logging;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer.Countdown;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Online.Rooms.RoomStatuses;
|
||||
using osu.Game.Rulesets;
|
||||
@ -534,7 +535,24 @@ namespace osu.Game.Online.Multiplayer
|
||||
|
||||
public Task MatchEvent(MatchServerEvent e)
|
||||
{
|
||||
// not used by any match types just yet.
|
||||
if (Room == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
Scheduler.Add(() =>
|
||||
{
|
||||
if (Room == null)
|
||||
return;
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case CountdownChangedEvent countdownChangedEvent:
|
||||
Room.Countdown = countdownChangedEvent.Countdown;
|
||||
break;
|
||||
}
|
||||
|
||||
RoomUpdated?.Invoke();
|
||||
}, false);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@ -14,20 +14,18 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
public abstract class ReadyButton : TriangleButton, IHasTooltip
|
||||
{
|
||||
public new readonly BindableBool Enabled = new BindableBool();
|
||||
|
||||
private IBindable<BeatmapAvailability> availability;
|
||||
protected readonly IBindable<BeatmapAvailability> Availability = new Bindable<BeatmapAvailability>();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OnlinePlayBeatmapAvailabilityTracker beatmapTracker)
|
||||
{
|
||||
availability = beatmapTracker.Availability.GetBoundCopy();
|
||||
|
||||
availability.BindValueChanged(_ => updateState());
|
||||
Availability.BindTo(beatmapTracker.Availability);
|
||||
Availability.BindValueChanged(_ => updateState());
|
||||
Enabled.BindValueChanged(_ => updateState(), true);
|
||||
}
|
||||
|
||||
private void updateState() =>
|
||||
base.Enabled.Value = availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value;
|
||||
base.Enabled.Value = Availability.Value.State == DownloadState.LocallyAvailable && Enabled.Value;
|
||||
|
||||
public virtual LocalisableString TooltipText
|
||||
{
|
||||
@ -36,7 +34,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
||||
if (Enabled.Value)
|
||||
return string.Empty;
|
||||
|
||||
if (availability.Value.State != DownloadState.LocallyAvailable)
|
||||
if (Availability.Value.State != DownloadState.LocallyAvailable)
|
||||
return "Beatmap not downloaded";
|
||||
|
||||
return string.Empty;
|
||||
|
@ -17,12 +17,14 @@ using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.Countdown;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
@ -124,6 +126,14 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
return;
|
||||
}
|
||||
|
||||
// Local user is the room host and is in a ready state.
|
||||
// The only action they can take is to stop a countdown if one's currently running.
|
||||
if (Room.Countdown != null)
|
||||
{
|
||||
stopCountdown();
|
||||
return;
|
||||
}
|
||||
|
||||
// And if a countdown isn't running, start the match.
|
||||
startMatch();
|
||||
|
||||
@ -131,6 +141,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
|
||||
void toggleReady() => Client.ToggleReady().ContinueWith(_ => endOperation());
|
||||
|
||||
void stopCountdown() => Client.SendMatchRequest(new StopCountdownRequest()).ContinueWith(_ => endOperation());
|
||||
|
||||
void startMatch() => Client.StartMatch().ContinueWith(t =>
|
||||
{
|
||||
// accessing Exception here silences any potential errors from the antecedent task
|
||||
@ -146,6 +158,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
|
||||
private void startCountdown(TimeSpan duration)
|
||||
{
|
||||
Debug.Assert(clickOperation == null);
|
||||
clickOperation = ongoingOperationTracker.BeginOperation();
|
||||
|
||||
Client.SendMatchRequest(new MatchStartCountdownRequest { Delay = duration }).ContinueWith(_ => endOperation());
|
||||
}
|
||||
|
||||
private void endOperation()
|
||||
@ -167,16 +183,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
int newCountReady = Room.Users.Count(u => u.State == MultiplayerUserState.Ready);
|
||||
int newCountTotal = Room.Users.Count(u => u.State != MultiplayerUserState.Spectating);
|
||||
|
||||
switch (localUser?.State)
|
||||
if (Room.Countdown != null)
|
||||
countdownButton.Alpha = 0;
|
||||
else
|
||||
{
|
||||
default:
|
||||
countdownButton.Alpha = 0;
|
||||
break;
|
||||
switch (localUser?.State)
|
||||
{
|
||||
default:
|
||||
countdownButton.Alpha = 0;
|
||||
break;
|
||||
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
countdownButton.Alpha = Room.Host?.Equals(localUser) == true ? 1 : 0;
|
||||
break;
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
countdownButton.Alpha = Room.Host?.Equals(localUser) == true ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
enabled.Value =
|
||||
@ -232,6 +253,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
onRoomUpdated();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (room?.Countdown != null)
|
||||
{
|
||||
// Update the countdown timer.
|
||||
onRoomUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
private void onRoomUpdated()
|
||||
{
|
||||
updateButtonText();
|
||||
@ -251,21 +283,39 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
int countReady = room.Users.Count(u => u.State == MultiplayerUserState.Ready);
|
||||
int countTotal = room.Users.Count(u => u.State != MultiplayerUserState.Spectating);
|
||||
|
||||
string countdownText = room.Countdown == null ? string.Empty : $"Starting in {room.Countdown.EndTime - DateTimeOffset.Now:mm\\:ss}";
|
||||
string countText = $"({countReady} / {countTotal} ready)";
|
||||
|
||||
switch (localUser?.State)
|
||||
if (room.Countdown != null)
|
||||
{
|
||||
default:
|
||||
Text = "Ready";
|
||||
break;
|
||||
switch (localUser?.State)
|
||||
{
|
||||
default:
|
||||
Text = $"Ready ({countdownText.ToLowerInvariant()})";
|
||||
break;
|
||||
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
Text = room.Host?.Equals(localUser) == true
|
||||
? $"Start match {countText}"
|
||||
: $"Waiting for host... {countText}";
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
Text = $"{countdownText} {countText}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (localUser?.State)
|
||||
{
|
||||
default:
|
||||
Text = "Ready";
|
||||
break;
|
||||
|
||||
break;
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
Text = room.Host?.Equals(localUser) == true
|
||||
? $"Start match {countText}"
|
||||
: $"Waiting for host... {countText}";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,20 +329,37 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
|
||||
var localUser = multiplayerClient.LocalUser;
|
||||
|
||||
switch (localUser?.State)
|
||||
if (room.Countdown != null)
|
||||
{
|
||||
default:
|
||||
setGreen();
|
||||
break;
|
||||
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
if (room?.Host?.Equals(localUser) == true)
|
||||
switch (localUser?.State)
|
||||
{
|
||||
default:
|
||||
setGreen();
|
||||
else
|
||||
setYellow();
|
||||
break;
|
||||
|
||||
break;
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
setYellow();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (localUser?.State)
|
||||
{
|
||||
default:
|
||||
setGreen();
|
||||
break;
|
||||
|
||||
case MultiplayerUserState.Spectating:
|
||||
case MultiplayerUserState.Ready:
|
||||
if (room?.Host?.Equals(localUser) == true)
|
||||
setGreen();
|
||||
else
|
||||
setYellow();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setYellow()
|
||||
@ -317,6 +384,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
if (multiplayerClient != null)
|
||||
multiplayerClient.RoomUpdated -= onRoomUpdated;
|
||||
}
|
||||
|
||||
public override LocalisableString TooltipText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (room?.Countdown != null && multiplayerClient.IsHost && multiplayerClient.LocalUser?.State == MultiplayerUserState.Ready)
|
||||
return "Cancel countdown";
|
||||
|
||||
return base.TooltipText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CountdownButton : IconButton, IHasPopover
|
||||
|
@ -7,12 +7,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.Countdown;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@ -114,12 +116,24 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
public void ChangeUserState(int userId, MultiplayerUserState newState)
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
((IMultiplayerClient)this).UserStateChanged(userId, newState);
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
switch (Room.State)
|
||||
{
|
||||
case MultiplayerRoomState.Open:
|
||||
// If there are no remaining ready users or the host is not ready, stop any existing countdown.
|
||||
// Todo: When we have an "automatic start" mode, this should also start a new countdown if any users _are_ ready.
|
||||
// Todo: This doesn't yet support non-match-start countdowns.
|
||||
bool shouldStopCountdown = Room.Users.All(u => u.State != MultiplayerUserState.Ready);
|
||||
shouldStopCountdown |= Room.Host?.State != MultiplayerUserState.Ready && Room.Host?.State != MultiplayerUserState.Spectating;
|
||||
|
||||
if (shouldStopCountdown)
|
||||
countdownStopSource?.Cancel();
|
||||
break;
|
||||
|
||||
case MultiplayerRoomState.WaitingForLoad:
|
||||
if (Room.Users.All(u => u.State != MultiplayerUserState.WaitingForLoad))
|
||||
{
|
||||
@ -282,6 +296,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private CancellationTokenSource? countdownFinishSource;
|
||||
private CancellationTokenSource? countdownStopSource;
|
||||
private Task countdownTask = Task.CompletedTask;
|
||||
|
||||
public void FinishCountDown() => countdownFinishSource?.Cancel();
|
||||
|
||||
public override async Task SendMatchRequest(MatchUserRequest request)
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
@ -289,6 +309,71 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case MatchStartCountdownRequest matchCountdownRequest:
|
||||
countdownStopSource?.Cancel();
|
||||
|
||||
var stopSource = countdownStopSource = new CancellationTokenSource();
|
||||
var finishSource = countdownFinishSource = new CancellationTokenSource();
|
||||
var cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(stopSource.Token, finishSource.Token);
|
||||
var countdown = new MatchStartCountdown { EndTime = DateTimeOffset.Now + matchCountdownRequest.Delay };
|
||||
|
||||
Task lastCountdownTask = countdownTask;
|
||||
countdownTask = start();
|
||||
|
||||
async Task start()
|
||||
{
|
||||
try
|
||||
{
|
||||
await lastCountdownTask;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
if (stopSource.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
Room.Countdown = countdown;
|
||||
MatchEvent(new CountdownChangedEvent { Countdown = countdown });
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(matchCountdownRequest.Delay, cancellationSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
if (Room.Countdown != countdown)
|
||||
return;
|
||||
|
||||
Room.Countdown = null;
|
||||
MatchEvent(new CountdownChangedEvent { Countdown = null });
|
||||
|
||||
using (cancellationSource)
|
||||
{
|
||||
if (stopSource.Token.IsCancellationRequested)
|
||||
return;
|
||||
}
|
||||
|
||||
StartMatch().WaitSafely();
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case StopCountdownRequest _:
|
||||
countdownStopSource?.Cancel();
|
||||
|
||||
Room.Countdown = null;
|
||||
await MatchEvent(new CountdownChangedEvent { Countdown = Room.Countdown });
|
||||
break;
|
||||
|
||||
case ChangeTeamRequest changeTeam:
|
||||
|
||||
TeamVersusRoomState roomState = (TeamVersusRoomState)Room.MatchState!;
|
||||
@ -307,7 +392,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
public override Task StartMatch()
|
||||
public override async Task StartMatch()
|
||||
{
|
||||
Debug.Assert(Room != null);
|
||||
|
||||
@ -315,7 +400,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready))
|
||||
ChangeUserState(user.UserID, MultiplayerUserState.WaitingForLoad);
|
||||
|
||||
return ((IMultiplayerClient)this).LoadRequested();
|
||||
await ((IMultiplayerClient)this).LoadRequested();
|
||||
}
|
||||
|
||||
public override Task AbortGameplay()
|
||||
|
Loading…
Reference in New Issue
Block a user