mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 17:07:38 +08:00
Merge pull request #19911 from smoogipoo/multi-spectator-clock-cleanup
Invert creation of clocks in multi-spectator
This commit is contained in:
commit
51e607e834
@ -4,11 +4,13 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Tests.OnlinePlay
|
namespace osu.Game.Tests.OnlinePlay
|
||||||
@ -16,20 +18,34 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
[HeadlessTest]
|
[HeadlessTest]
|
||||||
public class TestSceneCatchUpSyncManager : OsuTestScene
|
public class TestSceneCatchUpSyncManager : OsuTestScene
|
||||||
{
|
{
|
||||||
private TestManualClock master;
|
private GameplayClockContainer master;
|
||||||
private CatchUpSyncManager syncManager;
|
private CatchUpSyncManager syncManager;
|
||||||
|
|
||||||
private TestSpectatorPlayerClock player1;
|
private Dictionary<ISpectatorPlayerClock, int> clocksById;
|
||||||
private TestSpectatorPlayerClock player2;
|
private ISpectatorPlayerClock player1;
|
||||||
|
private ISpectatorPlayerClock player2;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
syncManager = new CatchUpSyncManager(master = new TestManualClock());
|
syncManager = new CatchUpSyncManager(master = new GameplayClockContainer(new TestManualClock()));
|
||||||
syncManager.AddPlayerClock(player1 = new TestSpectatorPlayerClock(1));
|
player1 = syncManager.CreateManagedClock();
|
||||||
syncManager.AddPlayerClock(player2 = new TestSpectatorPlayerClock(2));
|
player2 = syncManager.CreateManagedClock();
|
||||||
|
|
||||||
Schedule(() => Child = syncManager);
|
clocksById = new Dictionary<ISpectatorPlayerClock, int>
|
||||||
|
{
|
||||||
|
{ player1, 1 },
|
||||||
|
{ player2, 2 }
|
||||||
|
};
|
||||||
|
|
||||||
|
Schedule(() =>
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
syncManager,
|
||||||
|
master
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -129,8 +145,8 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
assertPlayerClockState(() => player1, false);
|
assertPlayerClockState(() => player1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setWaiting(Func<TestSpectatorPlayerClock> playerClock, bool waiting)
|
private void setWaiting(Func<ISpectatorPlayerClock> playerClock, bool waiting)
|
||||||
=> AddStep($"set player clock {playerClock().Id} waiting = {waiting}", () => playerClock().WaitingOnFrames.Value = waiting);
|
=> AddStep($"set player clock {clocksById[playerClock()]} waiting = {waiting}", () => playerClock().WaitingOnFrames.Value = waiting);
|
||||||
|
|
||||||
private void setAllWaiting(bool waiting) => AddStep($"set all player clocks waiting = {waiting}", () =>
|
private void setAllWaiting(bool waiting) => AddStep($"set all player clocks waiting = {waiting}", () =>
|
||||||
{
|
{
|
||||||
@ -144,51 +160,14 @@ namespace osu.Game.Tests.OnlinePlay
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// clock.Time = master.Time - offsetFromMaster
|
/// clock.Time = master.Time - offsetFromMaster
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void setPlayerClockTime(Func<TestSpectatorPlayerClock> playerClock, double offsetFromMaster)
|
private void setPlayerClockTime(Func<ISpectatorPlayerClock> playerClock, double offsetFromMaster)
|
||||||
=> AddStep($"set player clock {playerClock().Id} = master - {offsetFromMaster}", () => playerClock().Seek(master.CurrentTime - offsetFromMaster));
|
=> AddStep($"set player clock {clocksById[playerClock()]} = master - {offsetFromMaster}", () => playerClock().Seek(master.CurrentTime - offsetFromMaster));
|
||||||
|
|
||||||
private void assertCatchingUp(Func<TestSpectatorPlayerClock> playerClock, bool catchingUp) =>
|
private void assertCatchingUp(Func<ISpectatorPlayerClock> playerClock, bool catchingUp) =>
|
||||||
AddAssert($"player clock {playerClock().Id} {(catchingUp ? "is" : "is not")} catching up", () => playerClock().IsCatchingUp == catchingUp);
|
AddAssert($"player clock {clocksById[playerClock()]} {(catchingUp ? "is" : "is not")} catching up", () => playerClock().IsCatchingUp == catchingUp);
|
||||||
|
|
||||||
private void assertPlayerClockState(Func<TestSpectatorPlayerClock> playerClock, bool running)
|
private void assertPlayerClockState(Func<ISpectatorPlayerClock> playerClock, bool running)
|
||||||
=> AddAssert($"player clock {playerClock().Id} {(running ? "is" : "is not")} running", () => playerClock().IsRunning == running);
|
=> AddAssert($"player clock {clocksById[playerClock()]} {(running ? "is" : "is not")} running", () => playerClock().IsRunning == running);
|
||||||
|
|
||||||
private class TestSpectatorPlayerClock : TestManualClock, ISpectatorPlayerClock
|
|
||||||
{
|
|
||||||
public Bindable<bool> WaitingOnFrames { get; } = new Bindable<bool>(true);
|
|
||||||
|
|
||||||
public bool IsCatchingUp { get; set; }
|
|
||||||
|
|
||||||
public IFrameBasedClock Source
|
|
||||||
{
|
|
||||||
set => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly int Id;
|
|
||||||
|
|
||||||
public TestSpectatorPlayerClock(int id)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
|
|
||||||
WaitingOnFrames.BindValueChanged(waiting =>
|
|
||||||
{
|
|
||||||
if (waiting.NewValue)
|
|
||||||
Stop();
|
|
||||||
else
|
|
||||||
Start();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ProcessFrame()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public double ElapsedFrameTime => 0;
|
|
||||||
|
|
||||||
public double FramesPerSecond => 0;
|
|
||||||
|
|
||||||
public FrameTimeInfo TimeInfo => default;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestManualClock : ManualClock, IAdjustableClock
|
private class TestManualClock : ManualClock, IAdjustableClock
|
||||||
{
|
{
|
||||||
|
@ -17,15 +17,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const double CATCHUP_RATE = 2;
|
public const double CATCHUP_RATE = 2;
|
||||||
|
|
||||||
/// <summary>
|
public readonly IFrameBasedClock Source;
|
||||||
/// The source clock.
|
|
||||||
/// </summary>
|
|
||||||
public IFrameBasedClock? Source { get; set; }
|
|
||||||
|
|
||||||
public double CurrentTime { get; private set; }
|
public double CurrentTime { get; private set; }
|
||||||
|
|
||||||
public bool IsRunning { get; private set; }
|
public bool IsRunning { get; private set; }
|
||||||
|
|
||||||
|
public CatchUpSpectatorPlayerClock(IFrameBasedClock source)
|
||||||
|
{
|
||||||
|
Source = source;
|
||||||
|
}
|
||||||
|
|
||||||
public void Reset() => CurrentTime = 0;
|
public void Reset() => CurrentTime = 0;
|
||||||
|
|
||||||
public void Start() => IsRunning = true;
|
public void Start() => IsRunning = true;
|
||||||
@ -67,9 +69,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
ElapsedFrameTime = 0;
|
ElapsedFrameTime = 0;
|
||||||
FramesPerSecond = 0;
|
FramesPerSecond = 0;
|
||||||
|
|
||||||
if (Source == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Source.ProcessFrame();
|
Source.ProcessFrame();
|
||||||
|
|
||||||
if (IsRunning)
|
if (IsRunning)
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Timing;
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||||
{
|
{
|
||||||
@ -33,12 +30,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const double MAXIMUM_START_DELAY = 15000;
|
public const double MAXIMUM_START_DELAY = 15000;
|
||||||
|
|
||||||
public event Action ReadyToStart;
|
public event Action? ReadyToStart;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The master clock which is used to control the timing of all player clocks clocks.
|
/// The master clock which is used to control the timing of all player clocks clocks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IAdjustableClock MasterClock { get; }
|
public GameplayClockContainer MasterClock { get; }
|
||||||
|
|
||||||
public IBindable<MasterClockState> MasterState => masterState;
|
public IBindable<MasterClockState> MasterState => masterState;
|
||||||
|
|
||||||
@ -52,18 +49,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
private bool hasStarted;
|
private bool hasStarted;
|
||||||
private double? firstStartAttemptTime;
|
private double? firstStartAttemptTime;
|
||||||
|
|
||||||
public CatchUpSyncManager(IAdjustableClock master)
|
public CatchUpSyncManager(GameplayClockContainer master)
|
||||||
{
|
{
|
||||||
MasterClock = master;
|
MasterClock = master;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddPlayerClock(ISpectatorPlayerClock clock)
|
public ISpectatorPlayerClock CreateManagedClock()
|
||||||
{
|
{
|
||||||
Debug.Assert(!playerClocks.Contains(clock));
|
var clock = new CatchUpSpectatorPlayerClock(MasterClock);
|
||||||
playerClocks.Add(clock);
|
playerClocks.Add(clock);
|
||||||
|
return clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovePlayerClock(ISpectatorPlayerClock clock)
|
public void RemoveManagedClock(ISpectatorPlayerClock clock)
|
||||||
{
|
{
|
||||||
playerClocks.Remove(clock);
|
playerClocks.Remove(clock);
|
||||||
clock.Stop();
|
clock.Stop();
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Timing;
|
using osu.Framework.Timing;
|
||||||
|
|
||||||
@ -35,10 +33,5 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
/// Of note, this will be false if this clock is *ahead* of the master clock.
|
/// Of note, this will be false if this clock is *ahead* of the master clock.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
bool IsCatchingUp { get; set; }
|
bool IsCatchingUp { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The source clock
|
|
||||||
/// </summary>
|
|
||||||
IFrameBasedClock Source { set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Timing;
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||||
{
|
{
|
||||||
@ -17,12 +15,12 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An event which is invoked when gameplay is ready to start.
|
/// An event which is invoked when gameplay is ready to start.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action ReadyToStart;
|
event Action? ReadyToStart;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The master clock which player clocks should synchronise to.
|
/// The master clock which player clocks should synchronise to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IAdjustableClock MasterClock { get; }
|
GameplayClockContainer MasterClock { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An event which is invoked when the state of <see cref="MasterClock"/> is changed.
|
/// An event which is invoked when the state of <see cref="MasterClock"/> is changed.
|
||||||
@ -30,15 +28,15 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
IBindable<MasterClockState> MasterState { get; }
|
IBindable<MasterClockState> MasterState { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an <see cref="ISpectatorPlayerClock"/> to manage.
|
/// Create a new managed <see cref="ISpectatorPlayerClock"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clock">The <see cref="ISpectatorPlayerClock"/> to add.</param>
|
/// <returns>The newly created <see cref="ISpectatorPlayerClock"/>.</returns>
|
||||||
void AddPlayerClock(ISpectatorPlayerClock clock);
|
ISpectatorPlayerClock CreateManagedClock();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes an <see cref="ISpectatorPlayerClock"/>, stopping it from being managed by this <see cref="ISyncManager"/>.
|
/// Removes an <see cref="ISpectatorPlayerClock"/>, stopping it from being managed by this <see cref="ISyncManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clock">The <see cref="ISpectatorPlayerClock"/> to remove.</param>
|
/// <param name="clock">The <see cref="ISpectatorPlayerClock"/> to remove.</param>
|
||||||
void RemovePlayerClock(ISpectatorPlayerClock clock);
|
void RemoveManagedClock(ISpectatorPlayerClock clock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Extensions.ObjectExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -42,17 +40,17 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
protected override UserActivity InitialActivity => new UserActivity.SpectatingMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value);
|
protected override UserActivity InitialActivity => new UserActivity.SpectatingMultiplayerGame(Beatmap.Value.BeatmapInfo, Ruleset.Value);
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; }
|
private OsuColour colours { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private MultiplayerClient multiplayerClient { get; set; }
|
private MultiplayerClient multiplayerClient { get; set; } = null!;
|
||||||
|
|
||||||
private readonly PlayerArea[] instances;
|
private readonly PlayerArea[] instances;
|
||||||
private MasterGameplayClockContainer masterClockContainer;
|
private MasterGameplayClockContainer masterClockContainer = null!;
|
||||||
private ISyncManager syncManager;
|
private ISyncManager syncManager = null!;
|
||||||
private PlayerGrid grid;
|
private PlayerGrid grid = null!;
|
||||||
private MultiSpectatorLeaderboard leaderboard;
|
private MultiSpectatorLeaderboard leaderboard = null!;
|
||||||
private PlayerArea currentAudioSource;
|
private PlayerArea? currentAudioSource;
|
||||||
private bool canStartMasterClock;
|
private bool canStartMasterClock;
|
||||||
|
|
||||||
private readonly Room room;
|
private readonly Room room;
|
||||||
@ -125,10 +123,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < Users.Count; i++)
|
for (int i = 0; i < Users.Count; i++)
|
||||||
{
|
grid.Add(instances[i] = new PlayerArea(Users[i], syncManager.CreateManagedClock()));
|
||||||
grid.Add(instances[i] = new PlayerArea(Users[i], masterClockContainer));
|
|
||||||
syncManager.AddPlayerClock(instances[i].GameplayClock);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(users)
|
LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(users)
|
||||||
{
|
{
|
||||||
@ -181,7 +176,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool isCandidateAudioSource([CanBeNull] ISpectatorPlayerClock clock)
|
private bool isCandidateAudioSource(ISpectatorPlayerClock? clock)
|
||||||
=> clock?.IsRunning == true && !clock.IsCatchingUp && !clock.WaitingOnFrames.Value;
|
=> clock?.IsRunning == true && !clock.IsCatchingUp && !clock.WaitingOnFrames.Value;
|
||||||
|
|
||||||
private void onReadyToStart()
|
private void onReadyToStart()
|
||||||
@ -189,7 +184,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
// Seek the master clock to the gameplay time.
|
// 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.
|
// 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)
|
double startTime = instances.Where(i => i.Score != null)
|
||||||
.SelectMany(i => i.Score.Replay.Frames)
|
.SelectMany(i => i.Score.AsNonNull().Replay.Frames)
|
||||||
.Select(f => f.Time)
|
.Select(f => f.Time)
|
||||||
.DefaultIfEmpty(0)
|
.DefaultIfEmpty(0)
|
||||||
.Min();
|
.Min();
|
||||||
@ -242,7 +237,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
var instance = instances.Single(i => i.UserId == userId);
|
var instance = instances.Single(i => i.UserId == userId);
|
||||||
|
|
||||||
instance.FadeColour(colours.Gray4, 400, Easing.OutQuint);
|
instance.FadeColour(colours.Gray4, 400, Easing.OutQuint);
|
||||||
syncManager.RemovePlayerClock(instance.GameplayClock);
|
syncManager.RemoveManagedClock(instance.GameplayClock);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnBackButton()
|
public override bool OnBackButton()
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -29,7 +25,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised after <see cref="Player.StartGameplay"/> is called on <see cref="Player"/>.
|
/// Raised after <see cref="Player.StartGameplay"/> is called on <see cref="Player"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action OnGameplayStarted;
|
public event Action? OnGameplayStarted;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether a <see cref="Player"/> is loaded in the area.
|
/// Whether a <see cref="Player"/> is loaded in the area.
|
||||||
@ -44,23 +40,25 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="ISpectatorPlayerClock"/> used to control the gameplay running state of a loaded <see cref="Player"/>.
|
/// The <see cref="ISpectatorPlayerClock"/> used to control the gameplay running state of a loaded <see cref="Player"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NotNull]
|
public readonly ISpectatorPlayerClock GameplayClock;
|
||||||
public readonly ISpectatorPlayerClock GameplayClock = new CatchUpSpectatorPlayerClock();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The currently-loaded score.
|
/// The currently-loaded score.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[CanBeNull]
|
public Score? Score { get; private set; }
|
||||||
public Score Score { get; private set; }
|
|
||||||
|
[Resolved]
|
||||||
|
private IBindable<WorkingBeatmap> beatmap { get; set; } = null!;
|
||||||
|
|
||||||
private readonly BindableDouble volumeAdjustment = new BindableDouble();
|
private readonly BindableDouble volumeAdjustment = new BindableDouble();
|
||||||
private readonly Container gameplayContent;
|
private readonly Container gameplayContent;
|
||||||
private readonly LoadingLayer loadingLayer;
|
private readonly LoadingLayer loadingLayer;
|
||||||
private OsuScreenStack stack;
|
private OsuScreenStack? stack;
|
||||||
|
|
||||||
public PlayerArea(int userId, IFrameBasedClock masterClock)
|
public PlayerArea(int userId, ISpectatorPlayerClock clock)
|
||||||
{
|
{
|
||||||
UserId = userId;
|
UserId = userId;
|
||||||
|
GameplayClock = clock;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
@ -77,14 +75,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
};
|
};
|
||||||
|
|
||||||
audioContainer.AddAdjustment(AdjustableProperty.Volume, volumeAdjustment);
|
audioContainer.AddAdjustment(AdjustableProperty.Volume, volumeAdjustment);
|
||||||
|
|
||||||
GameplayClock.Source = masterClock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved]
|
public void LoadScore(Score score)
|
||||||
private IBindable<WorkingBeatmap> beatmap { get; set; }
|
|
||||||
|
|
||||||
public void LoadScore([NotNull] Score score)
|
|
||||||
{
|
{
|
||||||
if (Score != null)
|
if (Score != null)
|
||||||
throw new InvalidOperationException($"Cannot load a new score on a {nameof(PlayerArea)} that has an existing score.");
|
throw new InvalidOperationException($"Cannot load a new score on a {nameof(PlayerArea)} that has an existing score.");
|
||||||
|
Loading…
Reference in New Issue
Block a user