Skip to content

Commit

Permalink
Merge pull request #25079 from peppy/fix-player-startup-stop
Browse files Browse the repository at this point in the history
Fix multiplayer not correctly pausing the track on initialisation
  • Loading branch information
bdach committed Oct 10, 2023
2 parents 1388f72 + b9dadc5 commit 0c64fe7
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 3 deletions.
13 changes: 13 additions & 0 deletions osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.Play;

namespace osu.Game.Tests.Visual.Multiplayer
{
Expand All @@ -28,6 +29,11 @@ public override void SetUpSteps()
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
});

AddStep("Start track playing", () =>
{
Beatmap.Value.Track.Start();
});

AddStep("initialise gameplay", () =>
{
Stack.Push(player = new MultiplayerPlayer(MultiplayerClient.ServerAPIRoom, new PlaylistItem(Beatmap.Value.BeatmapInfo)
Expand All @@ -37,7 +43,14 @@ public override void SetUpSteps()
});

AddUntilStep("wait for player to be current", () => player.IsCurrentScreen() && player.IsLoaded);

AddAssert("gameplay clock is paused", () => player.ChildrenOfType<GameplayClockContainer>().Single().IsPaused.Value);
AddAssert("gameplay clock is not running", () => !player.ChildrenOfType<GameplayClockContainer>().Single().IsRunning);

AddStep("start gameplay", () => ((IMultiplayerClient)MultiplayerClient).GameplayStarted());

AddUntilStep("gameplay clock is not paused", () => !player.ChildrenOfType<GameplayClockContainer>().Single().IsPaused.Value);
AddAssert("gameplay clock is running", () => player.ChildrenOfType<GameplayClockContainer>().Single().IsRunning);
}

[Test]
Expand Down
3 changes: 3 additions & 0 deletions osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ protected override void StartGameplay()
loadingDisplay.Show();
client.ChangeState(MultiplayerUserState.ReadyForGameplay);
}

// This will pause the clock, pending the gameplay started callback from the server.
GameplayClockContainer.Reset();
}

private void failAndBail(string message = null)
Expand Down
8 changes: 6 additions & 2 deletions osu.Game/Screens/Play/GameplayClockContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,16 @@ public void Stop()
/// Resets this <see cref="GameplayClockContainer"/> and the source to an initial state ready for gameplay.
/// </summary>
/// <param name="time">The time to seek to on resetting. If <c>null</c>, the existing <see cref="StartTime"/> will be used.</param>
/// <param name="startClock">Whether to start the clock immediately, if not already started.</param>
/// <param name="startClock">Whether to start the clock immediately. If <c>false</c> and the clock was already paused, the clock will remain paused after this call.
/// </param>
public void Reset(double? time = null, bool startClock = false)
{
bool wasPaused = isPaused.Value;

Stop();
// The intention of the Reset method is to get things into a known sane state.
// As such, we intentionally stop the underlying clock directly here, bypassing Stop/StopGameplayClock.
// This is to avoid any kind of isPaused state checks and frequency ramping (as provided by MasterGameplayClockContainer).
GameplayClock.Stop();

if (time != null)
StartTime = time.Value;
Expand Down
2 changes: 1 addition & 1 deletion osu.Game/Screens/Play/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ public override void OnEntering(ScreenTransitionEvent e)
protected virtual void StartGameplay()
{
if (GameplayClockContainer.IsRunning)
throw new InvalidOperationException($"{nameof(StartGameplay)} should not be called when the gameplay clock is already running");
Logger.Error(new InvalidOperationException($"{nameof(StartGameplay)} should not be called when the gameplay clock is already running"), "Clock failure");

GameplayClockContainer.Reset(startClock: true);

Expand Down

0 comments on commit 0c64fe7

Please sign in to comment.