mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 19:22:54 +08:00
Merge pull request #12952 from peppy/autoplay-pause-support
Externalise autoplay generation from `Player` to allow use of replay playback functions
This commit is contained in:
commit
d39eb7eac2
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.EmptyFreeform.Objects;
|
|
||||||
using osu.Game.Rulesets.EmptyFreeform.Replays;
|
using osu.Game.Rulesets.EmptyFreeform.Replays;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -11,7 +10,7 @@ using osu.Game.Users;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyFreeform.Mods
|
namespace osu.Game.Rulesets.EmptyFreeform.Mods
|
||||||
{
|
{
|
||||||
public class EmptyFreeformModAutoplay : ModAutoplay<EmptyFreeformHitObject>
|
public class EmptyFreeformModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -4,14 +4,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Pippidon.Objects;
|
|
||||||
using osu.Game.Rulesets.Pippidon.Replays;
|
using osu.Game.Rulesets.Pippidon.Replays;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.Mods
|
namespace osu.Game.Rulesets.Pippidon.Mods
|
||||||
{
|
{
|
||||||
public class PippidonModAutoplay : ModAutoplay<PippidonHitObject>
|
public class PippidonModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.EmptyScrolling.Objects;
|
|
||||||
using osu.Game.Rulesets.EmptyScrolling.Replays;
|
using osu.Game.Rulesets.EmptyScrolling.Replays;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -11,7 +10,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.EmptyScrolling.Mods
|
namespace osu.Game.Rulesets.EmptyScrolling.Mods
|
||||||
{
|
{
|
||||||
public class EmptyScrollingModAutoplay : ModAutoplay<EmptyScrollingHitObject>
|
public class EmptyScrollingModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -4,14 +4,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Pippidon.Objects;
|
|
||||||
using osu.Game.Rulesets.Pippidon.Replays;
|
using osu.Game.Rulesets.Pippidon.Replays;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Pippidon.Mods
|
namespace osu.Game.Rulesets.Pippidon.Mods
|
||||||
{
|
{
|
||||||
public class PippidonModAutoplay : ModAutoplay<PippidonHitObject>
|
public class PippidonModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
|
||||||
using osu.Game.Rulesets.Catch.Replays;
|
using osu.Game.Rulesets.Catch.Replays;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -11,7 +10,7 @@ using osu.Game.Users;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Mods
|
namespace osu.Game.Rulesets.Catch.Mods
|
||||||
{
|
{
|
||||||
public class CatchModAutoplay : ModAutoplay<CatchHitObject>
|
public class CatchModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
|
||||||
using osu.Game.Rulesets.Mania.Replays;
|
using osu.Game.Rulesets.Mania.Replays;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -12,7 +11,7 @@ using osu.Game.Users;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Mods
|
namespace osu.Game.Rulesets.Mania.Mods
|
||||||
{
|
{
|
||||||
public class ManiaModAutoplay : ModAutoplay<ManiaHitObject>
|
public class ManiaModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -6,14 +6,13 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
|
||||||
using osu.Game.Rulesets.Osu.Replays;
|
using osu.Game.Rulesets.Osu.Replays;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Mods
|
namespace osu.Game.Rulesets.Osu.Mods
|
||||||
{
|
{
|
||||||
public class OsuModAutoplay : ModAutoplay<OsuHitObject>
|
public class OsuModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
|
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
|
||||||
|
|
||||||
|
@ -4,14 +4,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
|
||||||
using osu.Game.Rulesets.Taiko.Replays;
|
using osu.Game.Rulesets.Taiko.Replays;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Mods
|
namespace osu.Game.Rulesets.Taiko.Mods
|
||||||
{
|
{
|
||||||
public class TaikoModAutoplay : ModAutoplay<TaikoHitObject>
|
public class TaikoModAutoplay : ModAutoplay
|
||||||
{
|
{
|
||||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||||
{
|
{
|
||||||
|
@ -18,12 +18,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
[Description("Player instantiated with an autoplay mod.")]
|
[Description("Player instantiated with an autoplay mod.")]
|
||||||
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
|
public class TestSceneAutoplay : TestSceneAllRulesetPlayers
|
||||||
{
|
{
|
||||||
protected new TestPlayer Player => (TestPlayer)base.Player;
|
protected new TestReplayPlayer Player => (TestReplayPlayer)base.Player;
|
||||||
|
|
||||||
protected override Player CreatePlayer(Ruleset ruleset)
|
protected override Player CreatePlayer(Ruleset ruleset)
|
||||||
{
|
{
|
||||||
SelectedMods.Value = new[] { ruleset.GetAutoplayMod() };
|
SelectedMods.Value = new[] { ruleset.GetAutoplayMod() };
|
||||||
return new TestPlayer(false);
|
return new TestReplayPlayer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddCheckSteps()
|
protected override void AddCheckSteps()
|
||||||
|
@ -12,6 +12,7 @@ using osu.Game.Graphics.UserInterface;
|
|||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Mods;
|
using osu.Game.Overlays.Mods;
|
||||||
using osu.Game.Overlays.Toolbar;
|
using osu.Game.Overlays.Toolbar;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
@ -95,11 +96,12 @@ namespace osu.Game.Tests.Visual.Navigation
|
|||||||
|
|
||||||
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
AddUntilStep("wait for selected", () => !Game.Beatmap.IsDefault);
|
||||||
|
|
||||||
AddStep("set autoplay", () => Game.SelectedMods.Value = new[] { new OsuModAutoplay() });
|
AddStep("set mods", () => Game.SelectedMods.Value = new Mod[] { new OsuModNoFail(), new OsuModDoubleTime { SpeedChange = { Value = 2 } } });
|
||||||
|
|
||||||
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
AddStep("press enter", () => InputManager.Key(Key.Enter));
|
||||||
AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null);
|
AddUntilStep("wait for player", () => (player = Game.ScreenStack.CurrentScreen as Player) != null);
|
||||||
AddStep("seek to end", () => player.ChildrenOfType<GameplayClockContainer>().First().Seek(beatmap().Track.Length));
|
AddUntilStep("wait for track playing", () => beatmap().Track.IsRunning);
|
||||||
|
AddStep("seek to near end", () => player.ChildrenOfType<GameplayClockContainer>().First().Seek(beatmap().Beatmap.HitObjects[^1].StartTime - 1000));
|
||||||
AddUntilStep("wait for pass", () => (results = Game.ScreenStack.CurrentScreen as ResultsScreen) != null && results.IsLoaded);
|
AddUntilStep("wait for pass", () => (results = Game.ScreenStack.CurrentScreen as ResultsScreen) != null && results.IsLoaded);
|
||||||
AddStep("attempt to retry", () => results.ChildrenOfType<HotkeyRetryOverlay>().First().Action());
|
AddStep("attempt to retry", () => results.ChildrenOfType<HotkeyRetryOverlay>().First().Action());
|
||||||
AddUntilStep("wait for player", () => Game.ScreenStack.CurrentScreen != player && Game.ScreenStack.CurrentScreen is Player);
|
AddUntilStep("wait for player", () => Game.ScreenStack.CurrentScreen != player && Game.ScreenStack.CurrentScreen is Player);
|
||||||
|
@ -1,9 +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.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
@ -52,15 +54,21 @@ namespace osu.Game.Rulesets.Edit
|
|||||||
if (changeHandler != null)
|
if (changeHandler != null)
|
||||||
{
|
{
|
||||||
// for now only regenerate replay on a finalised state change, not HitObjectUpdated.
|
// for now only regenerate replay on a finalised state change, not HitObjectUpdated.
|
||||||
changeHandler.OnStateChange += updateReplay;
|
changeHandler.OnStateChange += () => Scheduler.AddOnce(regenerateAutoplay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
beatmap.HitObjectUpdated += _ => updateReplay();
|
beatmap.HitObjectUpdated += _ => Scheduler.AddOnce(regenerateAutoplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scheduler.AddOnce(regenerateAutoplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateReplay() => Scheduler.AddOnce(drawableRuleset.RegenerateAutoplay);
|
private void regenerateAutoplay()
|
||||||
|
{
|
||||||
|
var autoplayMod = drawableRuleset.Mods.OfType<ModAutoplay>().Single();
|
||||||
|
drawableRuleset.SetReplayScore(autoplayMod.CreateReplayScore(drawableRuleset.Beatmap, drawableRuleset.Mods));
|
||||||
|
}
|
||||||
|
|
||||||
private void addHitObject(HitObject hitObject)
|
private void addHitObject(HitObject hitObject)
|
||||||
{
|
{
|
||||||
|
14
osu.Game/Rulesets/Mods/ICreateReplay.cs
Normal file
14
osu.Game/Rulesets/Mods/ICreateReplay.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mods
|
||||||
|
{
|
||||||
|
public interface ICreateReplay
|
||||||
|
{
|
||||||
|
public Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods);
|
||||||
|
}
|
||||||
|
}
|
@ -7,22 +7,11 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
using osu.Game.Rulesets.UI;
|
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
public abstract class ModAutoplay<T> : ModAutoplay, IApplicableToDrawableRuleset<T>
|
public abstract class ModAutoplay : Mod, IApplicableFailOverride, ICreateReplay
|
||||||
where T : HitObject
|
|
||||||
{
|
|
||||||
public virtual void ApplyToDrawableRuleset(DrawableRuleset<T> drawableRuleset)
|
|
||||||
{
|
|
||||||
drawableRuleset.SetReplayScore(CreateReplayScore(drawableRuleset.Beatmap, drawableRuleset.Mods));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class ModAutoplay : Mod, IApplicableFailOverride
|
|
||||||
{
|
{
|
||||||
public override string Name => "Autoplay";
|
public override string Name => "Autoplay";
|
||||||
public override string Acronym => "AT";
|
public override string Acronym => "AT";
|
||||||
|
@ -182,18 +182,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
.WithChild(ResumeOverlay)));
|
.WithChild(ResumeOverlay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
RegenerateAutoplay();
|
applyRulesetMods(Mods, config);
|
||||||
|
|
||||||
loadObjects(cancellationToken ?? default);
|
loadObjects(cancellationToken ?? default);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegenerateAutoplay()
|
|
||||||
{
|
|
||||||
// for now this is applying mods which aren't just autoplay.
|
|
||||||
// we'll need to reconsider this flow in the future.
|
|
||||||
applyRulesetMods(Mods, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates and adds drawable representations of hit objects to the play field.
|
/// Creates and adds drawable representations of hit objects to the play field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -17,7 +17,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
public class MultiSpectatorPlayer : SpectatorPlayer
|
public class MultiSpectatorPlayer : SpectatorPlayer
|
||||||
{
|
{
|
||||||
private readonly Bindable<bool> waitingOnFrames = new Bindable<bool>(true);
|
private readonly Bindable<bool> waitingOnFrames = new Bindable<bool>(true);
|
||||||
private readonly Score score;
|
|
||||||
private readonly ISpectatorPlayerClock spectatorPlayerClock;
|
private readonly ISpectatorPlayerClock spectatorPlayerClock;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -28,7 +27,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock)
|
public MultiSpectatorPlayer([NotNull] Score score, [NotNull] ISpectatorPlayerClock spectatorPlayerClock)
|
||||||
: base(score)
|
: base(score)
|
||||||
{
|
{
|
||||||
this.score = score;
|
|
||||||
this.spectatorPlayerClock = spectatorPlayerClock;
|
this.spectatorPlayerClock = spectatorPlayerClock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +41,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
base.UpdateAfterChildren();
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
// This is required because the frame stable clock is set to WaitingOnFrames = false for one frame.
|
// This is required because the frame stable clock is set to WaitingOnFrames = false for one frame.
|
||||||
waitingOnFrames.Value = DrawableRuleset.FrameStableClock.WaitingOnFrames.Value || score.Replay.Frames.Count == 0;
|
waitingOnFrames.Value = DrawableRuleset.FrameStableClock.WaitingOnFrames.Value || Score.Replay.Frames.Count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
|
protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBeatmap beatmap, double gameplayStart)
|
||||||
|
@ -54,11 +54,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
return new PlaylistsResultsScreen(score, RoomId.Value.Value, PlaylistItem, true);
|
return new PlaylistsResultsScreen(score, RoomId.Value.Value, PlaylistItem, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Score CreateScore()
|
protected override void PrepareScoreForResults()
|
||||||
{
|
{
|
||||||
var score = base.CreateScore();
|
base.PrepareScoreForResults();
|
||||||
score.ScoreInfo.TotalScore = (int)Math.Round(ScoreProcessor.GetStandardisedScore());
|
|
||||||
return score;
|
Score.ScoreInfo.TotalScore = (int)Math.Round(ScoreProcessor.GetStandardisedScore());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
@ -24,10 +23,8 @@ using osu.Game.IO.Archives;
|
|||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Spectator;
|
using osu.Game.Online.Spectator;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Replays;
|
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Replays;
|
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -137,6 +134,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
public readonly PlayerConfiguration Configuration;
|
public readonly PlayerConfiguration Configuration;
|
||||||
|
|
||||||
|
protected Score Score { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new player instance.
|
/// Create a new player instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -145,7 +144,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Configuration = configuration ?? new PlayerConfiguration();
|
Configuration = configuration ?? new PlayerConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private GameplayBeatmap gameplayBeatmap;
|
protected GameplayBeatmap GameplayBeatmap { get; private set; }
|
||||||
|
|
||||||
private ScreenSuspensionHandler screenSuspension;
|
private ScreenSuspensionHandler screenSuspension;
|
||||||
|
|
||||||
@ -161,24 +160,32 @@ namespace osu.Game.Screens.Play
|
|||||||
if (!LoadedBeatmapSuccessfully)
|
if (!LoadedBeatmapSuccessfully)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// replays should never be recorded or played back when autoplay is enabled
|
Score = CreateScore();
|
||||||
if (!Mods.Value.Any(m => m is ModAutoplay))
|
|
||||||
PrepareReplay();
|
// ensure the score is in a consistent state with the current player.
|
||||||
|
Score.ScoreInfo.Beatmap = Beatmap.Value.BeatmapInfo;
|
||||||
|
Score.ScoreInfo.Ruleset = rulesetInfo;
|
||||||
|
Score.ScoreInfo.Mods = Mods.Value.ToArray();
|
||||||
|
|
||||||
|
PrepareReplay();
|
||||||
|
|
||||||
|
ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(Score.ScoreInfo);
|
||||||
|
|
||||||
gameActive.BindValueChanged(_ => updatePauseOnFocusLostState(), true);
|
gameActive.BindValueChanged(_ => updatePauseOnFocusLostState(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[CanBeNull]
|
|
||||||
private Score recordingScore;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Run any recording / playback setup for replays.
|
/// Run any recording / playback setup for replays.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void PrepareReplay()
|
protected virtual void PrepareReplay()
|
||||||
{
|
{
|
||||||
DrawableRuleset.SetRecordTarget(recordingScore = new Score());
|
DrawableRuleset.SetRecordTarget(Score);
|
||||||
|
}
|
||||||
|
|
||||||
ScoreProcessor.NewJudgement += result => ScoreProcessor.PopulateScore(recordingScore.ScoreInfo);
|
protected virtual void PrepareScoreForResults()
|
||||||
|
{
|
||||||
|
// perform one final population to ensure everything is up-to-date.
|
||||||
|
ScoreProcessor.PopulateScore(Score.ScoreInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
@ -223,10 +230,10 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
||||||
|
|
||||||
AddInternal(gameplayBeatmap = new GameplayBeatmap(playableBeatmap));
|
AddInternal(GameplayBeatmap = new GameplayBeatmap(playableBeatmap));
|
||||||
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
||||||
|
|
||||||
dependencies.CacheAs(gameplayBeatmap);
|
dependencies.CacheAs(GameplayBeatmap);
|
||||||
|
|
||||||
var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin);
|
var beatmapSkinProvider = new BeatmapSkinProvidingContainer(Beatmap.Value.Skin);
|
||||||
|
|
||||||
@ -284,7 +291,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
HealthProcessor.ApplyResult(r);
|
HealthProcessor.ApplyResult(r);
|
||||||
ScoreProcessor.ApplyResult(r);
|
ScoreProcessor.ApplyResult(r);
|
||||||
gameplayBeatmap.ApplyResult(r);
|
GameplayBeatmap.ApplyResult(r);
|
||||||
};
|
};
|
||||||
|
|
||||||
DrawableRuleset.RevertResult += r =>
|
DrawableRuleset.RevertResult += r =>
|
||||||
@ -633,11 +640,11 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
prepareScoreForDisplayTask ??= Task.Run(async () =>
|
prepareScoreForDisplayTask ??= Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var score = CreateScore();
|
PrepareScoreForResults();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PrepareScoreForResultsAsync(score).ConfigureAwait(false);
|
await PrepareScoreForResultsAsync(Score).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -646,14 +653,14 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ImportScore(score).ConfigureAwait(false);
|
await ImportScore(Score).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error(ex, "Score import failed!");
|
Logger.Error(ex, "Score import failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return score.ScoreInfo;
|
return Score.ScoreInfo;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (skipStoryboardOutro)
|
if (skipStoryboardOutro)
|
||||||
@ -905,41 +912,19 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the player's <see cref="Score"/>.
|
/// Creates the player's <see cref="Scoring.Score"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The <see cref="Score"/>.</returns>
|
/// <returns>The <see cref="Scoring.Score"/>.</returns>
|
||||||
protected virtual Score CreateScore()
|
protected virtual Score CreateScore() =>
|
||||||
{
|
new Score
|
||||||
var score = new Score
|
|
||||||
{
|
{
|
||||||
ScoreInfo = new ScoreInfo
|
ScoreInfo = new ScoreInfo { User = api.LocalUser.Value },
|
||||||
{
|
|
||||||
Beatmap = Beatmap.Value.BeatmapInfo,
|
|
||||||
Ruleset = rulesetInfo,
|
|
||||||
Mods = Mods.Value.ToArray(),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (DrawableRuleset.ReplayScore != null)
|
|
||||||
{
|
|
||||||
score.ScoreInfo.User = DrawableRuleset.ReplayScore.ScoreInfo?.User ?? new GuestUser();
|
|
||||||
score.Replay = DrawableRuleset.ReplayScore.Replay;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
score.ScoreInfo.User = api.LocalUser.Value;
|
|
||||||
score.Replay = new Replay { Frames = recordingScore?.Replay.Frames.ToList() ?? new List<ReplayFrame>() };
|
|
||||||
}
|
|
||||||
|
|
||||||
ScoreProcessor.PopulateScore(score.ScoreInfo);
|
|
||||||
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Imports the player's <see cref="Score"/> to the local database.
|
/// Imports the player's <see cref="Scoring.Score"/> to the local database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="score">The <see cref="Score"/> to import.</param>
|
/// <param name="score">The <see cref="Scoring.Score"/> to import.</param>
|
||||||
/// <returns>The imported score.</returns>
|
/// <returns>The imported score.</returns>
|
||||||
protected virtual async Task ImportScore(Score score)
|
protected virtual async Task ImportScore(Score score)
|
||||||
{
|
{
|
||||||
@ -951,7 +936,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
new LegacyScoreEncoder(score, gameplayBeatmap.PlayableBeatmap).Encode(stream);
|
new LegacyScoreEncoder(score, GameplayBeatmap.PlayableBeatmap).Encode(stream);
|
||||||
replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr");
|
replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,9 +955,9 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Prepare the <see cref="Score"/> for display at results.
|
/// Prepare the <see cref="Scoring.Score"/> for display at results.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="score">The <see cref="Score"/> to prepare.</param>
|
/// <param name="score">The <see cref="Scoring.Score"/> to prepare.</param>
|
||||||
/// <returns>A task that prepares the provided score. On completion, the score is assumed to be ready for display.</returns>
|
/// <returns>A task that prepares the provided score. On completion, the score is assumed to be ready for display.</returns>
|
||||||
protected virtual Task PrepareScoreForResultsAsync(Score score) => Task.CompletedTask;
|
protected virtual Task PrepareScoreForResultsAsync(Score score) => Task.CompletedTask;
|
||||||
|
|
||||||
|
@ -1,9 +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.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Input.Bindings;
|
using osu.Framework.Input.Bindings;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
|
|
||||||
@ -11,15 +15,20 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
public class ReplayPlayer : Player, IKeyBindingHandler<GlobalAction>
|
public class ReplayPlayer : Player, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
protected readonly Score Score;
|
private readonly Func<IBeatmap, IReadOnlyList<Mod>, Score> createScore;
|
||||||
|
|
||||||
// Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108)
|
// Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108)
|
||||||
protected override bool CheckModsAllowFailure() => false;
|
protected override bool CheckModsAllowFailure() => false;
|
||||||
|
|
||||||
public ReplayPlayer(Score score, PlayerConfiguration configuration = null)
|
public ReplayPlayer(Score score, PlayerConfiguration configuration = null)
|
||||||
|
: this((_, __) => score, configuration)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplayPlayer(Func<IBeatmap, IReadOnlyList<Mod>, Score> createScore, PlayerConfiguration configuration = null)
|
||||||
: base(configuration)
|
: base(configuration)
|
||||||
{
|
{
|
||||||
Score = score;
|
this.createScore = createScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareReplay()
|
protected override void PrepareReplay()
|
||||||
@ -27,15 +36,7 @@ namespace osu.Game.Screens.Play
|
|||||||
DrawableRuleset?.SetReplayScore(Score);
|
DrawableRuleset?.SetReplayScore(Score);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Score CreateScore()
|
protected override Score CreateScore() => createScore(GameplayBeatmap.PlayableBeatmap, Mods.Value);
|
||||||
{
|
|
||||||
var baseScore = base.CreateScore();
|
|
||||||
|
|
||||||
// Since the replay score doesn't contain statistics, we'll pass them through here.
|
|
||||||
Score.ScoreInfo.HitEvents = baseScore.ScoreInfo.HitEvents;
|
|
||||||
|
|
||||||
return Score;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't re-import replay scores as they're already present in the database.
|
// Don't re-import replay scores as they're already present in the database.
|
||||||
protected override Task ImportScore(Score score) => Task.CompletedTask;
|
protected override Task ImportScore(Score score) => Task.CompletedTask;
|
||||||
|
@ -18,6 +18,9 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
private readonly Score score;
|
private readonly Score score;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private SpectatorClient spectatorClient { get; set; }
|
||||||
|
|
||||||
protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap
|
protected override bool CheckModsAllowFailure() => false; // todo: better support starting mid-way through beatmap
|
||||||
|
|
||||||
public SpectatorPlayer(Score score)
|
public SpectatorPlayer(Score score)
|
||||||
@ -25,13 +28,10 @@ namespace osu.Game.Screens.Play
|
|||||||
this.score = score;
|
this.score = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ResultsScreen CreateResults(ScoreInfo score)
|
protected override Score CreateScore() => score;
|
||||||
{
|
|
||||||
return new SpectatorResultsScreen(score);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Resolved]
|
protected override ResultsScreen CreateResults(ScoreInfo score)
|
||||||
private SpectatorClient spectatorClient { get; set; }
|
=> new SpectatorResultsScreen(score);
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Screens.Select
|
|||||||
public class PlaySongSelect : SongSelect
|
public class PlaySongSelect : SongSelect
|
||||||
{
|
{
|
||||||
private bool removeAutoModOnResume;
|
private bool removeAutoModOnResume;
|
||||||
private OsuScreen player;
|
private OsuScreen playerLoader;
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
private NotificationOverlay notifications { get; set; }
|
private NotificationOverlay notifications { get; set; }
|
||||||
@ -49,7 +49,7 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
base.OnResuming(last);
|
base.OnResuming(last);
|
||||||
|
|
||||||
player = null;
|
playerLoader = null;
|
||||||
|
|
||||||
if (removeAutoModOnResume)
|
if (removeAutoModOnResume)
|
||||||
{
|
{
|
||||||
@ -79,14 +79,14 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
protected override bool OnStart()
|
protected override bool OnStart()
|
||||||
{
|
{
|
||||||
if (player != null) return false;
|
if (playerLoader != null) return false;
|
||||||
|
|
||||||
// Ctrl+Enter should start map with autoplay enabled.
|
// Ctrl+Enter should start map with autoplay enabled.
|
||||||
if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true)
|
if (GetContainingInputManager().CurrentState?.Keyboard.ControlPressed == true)
|
||||||
{
|
{
|
||||||
var autoplayMod = getAutoplayMod();
|
var autoInstance = getAutoplayMod();
|
||||||
|
|
||||||
if (autoplayMod == null)
|
if (autoInstance == null)
|
||||||
{
|
{
|
||||||
notifications?.Post(new SimpleNotification
|
notifications?.Post(new SimpleNotification
|
||||||
{
|
{
|
||||||
@ -97,18 +97,26 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
var mods = Mods.Value;
|
var mods = Mods.Value;
|
||||||
|
|
||||||
if (mods.All(m => m.GetType() != autoplayMod.GetType()))
|
if (mods.All(m => m.GetType() != autoInstance.GetType()))
|
||||||
{
|
{
|
||||||
Mods.Value = mods.Append(autoplayMod).ToArray();
|
Mods.Value = mods.Append(autoInstance).ToArray();
|
||||||
removeAutoModOnResume = true;
|
removeAutoModOnResume = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SampleConfirm?.Play();
|
SampleConfirm?.Play();
|
||||||
|
|
||||||
this.Push(player = new PlayerLoader(() => new SoloPlayer()));
|
this.Push(playerLoader = new PlayerLoader(createPlayer));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
Player createPlayer()
|
||||||
|
{
|
||||||
|
var replayGeneratingMod = Mods.Value.OfType<ICreateReplay>().FirstOrDefault();
|
||||||
|
if (replayGeneratingMod != null)
|
||||||
|
return new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateReplayScore(beatmap, mods));
|
||||||
|
|
||||||
|
return new SoloPlayer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
@ -48,6 +49,26 @@ namespace osu.Game.Tests.Visual
|
|||||||
PauseOnFocusLost = pauseOnFocusLost;
|
PauseOnFocusLost = pauseOnFocusLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void PrepareReplay()
|
||||||
|
{
|
||||||
|
// Generally, replay generation is handled by whatever is constructing the player.
|
||||||
|
// This is implemented locally here to ease migration of test scenes that have some executions
|
||||||
|
// running with autoplay and some not, but are not written in a way that lends to instantiating
|
||||||
|
// different `Player` types.
|
||||||
|
//
|
||||||
|
// Eventually we will want to remove this and update all test usages which rely on autoplay to use
|
||||||
|
// a `TestReplayPlayer`.
|
||||||
|
var autoplayMod = Mods.Value.OfType<ModAutoplay>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (autoplayMod != null)
|
||||||
|
{
|
||||||
|
DrawableRuleset?.SetReplayScore(autoplayMod.CreateReplayScore(GameplayBeatmap.PlayableBeatmap, Mods.Value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.PrepareReplay();
|
||||||
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
|
65
osu.Game/Tests/Visual/TestReplayPlayer.cs
Normal file
65
osu.Game/Tests/Visual/TestReplayPlayer.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// 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 System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.UI;
|
||||||
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A player that exposes many components that would otherwise not be available, for testing purposes.
|
||||||
|
/// </summary>
|
||||||
|
public class TestReplayPlayer : ReplayPlayer
|
||||||
|
{
|
||||||
|
protected override bool PauseOnFocusLost { get; }
|
||||||
|
|
||||||
|
public new DrawableRuleset DrawableRuleset => base.DrawableRuleset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mods from *player* (not OsuScreen).
|
||||||
|
/// </summary>
|
||||||
|
public new Bindable<IReadOnlyList<Mod>> Mods => base.Mods;
|
||||||
|
|
||||||
|
public new HUDOverlay HUDOverlay => base.HUDOverlay;
|
||||||
|
|
||||||
|
public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer;
|
||||||
|
|
||||||
|
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;
|
||||||
|
|
||||||
|
public new HealthProcessor HealthProcessor => base.HealthProcessor;
|
||||||
|
|
||||||
|
public new bool PauseCooldownActive => base.PauseCooldownActive;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiate a replay player that renders an autoplay mod.
|
||||||
|
/// </summary>
|
||||||
|
public TestReplayPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false)
|
||||||
|
: base((beatmap, mods) => mods.OfType<ModAutoplay>().First().CreateReplayScore(beatmap, mods), new PlayerConfiguration
|
||||||
|
{
|
||||||
|
AllowPause = allowPause,
|
||||||
|
ShowResults = showResults
|
||||||
|
})
|
||||||
|
{
|
||||||
|
PauseOnFocusLost = pauseOnFocusLost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiate a replay player that renders the provided replay.
|
||||||
|
/// </summary>
|
||||||
|
public TestReplayPlayer(Score score, bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false)
|
||||||
|
: base(score, new PlayerConfiguration
|
||||||
|
{
|
||||||
|
AllowPause = allowPause,
|
||||||
|
ShowResults = showResults
|
||||||
|
})
|
||||||
|
{
|
||||||
|
PauseOnFocusLost = pauseOnFocusLost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user