mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 02:43:19 +08:00
Merge pull request #24448 from peppy/multi-spectator-better-start-time
Improve choice of where to start playback of multiplayer spectator
This commit is contained in:
commit
270c03235d
@ -2,12 +2,13 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
@ -198,15 +199,29 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
|
||||
private void performInitialSeek()
|
||||
{
|
||||
// Seek the master clock to the gameplay time.
|
||||
// This is chosen as the first available frame in the players' replays, which matches the seek by each individual SpectatorPlayer.
|
||||
double startTime = instances.Where(i => i.Score != null)
|
||||
.SelectMany(i => i.Score.AsNonNull().Replay.Frames)
|
||||
.Select(f => f.Time)
|
||||
.DefaultIfEmpty(0)
|
||||
.Min();
|
||||
// We want to start showing gameplay as soon as possible.
|
||||
// Each client may be in a different place in the beatmap, so we need to do our best to find a common
|
||||
// starting point.
|
||||
//
|
||||
// Preferring a lower value ensures that we don't have some clients stuttering to keep up.
|
||||
List<double> minFrameTimes = new List<double>();
|
||||
|
||||
foreach (var instance in instances)
|
||||
{
|
||||
if (instance.Score == null)
|
||||
continue;
|
||||
|
||||
minFrameTimes.Add(instance.Score.Replay.Frames.MinBy(f => f.Time)?.Time ?? 0);
|
||||
}
|
||||
|
||||
// Remove any outliers (only need to worry about removing those lower than the mean since we will take a Min() after).
|
||||
double mean = minFrameTimes.Average();
|
||||
minFrameTimes.RemoveAll(t => mean - t > 1000);
|
||||
|
||||
double startTime = minFrameTimes.Min();
|
||||
|
||||
masterClockContainer.Reset(startTime, true);
|
||||
Logger.Log($"Multiplayer spectator seeking to initial time of {startTime}");
|
||||
}
|
||||
|
||||
protected override void OnNewPlayingUserState(int userId, SpectatorState spectatorState)
|
||||
@ -245,6 +260,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
return base.OnBackButton();
|
||||
|
||||
// On a manual exit, set the player back to idle unless gameplay has finished.
|
||||
// Of note, this doesn't cover exiting using alt-f4 or menu home option.
|
||||
if (multiplayerClient.Room.State != MultiplayerRoomState.Open)
|
||||
multiplayerClient.ChangeState(MultiplayerUserState.Idle);
|
||||
|
||||
|
@ -182,7 +182,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
return;
|
||||
|
||||
masterState = newState;
|
||||
Logger.Log($"{nameof(SpectatorSyncManager)}'s master clock become {masterState}");
|
||||
Logger.Log($"{nameof(SpectatorSyncManager)}'s master clock became {masterState}");
|
||||
|
||||
switch (masterState)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user