// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable using System.ComponentModel; using System.Linq; using osu.Framework.Testing; using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; using osu.Game.Screens.Play.Break; using osu.Game.Screens.Ranking; using osu.Game.Users.Drawables; namespace osu.Game.Tests.Visual.Gameplay { [Description("Player instantiated with an autoplay mod.")] public partial class TestSceneAutoplay : TestSceneAllRulesetPlayers { protected new TestReplayPlayer Player => (TestReplayPlayer)base.Player; protected override Player CreatePlayer(Ruleset ruleset) { SelectedMods.Value = new[] { ruleset.GetAutoplayMod() }; return new TestReplayPlayer(false); } protected override void AddCheckSteps() { // we only want this beatmap for time reference. var referenceBeatmap = CreateBeatmap(new OsuRuleset().RulesetInfo); AddUntilStep("score above zero", () => Player.ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => Player.HUDOverlay.InputCountController.Triggers.Any(kc => kc.ActivationCount.Value > 2)); seekTo(referenceBeatmap.Breaks[0].StartTime); AddAssert("keys not counting", () => !Player.HUDOverlay.InputCountController.IsCounting.Value); AddAssert("overlay displays 100% accuracy", () => Player.BreakOverlay.ChildrenOfType().Single().AccuracyDisplay.Current.Value == 1); AddStep("rewind", () => Player.GameplayClockContainer.Seek(-80000)); AddUntilStep("key counter reset", () => Player.HUDOverlay.InputCountController.Triggers.All(kc => kc.ActivationCount.Value == 0)); seekTo(referenceBeatmap.HitObjects[^1].GetEndTime()); AddUntilStep("results displayed", () => getResultsScreen()?.IsLoaded == true); AddAssert("score has combo", () => getResultsScreen().Score!.Combo > 100); AddAssert("score has no misses", () => getResultsScreen().Score!.Statistics[HitResult.Miss] == 0); AddUntilStep("avatar displayed", () => getAvatar() != null); AddAssert("avatar not clickable", () => getAvatar().ChildrenOfType().First().Action == null); ClickableAvatar getAvatar() => getResultsScreen() .ChildrenOfType().FirstOrDefault(); ResultsScreen getResultsScreen() => Stack.CurrentScreen as ResultsScreen; } private void seekTo(double time) { AddStep($"seek to {time}", () => Player.GameplayClockContainer.Seek(time)); // Prevent test timeouts by seeking in 10 second increments. for (double t = 0; t < time; t += 10000) { double expectedTime = t; AddUntilStep($"current time >= {t}", () => Player.DrawableRuleset.FrameStableClock.CurrentTime >= expectedTime); } AddUntilStep("wait for seek to complete", () => Player.DrawableRuleset.FrameStableClock.CurrentTime >= time); } } }