diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Mods/EmptyFreeformModAutoplay.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Mods/EmptyFreeformModAutoplay.cs index d4496a24fd..d3ef3f6e56 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Mods/EmptyFreeformModAutoplay.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Mods/EmptyFreeformModAutoplay.cs @@ -3,22 +3,14 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.EmptyFreeform.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; namespace osu.Game.Rulesets.EmptyFreeform.Mods { public class EmptyFreeformModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo - { - User = new APIUser { Username = "sample" }, - }, - Replay = new EmptyFreeformAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new EmptyFreeformAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "sample" }); } } diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs index 6e1fe42ee2..f57b874ff3 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs @@ -3,22 +3,14 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Pippidon.Replays; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Pippidon.Mods { public class PippidonModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo - { - User = new APIUser { Username = "sample" }, - }, - Replay = new PippidonAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new PippidonAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "sample" }); } } diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Mods/EmptyScrollingModAutoplay.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Mods/EmptyScrollingModAutoplay.cs index c5bacb522f..5cf40c30cd 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Mods/EmptyScrollingModAutoplay.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Mods/EmptyScrollingModAutoplay.cs @@ -1,24 +1,16 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Beatmaps; -using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.EmptyScrolling.Replays; -using osu.Game.Scoring; using System.Collections.Generic; -using osu.Game.Online.API.Requests.Responses; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.EmptyScrolling.Replays; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.EmptyScrolling.Mods { public class EmptyScrollingModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo - { - User = new APIUser { Username = "sample" }, - }, - Replay = new EmptyScrollingAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new EmptyScrollingAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "sample" }); } } diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs index 6e1fe42ee2..f57b874ff3 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Mods/PippidonModAutoplay.cs @@ -3,22 +3,14 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Pippidon.Replays; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Pippidon.Mods { public class PippidonModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo - { - User = new APIUser { Username = "sample" }, - }, - Replay = new PippidonAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new PippidonAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "sample" }); } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 11fffb31de..50e48101d3 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -3,19 +3,14 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Catch.Mods { public class CatchModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!salad" } }, - Replay = new CatchAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new CatchAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "osu!salad" }); } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs index 6d2286b957..7eda6b37d3 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs @@ -3,20 +3,15 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Catch.Mods { public class CatchModCinema : ModCinema { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!salad" } }, - Replay = new CatchAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new CatchAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "osu!salad" }); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 1504c868d0..d444c9b634 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -3,20 +3,15 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!topus" } }, - Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), new ModCreatedUser { Username = "osu!topus" }); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs index 4f1276946b..f0db742eac 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs @@ -3,21 +3,16 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mods; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Mania.Mods { public class ManiaModCinema : ModCinema { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!topus" } }, - Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), new ModCreatedUser { Username = "osu!topus" }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs index 840d871b7b..a9325f98f7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using NUnit.Framework; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Replays; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Beatmaps; @@ -13,7 +12,6 @@ using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; using osu.Game.Tests.Visual; using osuTK; @@ -67,11 +65,8 @@ namespace osu.Game.Rulesets.Osu.Tests private class TestAutoMod : OsuModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "Autoplay" } }, - Replay = new MissingAutoGenerator(beatmap, mods).Generate() - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new MissingAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = "Autoplay" }); } private class MissingAutoGenerator : OsuAutoGeneratorBase diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index 2668013321..31179cdf4a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -5,10 +5,8 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu.Mods { @@ -16,10 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAimAssist), typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "Autoplay" } }, - Replay = new OsuAutoGenerator(beatmap, mods).Generate() - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = "Autoplay" }); } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs index ff31cfcd18..d677ab43d0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs @@ -5,11 +5,9 @@ using System; using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Replays; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Osu.Mods { @@ -17,10 +15,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAimAssist), typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "Autoplay" } }, - Replay = new OsuAutoGenerator(beatmap, mods).Generate() - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedUser { Username = "Autoplay" }); } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index 5832ae3dc1..4b74b4991e 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -3,19 +3,14 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Replays; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModAutoplay : ModAutoplay { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "mekkadosu!" } }, - Replay = new TaikoAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "mekkadosu!" }); } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs index f76e04a069..fee0cb2744 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs @@ -3,20 +3,15 @@ using System.Collections.Generic; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Replays; -using osu.Game.Scoring; namespace osu.Game.Rulesets.Taiko.Mods { public class TaikoModCinema : ModCinema { - public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score - { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "mekkadosu!" } }, - Replay = new TaikoAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "mekkadosu!" }); } } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index fdc3916c47..346a88a2d5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -5,12 +5,14 @@ using System.ComponentModel; using System.Linq; using osu.Framework.Testing; using osu.Game.Beatmaps.Timing; +using osu.Game.Graphics.Containers; using osu.Game.Rulesets; using osu.Game.Rulesets.Objects; 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 { @@ -39,11 +41,18 @@ namespace osu.Game.Tests.Visual.Gameplay seekToBreak(1); AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); - AddUntilStep("results displayed", () => getResultsScreen() != null); + + 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; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index f94e122b30..8622fe8f53 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty()); - return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod()?.CreateReplayScore(beatmap, Array.Empty())); + return new ScoreAccessibleReplayPlayer(ruleset.GetAutoplayMod()?.CreateScoreFromReplayData(beatmap, Array.Empty())); } protected override void AddCheckSteps() diff --git a/osu.Game/Online/API/Requests/Responses/APIUser.cs b/osu.Game/Online/API/Requests/Responses/APIUser.cs index a53ac1cd9b..a87f0811a1 100644 --- a/osu.Game/Online/API/Requests/Responses/APIUser.cs +++ b/osu.Game/Online/API/Requests/Responses/APIUser.cs @@ -15,6 +15,11 @@ namespace osu.Game.Online.API.Requests.Responses [JsonObject(MemberSerialization.OptIn)] public class APIUser : IEquatable, IUser { + /// + /// A user ID which can be used to represent any system user which is not attached to a user profile. + /// + public const int SYSTEM_USER_ID = 0; + [JsonProperty(@"id")] public int Id { get; set; } = 1; @@ -238,7 +243,7 @@ namespace osu.Game.Online.API.Requests.Responses /// public static readonly APIUser SYSTEM_USER = new APIUser { - Id = 0, + Id = SYSTEM_USER_ID, Username = "system", Colour = @"9c0101", }; diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs index 9fac1463f2..518a2bf9c8 100644 --- a/osu.Game/Overlays/UserProfileOverlay.cs +++ b/osu.Game/Overlays/UserProfileOverlay.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays public void ShowUser(IUser user) { - if (user == APIUser.SYSTEM_USER) + if (user.OnlineID == APIUser.SYSTEM_USER_ID) return; Show(); diff --git a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs index 071f01ca00..392a5db9da 100644 --- a/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs +++ b/osu.Game/Rulesets/Edit/DrawableEditorRulesetWrapper.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Edit private void regenerateAutoplay() { var autoplayMod = drawableRuleset.Mods.OfType().Single(); - drawableRuleset.SetReplayScore(autoplayMod.CreateReplayScore(drawableRuleset.Beatmap, drawableRuleset.Mods)); + drawableRuleset.SetReplayScore(autoplayMod.CreateScoreFromReplayData(drawableRuleset.Beatmap, drawableRuleset.Mods)); } private void addHitObject(HitObject hitObject) diff --git a/osu.Game/Rulesets/Mods/ICreateReplay.cs b/osu.Game/Rulesets/Mods/ICreateReplay.cs index 098bd8799a..1e5eeca92c 100644 --- a/osu.Game/Rulesets/Mods/ICreateReplay.cs +++ b/osu.Game/Rulesets/Mods/ICreateReplay.cs @@ -1,14 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public interface ICreateReplay + [Obsolete("Use ICreateReplayData instead")] // Can be removed 20220929 + public interface ICreateReplay : ICreateReplayData { public Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods); + + ModReplayData ICreateReplayData.CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + { + var replayScore = CreateReplayScore(beatmap, mods); + return new ModReplayData(replayScore.Replay, new ModCreatedUser { Username = replayScore.ScoreInfo.User.Username }); + } } } diff --git a/osu.Game/Rulesets/Mods/ICreateReplayData.cs b/osu.Game/Rulesets/Mods/ICreateReplayData.cs new file mode 100644 index 0000000000..7d208e9000 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ICreateReplayData.cs @@ -0,0 +1,63 @@ +// Copyright (c) ppy Pty Ltd . 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.Online.API.Requests.Responses; +using osu.Game.Replays; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Rulesets.Mods +{ + /// + /// A mod which creates full replay data, which is to be played back in place of a local user playing the game. + /// + public interface ICreateReplayData + { + /// + /// Create replay data. + /// + /// The beatmap to create replay data for. + /// The mods to take into account when creating the replay data. + /// A structure, containing the generated replay data. + /// + /// For callers that want to receive a directly usable instance, + /// the extension method is provided for convenience. + /// + ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods); + } + + /// + /// Data created by a mod that implements . + /// + public class ModReplayData + { + /// + /// The full replay data. + /// + public readonly Replay Replay; + + /// + /// Placeholder user data to show in place of the local user when the associated mod is active. + /// + public readonly ModCreatedUser User; + + public ModReplayData(Replay replay, ModCreatedUser user = null) + { + Replay = replay; + User = user ?? new ModCreatedUser(); + } + } + + /// + /// A user which is associated with a replay that was created by a mod (ie. autoplay or cinema). + /// + public class ModCreatedUser : IUser + { + public int OnlineID => APIUser.SYSTEM_USER_ID; + public bool IsBot => true; + + public string Username { get; set; } = string.Empty; + } +} diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index e804cb6734..87dc627b19 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -11,7 +11,7 @@ using osu.Game.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModAutoplay : Mod, IApplicableFailOverride, ICreateReplay + public abstract class ModAutoplay : Mod, IApplicableFailOverride, ICreateReplayData { public override string Name => "Autoplay"; public override string Acronym => "AT"; @@ -30,6 +30,16 @@ namespace osu.Game.Rulesets.Mods public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; + [Obsolete("Override CreateReplayData(IBeatmap, IReadOnlyList) instead")] // Can be removed 20220929 public virtual Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { Replay = new Replay() }; + + public virtual ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + { +#pragma warning disable CS0618 + var replayScore = CreateReplayScore(beatmap, mods); +#pragma warning restore CS0618 + + return new ModReplayData(replayScore.Replay, new ModCreatedUser { Username = replayScore.ScoreInfo.User.Username }); + } } } diff --git a/osu.Game/Rulesets/Mods/ModExtensions.cs b/osu.Game/Rulesets/Mods/ModExtensions.cs new file mode 100644 index 0000000000..b22030414b --- /dev/null +++ b/osu.Game/Rulesets/Mods/ModExtensions.cs @@ -0,0 +1,31 @@ +// Copyright (c) ppy Pty Ltd . 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.Online.API.Requests.Responses; +using osu.Game.Scoring; + +namespace osu.Game.Rulesets.Mods +{ + public static class ModExtensions + { + public static Score CreateScoreFromReplayData(this ICreateReplayData mod, IBeatmap beatmap, IReadOnlyList mods) + { + var replayData = mod.CreateReplayData(beatmap, mods); + + return new Score + { + Replay = replayData.Replay, + ScoreInfo = + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = replayData.User.Username, + } + } + }; + } + } +} diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 434a0ea030..593436bbb7 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -98,9 +98,12 @@ namespace osu.Game.Screens.Select Player createPlayer() { - var replayGeneratingMod = Mods.Value.OfType().FirstOrDefault(); + var replayGeneratingMod = Mods.Value.OfType().FirstOrDefault(); + if (replayGeneratingMod != null) - return new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateReplayScore(beatmap, mods)); + { + return new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateScoreFromReplayData(beatmap, mods)); + } return new SoloPlayer(); } diff --git a/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs b/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs index d126eff075..0808cd157f 100644 --- a/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs +++ b/osu.Game/Skinning/Editor/SkinEditorSceneLibrary.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play; using osu.Game.Screens.Select; using osuTK; @@ -94,7 +95,7 @@ namespace osu.Game.Skinning.Editor var replayGeneratingMod = ruleset.Value.CreateInstance().GetAutoplayMod(); if (replayGeneratingMod != null) - screen.Push(new PlayerLoader(() => new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateReplayScore(beatmap, mods)))); + screen.Push(new PlayerLoader(() => new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateScoreFromReplayData(beatmap, mods)))); }, new[] { typeof(Player), typeof(SongSelect) }) }, } diff --git a/osu.Game/Tests/Visual/TestPlayer.cs b/osu.Game/Tests/Visual/TestPlayer.cs index d463905cf4..66a956ca3d 100644 --- a/osu.Game/Tests/Visual/TestPlayer.cs +++ b/osu.Game/Tests/Visual/TestPlayer.cs @@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual if (autoplayMod != null) { - DrawableRuleset?.SetReplayScore(autoplayMod.CreateReplayScore(GameplayState.Beatmap, Mods.Value)); + DrawableRuleset?.SetReplayScore(autoplayMod.CreateScoreFromReplayData(GameplayState.Beatmap, Mods.Value)); return; } diff --git a/osu.Game/Tests/Visual/TestReplayPlayer.cs b/osu.Game/Tests/Visual/TestReplayPlayer.cs index da302d018d..bacb2427b0 100644 --- a/osu.Game/Tests/Visual/TestReplayPlayer.cs +++ b/osu.Game/Tests/Visual/TestReplayPlayer.cs @@ -40,7 +40,7 @@ namespace osu.Game.Tests.Visual /// Instantiate a replay player that renders an autoplay mod. /// public TestReplayPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false) - : base((beatmap, mods) => mods.OfType().First().CreateReplayScore(beatmap, mods), new PlayerConfiguration + : base((beatmap, mods) => mods.OfType().First().CreateScoreFromReplayData(beatmap, mods), new PlayerConfiguration { AllowPause = allowPause, ShowResults = showResults diff --git a/osu.Game/Users/Drawables/ClickableAvatar.cs b/osu.Game/Users/Drawables/ClickableAvatar.cs index 34c87568a1..0dd135b500 100644 --- a/osu.Game/Users/Drawables/ClickableAvatar.cs +++ b/osu.Game/Users/Drawables/ClickableAvatar.cs @@ -21,7 +21,7 @@ namespace osu.Game.Users.Drawables /// public bool OpenOnClick { - set => clickableArea.Enabled.Value = value; + set => clickableArea.Enabled.Value = clickableArea.Action != null && value; } /// @@ -52,8 +52,10 @@ namespace osu.Game.Users.Drawables Add(clickableArea = new ClickableArea { RelativeSizeAxes = Axes.Both, - Action = openProfile }); + + if (user?.Id != APIUser.SYSTEM_USER_ID) + clickableArea.Action = openProfile; } [BackgroundDependencyLoader]