Fix multiplayer spectator not getting gameplay adjustments applied

This commit is contained in:
Dean Herbert 2022-09-07 19:12:34 +09:00
parent fa15502384
commit 1be3b74ff3
3 changed files with 32 additions and 1 deletions

View File

@ -53,6 +53,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
}
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
=> new GameplayClockContainer(spectatorPlayerClock);
{
var gameplayClockContainer = new GameplayClockContainer(spectatorPlayerClock);
// Directionality is important, as BindAdjustments is... not actually a bidirectional bind...
// We want to ensure that any adjustments applied by the Player instance are applied to the SpectatorPlayerClock
// so they can be consumed by the spectator screen (and applied to the master clock / track).
spectatorPlayerClock.GameplayAdjustments.BindAdjustments(gameplayClockContainer.GameplayAdjustments);
return gameplayClockContainer;
}
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -43,6 +44,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
[Resolved]
private MultiplayerClient multiplayerClient { get; set; } = null!;
private AudioAdjustments? boundAdjustments;
private readonly PlayerArea[] instances;
private MasterGameplayClockContainer masterClockContainer = null!;
private SpectatorSyncManager syncManager = null!;
@ -157,6 +160,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
base.LoadComplete();
masterClockContainer.Reset();
// Start with adjustments from the first player to keep a sane state.
bindAudioAdjustments(instances.First());
}
protected override void Update()
@ -169,11 +175,24 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
.OrderBy(i => Math.Abs(i.SpectatorPlayerClock.CurrentTime - syncManager.CurrentMasterTime))
.FirstOrDefault();
// Only bind adjustments if there's actually a valid source, else just use the previous ones to ensure no sudden changes to audio.
if (currentAudioSource != null)
bindAudioAdjustments(currentAudioSource);
foreach (var instance in instances)
instance.Mute = instance != currentAudioSource;
}
}
private void bindAudioAdjustments(PlayerArea first)
{
if (boundAdjustments != null)
masterClockContainer.GameplayAdjustments.UnbindAdjustments(boundAdjustments);
boundAdjustments = first.SpectatorPlayerClock.GameplayAdjustments;
masterClockContainer.GameplayAdjustments.BindAdjustments(boundAdjustments);
}
private bool isCandidateAudioSource(SpectatorPlayerClock? clock)
=> clock?.IsRunning == true && !clock.IsCatchingUp && !clock.WaitingOnFrames;

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Audio;
using osu.Framework.Timing;
using osu.Game.Screens.Play;
@ -19,6 +20,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
private readonly GameplayClockContainer masterClock;
public readonly AudioAdjustments GameplayAdjustments = new AudioAdjustments();
public double CurrentTime { get; private set; }
/// <summary>