mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 14:12:54 +08:00
Make spectating instances use custom GCC
This commit is contained in:
parent
54643f53e3
commit
774cca38c4
@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Online.Spectator;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Screens.Spectate;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
@ -29,6 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
private SpectatorStreamingClient spectatorClient { get; set; }
|
||||
|
||||
private readonly PlayerInstance[] instances;
|
||||
private GameplayClockContainer gameplayClockContainer;
|
||||
private PlayerGrid grid;
|
||||
private MultiplayerSpectatorLeaderboard leaderboard;
|
||||
private double? loadFinishTime;
|
||||
@ -44,23 +46,26 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
{
|
||||
Container leaderboardContainer;
|
||||
|
||||
InternalChild = new GridContainer
|
||||
InternalChild = gameplayClockContainer = new MasterGameplayClockContainer(Beatmap.Value, 0)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ColumnDimensions = new[]
|
||||
Child = new GridContainer
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize)
|
||||
},
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ColumnDimensions = new[]
|
||||
{
|
||||
leaderboardContainer = new Container
|
||||
new Dimension(GridSizeMode.AutoSize)
|
||||
},
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X
|
||||
},
|
||||
grid = new PlayerGrid { RelativeSizeAxes = Axes.Both }
|
||||
leaderboardContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X
|
||||
},
|
||||
grid = new PlayerGrid { RelativeSizeAxes = Axes.Both }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -94,6 +99,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
&& instances.Any(i => i.Score.Replay.Frames.Count > 0))
|
||||
);
|
||||
|
||||
private bool firstStartFrame = true;
|
||||
|
||||
private void updateGameplayPlayingState()
|
||||
{
|
||||
// Make sure all players are loaded and have frames before starting any.
|
||||
@ -104,13 +111,16 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstStartFrame)
|
||||
gameplayClockContainer.Restart();
|
||||
|
||||
// Not all instances may be in a valid gameplay state (see canStartGameplay). Only control the ones that are.
|
||||
IEnumerable<PlayerInstance> validInstances = instances.Where(i => i.Score.Replay.Frames.Count > 0);
|
||||
|
||||
double targetTrackTime = validInstances.Select(i => i.GetCurrentTrackTime()).Max();
|
||||
double targetGameplayTime = gameplayClockContainer.GameplayClock.CurrentTime;
|
||||
|
||||
var instanceTimes = string.Join(',', validInstances.Select(i => $" {i.User.Id}: {(int)i.GetCurrentTrackTime()}"));
|
||||
Logger.Log($"target: {(int)targetTrackTime},{instanceTimes}");
|
||||
var instanceTimes = string.Join(',', validInstances.Select(i => $" {i.User.Id}: {(int)i.GetCurrentGameplayTime()}"));
|
||||
Logger.Log($"target: {(int)targetGameplayTime},{instanceTimes}");
|
||||
|
||||
foreach (var inst in validInstances)
|
||||
{
|
||||
@ -123,8 +133,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
if (!canContinuePlayback)
|
||||
continue;
|
||||
|
||||
inst.ContinueGameplay(targetTrackTime);
|
||||
inst.ContinueGameplay(targetGameplayTime);
|
||||
}
|
||||
|
||||
firstStartFrame = false;
|
||||
}
|
||||
|
||||
protected override void OnUserStateChanged(int userId, SpectatorState spectatorState)
|
||||
@ -142,7 +154,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
leaderboard.RemoveClock(existingInstance.User.Id);
|
||||
}
|
||||
|
||||
LoadComponentAsync(instances[userIndex] = new PlayerInstance(gameplayState.Score), d =>
|
||||
LoadComponentAsync(instances[userIndex] = new PlayerInstance(gameplayState.Score, gameplayClockContainer.GameplayClock), d =>
|
||||
{
|
||||
if (instances[userIndex] == d)
|
||||
{
|
||||
|
@ -1,6 +1,9 @@
|
||||
// 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 osu.Framework.Bindables;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -11,11 +14,37 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
{
|
||||
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||
|
||||
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||
public new SubGameplayClockContainer GameplayClockContainer => (SubGameplayClockContainer)base.GameplayClockContainer;
|
||||
|
||||
public MultiplayerSpectatorPlayer(Score score)
|
||||
private readonly GameplayClock gameplayClock;
|
||||
|
||||
public MultiplayerSpectatorPlayer(Score score, GameplayClock gameplayClock)
|
||||
: base(score)
|
||||
{
|
||||
this.gameplayClock = gameplayClock;
|
||||
}
|
||||
|
||||
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
|
||||
=> new SubGameplayClockContainer(gameplayClock);
|
||||
}
|
||||
|
||||
public class SubGameplayClockContainer : GameplayClockContainer
|
||||
{
|
||||
public new DecoupleableInterpolatingFramedClock AdjustableClock => base.AdjustableClock;
|
||||
|
||||
public SubGameplayClockContainer(IClock sourceClock)
|
||||
: base(sourceClock)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnIsPausedChanged(ValueChangedEvent<bool> isPaused)
|
||||
{
|
||||
if (isPaused.NewValue)
|
||||
AdjustableClock.Stop();
|
||||
else
|
||||
AdjustableClock.Start();
|
||||
}
|
||||
|
||||
protected override GameplayClock CreateGameplayClock(IFrameBasedClock source) => new GameplayClock(source);
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
@ -38,15 +36,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
public WorkingBeatmap Beatmap { get; private set; }
|
||||
|
||||
public readonly Score Score;
|
||||
private readonly GameplayClock gameplayClock;
|
||||
|
||||
public bool IsCatchingUp { get; private set; }
|
||||
|
||||
private OsuScreenStack stack;
|
||||
private MultiplayerSpectatorPlayer player;
|
||||
|
||||
public PlayerInstance(Score score)
|
||||
public PlayerInstance(Score score, GameplayClock gameplayClock)
|
||||
{
|
||||
Score = score;
|
||||
this.gameplayClock = gameplayClock;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
}
|
||||
};
|
||||
|
||||
stack.Push(new MultiplayerSpectatorPlayerLoader(Score, () => player = new MultiplayerSpectatorPlayer(Score)));
|
||||
stack.Push(new MultiplayerSpectatorPlayerLoader(Score, () => player = new MultiplayerSpectatorPlayer(Score, gameplayClock)));
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
@ -76,8 +76,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
updateCatchup();
|
||||
}
|
||||
|
||||
private readonly BindableDouble catchupFrequencyAdjustment = new BindableDouble(catchup_rate);
|
||||
private double targetTrackTime;
|
||||
private double targetGameplayTime;
|
||||
|
||||
private void updateCatchup()
|
||||
{
|
||||
@ -91,7 +90,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
return;
|
||||
|
||||
double currentTime = Beatmap.Track.CurrentTime;
|
||||
double timeBehind = targetTrackTime - currentTime;
|
||||
double timeBehind = targetGameplayTime - currentTime;
|
||||
|
||||
double offsetForCatchup = IsCatchingUp ? SYNC_TARGET : MAX_OFFSET;
|
||||
bool catchupRequired = timeBehind > offsetForCatchup;
|
||||
@ -102,12 +101,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
|
||||
if (catchupRequired)
|
||||
{
|
||||
Beatmap.Track.AddAdjustment(AdjustableProperty.Frequency, catchupFrequencyAdjustment);
|
||||
// player.GameplayClockContainer.AdjustableClock.Rate = catchup_rate;
|
||||
Logger.Log($"{User.Id} catchup started (behind: {(int)timeBehind})");
|
||||
}
|
||||
else
|
||||
{
|
||||
Beatmap.Track.RemoveAdjustment(AdjustableProperty.Frequency, catchupFrequencyAdjustment);
|
||||
// player.GameplayClockContainer.AdjustableClock.Rate = 1;
|
||||
Logger.Log($"{User.Id} catchup finished (behind: {(int)timeBehind})");
|
||||
}
|
||||
|
||||
@ -122,21 +121,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
return player.GameplayClockContainer.GameplayClock.CurrentTime;
|
||||
}
|
||||
|
||||
public double GetCurrentTrackTime()
|
||||
public bool IsPlaying()
|
||||
{
|
||||
if (player?.IsLoaded != true)
|
||||
return 0;
|
||||
if (player.IsLoaded != true)
|
||||
return false;
|
||||
|
||||
return Beatmap.Track.CurrentTime;
|
||||
return player.GameplayClockContainer.GameplayClock.IsRunning;
|
||||
}
|
||||
|
||||
public void ContinueGameplay(double targetTrackTime)
|
||||
public void ContinueGameplay(double targetGameplayTime)
|
||||
{
|
||||
if (player?.IsLoaded != true)
|
||||
return;
|
||||
|
||||
player.GameplayClockContainer.Start();
|
||||
this.targetTrackTime = targetTrackTime;
|
||||
this.targetGameplayTime = targetGameplayTime;
|
||||
}
|
||||
|
||||
public void PauseGameplay()
|
||||
|
Loading…
Reference in New Issue
Block a user