From a0692ce47780c05a907439172f3ae85a6b0b80a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Mar 2022 22:20:56 +0900 Subject: [PATCH 01/25] Add a `const` for system users which should never display a profile --- osu.Game/Online/API/Requests/Responses/APIUser.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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", }; From d2d88015e32927ab8704b273c2a090630cce084c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Mar 2022 22:21:23 +0900 Subject: [PATCH 02/25] Update all cinema/autoplay mods to specify the system user ID --- .../Mods/EmptyFreeformModAutoplay.cs | 6 +++++- .../Mods/PippidonModAutoplay.cs | 6 +++++- .../Mods/EmptyScrollingModAutoplay.cs | 6 +++++- .../Mods/PippidonModAutoplay.cs | 6 +++++- osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs | 9 ++++++++- osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs | 9 ++++++++- osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs | 9 ++++++++- osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs | 9 ++++++++- osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 9 ++++++++- osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs | 9 ++++++++- osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs | 9 ++++++++- osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs | 9 ++++++++- 12 files changed, 84 insertions(+), 12 deletions(-) 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..9c2a108c4e 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 @@ -16,7 +16,11 @@ namespace osu.Game.Rulesets.EmptyFreeform.Mods { ScoreInfo = new ScoreInfo { - User = new APIUser { Username = "sample" }, + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "sample" + }, }, Replay = new EmptyFreeformAutoGenerator(beatmap).Generate(), }; 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..6683856a1a 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 @@ -16,7 +16,11 @@ namespace osu.Game.Rulesets.Pippidon.Mods { ScoreInfo = new ScoreInfo { - User = new APIUser { Username = "sample" }, + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "sample" + }, }, Replay = new PippidonAutoGenerator(beatmap).Generate(), }; 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..e3cecc7b44 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 @@ -16,7 +16,11 @@ namespace osu.Game.Rulesets.EmptyScrolling.Mods { ScoreInfo = new ScoreInfo { - User = new APIUser { Username = "sample" }, + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "sample" + }, }, Replay = new EmptyScrollingAutoGenerator(beatmap).Generate(), }; 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..6683856a1a 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 @@ -16,7 +16,11 @@ namespace osu.Game.Rulesets.Pippidon.Mods { ScoreInfo = new ScoreInfo { - User = new APIUser { Username = "sample" }, + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "sample" + }, }, Replay = new PippidonAutoGenerator(beatmap).Generate(), }; diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index 11fffb31de..fbbb610035 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -14,7 +14,14 @@ namespace osu.Game.Rulesets.Catch.Mods { public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!salad" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "osu!salad" + } + }, Replay = new CatchAutoGenerator(beatmap).Generate(), }; } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs index 6d2286b957..2f4769048f 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs @@ -15,7 +15,14 @@ namespace osu.Game.Rulesets.Catch.Mods { public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!salad" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "osu!salad" + } + }, Replay = new CatchAutoGenerator(beatmap).Generate(), }; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 1504c868d0..4eea0d4a44 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -15,7 +15,14 @@ namespace osu.Game.Rulesets.Mania.Mods { public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!topus" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "osu!topus" + } + }, Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), }; } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs index 4f1276946b..0aa419bbcb 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs @@ -16,7 +16,14 @@ namespace osu.Game.Rulesets.Mania.Mods { public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "osu!topus" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "osu!topus" + } + }, Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), }; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs index 2668013321..c5b1c55c40 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -18,7 +18,14 @@ namespace osu.Game.Rulesets.Osu.Mods public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "Autoplay" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "Autoplay", + } + }, Replay = new OsuAutoGenerator(beatmap, mods).Generate() }; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs index ff31cfcd18..83e6f0efb5 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs @@ -19,7 +19,14 @@ namespace osu.Game.Rulesets.Osu.Mods public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "Autoplay" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "Autoplay" + } + }, Replay = new OsuAutoGenerator(beatmap, mods).Generate() }; } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index 5832ae3dc1..b9bf3ab1b4 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -14,7 +14,14 @@ namespace osu.Game.Rulesets.Taiko.Mods { public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "mekkadosu!" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "mekkadosu!" + } + }, Replay = new TaikoAutoGenerator(beatmap).Generate(), }; } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs index f76e04a069..6ecf8a3b3d 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs @@ -15,7 +15,14 @@ namespace osu.Game.Rulesets.Taiko.Mods { public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList mods) => new Score { - ScoreInfo = new ScoreInfo { User = new APIUser { Username = "mekkadosu!" } }, + ScoreInfo = new ScoreInfo + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = "mekkadosu!" + } + }, Replay = new TaikoAutoGenerator(beatmap).Generate(), }; } From dc7dc7f65ac7a3ef3a0f3d1cd9edd06ae0186099 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Mar 2022 22:50:31 +0900 Subject: [PATCH 03/25] Update `UserProfileOverlay` and `ClickableAvatar` to treat system users more correctly --- osu.Game/Overlays/UserProfileOverlay.cs | 2 +- osu.Game/Users/Drawables/ClickableAvatar.cs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) 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/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] From 7059e4bf9463a1adf45b2dc707e9cba5f4ac2be7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 28 Mar 2022 23:37:39 +0900 Subject: [PATCH 04/25] Add test coverage for autoplay avatar not being clickable --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index fdc3916c47..518ab5a1d3 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 dispalyed", () => getAvatar() != null); + AddAssert("avatar not clickable", () => getAvatar().ChildrenOfType().First().Action == null); + + ClickableAvatar getAvatar() => getResultsScreen() + .ChildrenOfType().FirstOrDefault(); + ResultsScreen getResultsScreen() => Stack.CurrentScreen as ResultsScreen; } From 3fc8c23fe440644f321c9fa41ca183cf0b0ae637 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Mar 2022 16:49:52 +0900 Subject: [PATCH 05/25] Remove unnecessary `SetReplayScore` call in `ModCinema` --- osu.Game/Rulesets/Mods/ModCinema.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModCinema.cs b/osu.Game/Rulesets/Mods/ModCinema.cs index f28ef1edeb..1fe5ddecf9 100644 --- a/osu.Game/Rulesets/Mods/ModCinema.cs +++ b/osu.Game/Rulesets/Mods/ModCinema.cs @@ -14,8 +14,6 @@ namespace osu.Game.Rulesets.Mods { public virtual void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) { - drawableRuleset.SetReplayScore(CreateReplayScore(drawableRuleset.Beatmap, drawableRuleset.Mods)); - // AlwaysPresent required for hitsounds drawableRuleset.AlwaysPresent = true; drawableRuleset.Hide(); From 7d716adf39a8f91d1bac35332ad3346fa3020d67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Mar 2022 16:27:42 +0900 Subject: [PATCH 06/25] Create new `ICreateReplayData` interface and obsolete `ICreateReplay` --- osu.Game/Rulesets/Mods/ICreateReplay.cs | 10 +++- osu.Game/Rulesets/Mods/ICreateReplayData.cs | 58 +++++++++++++++++++++ osu.Game/Rulesets/Mods/ModAutoplay.cs | 15 +++++- 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/ICreateReplayData.cs diff --git a/osu.Game/Rulesets/Mods/ICreateReplay.cs b/osu.Game/Rulesets/Mods/ICreateReplay.cs index 098bd8799a..4883ce5842 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 ModCreatedReplayUser { 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..b022949345 --- /dev/null +++ b/osu.Game/Rulesets/Mods/ICreateReplayData.cs @@ -0,0 +1,58 @@ +// 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.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. + /// + /// + /// + /// + public 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 ModCreatedReplayUser User; + + public ModReplayData(Replay replay, ModCreatedReplayUser user = null) + { + Replay = replay; + User = user ?? new ModCreatedReplayUser(); + } + } + + /// + /// A user which is associated with a replay that was created by a mod (ie. autoplay or cinema). + /// + public class ModCreatedReplayUser : 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 60b9c29fe0..aa72812bc3 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics.Sprites; +using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Replays; @@ -11,7 +12,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 +31,18 @@ namespace osu.Game.Rulesets.Mods public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; + [Obsolete("Use CreateScoreFromReplayData(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) + { + Logger.Log($"Ruleset mod implementation for {GetType().Name} should be updated to newer {nameof(ICreateReplayData)} signature.", LoggingTarget.Information); + +#pragma warning disable CS0618 + var replayScore = CreateReplayScore(beatmap, mods); +#pragma warning restore CS0618 + + return new ModReplayData(replayScore.Replay, new ModCreatedReplayUser { Username = replayScore.ScoreInfo.User.Username }); + } } } From ea9495eb74e42393063675dca467f5edd426e39c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Mar 2022 16:45:21 +0900 Subject: [PATCH 07/25] Update all existing calls to extension method with correct fallback handling --- .../Visual/Gameplay/TestSceneReplay.cs | 2 +- .../Edit/DrawableEditorRulesetWrapper.cs | 2 +- osu.Game/Rulesets/Mods/ModExtensions.cs | 31 +++++++++++++++++++ osu.Game/Screens/Select/PlaySongSelect.cs | 24 ++++++++++++-- .../Skinning/Editor/SkinEditorSceneLibrary.cs | 3 +- osu.Game/Tests/Visual/TestPlayer.cs | 2 +- osu.Game/Tests/Visual/TestReplayPlayer.cs | 2 +- 7 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 osu.Game/Rulesets/Mods/ModExtensions.cs 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/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/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 94aa165785..17dc4524fe 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Screens; using osu.Game.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; @@ -111,9 +112,28 @@ 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) => + { + var replayData = replayGeneratingMod.CreateReplayData(beatmap, mods); + + return new Score + { + Replay = replayData.Replay, + ScoreInfo = + { + User = new APIUser + { + Id = APIUser.SYSTEM_USER_ID, + Username = replayData.User.Username, + } + } + }; + }); + } 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 From 4b2c01a8c1591c480f092fe5473f39c6aa3e185b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 29 Mar 2022 16:59:03 +0900 Subject: [PATCH 08/25] Bring all mod implementations up-to-date --- .../Mods/EmptyFreeformModAutoplay.cs | 16 ++------------ .../Mods/PippidonModAutoplay.cs | 16 ++------------ .../Mods/EmptyScrollingModAutoplay.cs | 22 +++++-------------- .../Mods/PippidonModAutoplay.cs | 16 ++------------ .../Mods/CatchModAutoplay.cs | 16 ++------------ .../Mods/CatchModCinema.cs | 16 ++------------ .../Mods/ManiaModAutoplay.cs | 16 ++------------ .../Mods/ManiaModCinema.cs | 16 ++------------ .../TestSceneMissHitWindowJudgements.cs | 9 ++------ osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 16 ++------------ osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs | 16 ++------------ .../Mods/TaikoModAutoplay.cs | 16 ++------------ .../Mods/TaikoModCinema.cs | 16 ++------------ 13 files changed, 29 insertions(+), 178 deletions(-) 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 9c2a108c4e..dfa0615604 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,26 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "sample" - }, - }, - Replay = new EmptyFreeformAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new EmptyFreeformAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { 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 6683856a1a..6a24812ce8 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,26 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "sample" - }, - }, - Replay = new PippidonAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new PippidonAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { 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 e3cecc7b44..cd0233fb51 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,28 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "sample" - }, - }, - Replay = new EmptyScrollingAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new EmptyScrollingAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { 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 6683856a1a..6a24812ce8 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,26 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "sample" - }, - }, - Replay = new PippidonAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new PippidonAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "sample" }); } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs index fbbb610035..08deb8378a 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -3,26 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "osu!salad" - } - }, - Replay = new CatchAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new CatchAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "osu!salad" }); } } diff --git a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs index 2f4769048f..d499348a09 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs @@ -3,27 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "osu!salad" - } - }, - Replay = new CatchAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new CatchAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "osu!salad" }); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs index 4eea0d4a44..9ea7852808 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -3,27 +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 - { - Id = APIUser.SYSTEM_USER_ID, - 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 ModCreatedReplayUser { Username = "osu!topus" }); } } diff --git a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs index 0aa419bbcb..a5d33261c5 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs @@ -3,28 +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 - { - Id = APIUser.SYSTEM_USER_ID, - 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 ModCreatedReplayUser { Username = "osu!topus" }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs index 840d871b7b..124a519ab3 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 ModCreatedReplayUser { 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 c5b1c55c40..51283e171b 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,17 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "Autoplay", - } - }, - Replay = new OsuAutoGenerator(beatmap, mods).Generate() - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedReplayUser { Username = "Autoplay" }); } } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs index 83e6f0efb5..6ecf8b73d2 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,17 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "Autoplay" - } - }, - Replay = new OsuAutoGenerator(beatmap, mods).Generate() - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedReplayUser { Username = "Autoplay" }); } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs index b9bf3ab1b4..1579a121b6 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -3,26 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "mekkadosu!" - } - }, - Replay = new TaikoAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "mekkadosu!" }); } } diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs index 6ecf8a3b3d..831e182193 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs @@ -3,27 +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 - { - Id = APIUser.SYSTEM_USER_ID, - Username = "mekkadosu!" - } - }, - Replay = new TaikoAutoGenerator(beatmap).Generate(), - }; + public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) + => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "mekkadosu!" }); } } From 83bae81095dd8de79cfef2f166db8eeb16c0873a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 30 Mar 2022 22:02:51 +0200 Subject: [PATCH 09/25] Fill out `ICreateReplayData` xmldocs --- osu.Game/Rulesets/Mods/ICreateReplayData.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ICreateReplayData.cs b/osu.Game/Rulesets/Mods/ICreateReplayData.cs index b022949345..1d07b95e7a 100644 --- a/osu.Game/Rulesets/Mods/ICreateReplayData.cs +++ b/osu.Game/Rulesets/Mods/ICreateReplayData.cs @@ -5,6 +5,7 @@ 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 @@ -17,9 +18,13 @@ namespace osu.Game.Rulesets.Mods /// /// 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. + /// public ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods); } From 436dec68c993813c20a8ff6753f459390226e38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 30 Mar 2022 22:03:51 +0200 Subject: [PATCH 10/25] Use provided extension method instead of reimplementing locally --- osu.Game/Screens/Select/PlaySongSelect.cs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs index 3f2a5c6183..593436bbb7 100644 --- a/osu.Game/Screens/Select/PlaySongSelect.cs +++ b/osu.Game/Screens/Select/PlaySongSelect.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Screens; using osu.Game.Graphics; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets.Mods; @@ -103,23 +102,7 @@ namespace osu.Game.Screens.Select if (replayGeneratingMod != null) { - return new ReplayPlayer((beatmap, mods) => - { - var replayData = replayGeneratingMod.CreateReplayData(beatmap, mods); - - return new Score - { - Replay = replayData.Replay, - ScoreInfo = - { - User = new APIUser - { - Id = APIUser.SYSTEM_USER_ID, - Username = replayData.User.Username, - } - } - }; - }); + return new ReplayPlayer((beatmap, mods) => replayGeneratingMod.CreateScoreFromReplayData(beatmap, mods)); } return new SoloPlayer(); From f4184cb6fe5abc7ae7e86d7f0fecace52f4b010c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 30 Mar 2022 22:04:19 +0200 Subject: [PATCH 11/25] Fix typo in step name --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 518ab5a1d3..346a88a2d5 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -47,7 +47,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("score has combo", () => getResultsScreen().Score.Combo > 100); AddAssert("score has no misses", () => getResultsScreen().Score.Statistics[HitResult.Miss] == 0); - AddUntilStep("avatar dispalyed", () => getAvatar() != null); + AddUntilStep("avatar displayed", () => getAvatar() != null); AddAssert("avatar not clickable", () => getAvatar().ChildrenOfType().First().Action == null); ClickableAvatar getAvatar() => getResultsScreen() From 6874cdf0c88db8d49f9545fc633eaab9a7ea307c Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 31 Mar 2022 01:50:46 +0300 Subject: [PATCH 12/25] Remove unnecessary `public` prefix in interface method --- osu.Game/Rulesets/Mods/ICreateReplayData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ICreateReplayData.cs b/osu.Game/Rulesets/Mods/ICreateReplayData.cs index 1d07b95e7a..2b8305ac78 100644 --- a/osu.Game/Rulesets/Mods/ICreateReplayData.cs +++ b/osu.Game/Rulesets/Mods/ICreateReplayData.cs @@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mods /// For callers that want to receive a directly usable instance, /// the extension method is provided for convenience. /// - public ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods); + ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods); } /// From 234bec45cca3a30c66ea13c630066b9fef1b6c43 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 11:32:00 +0900 Subject: [PATCH 13/25] Remove unnecessary logging --- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 10fe97c180..7b9ae187ce 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -36,8 +36,6 @@ namespace osu.Game.Rulesets.Mods public virtual ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) { - Logger.Log($"Ruleset mod implementation for {GetType().Name} should be updated to newer {nameof(ICreateReplayData)} signature.", LoggingTarget.Information); - #pragma warning disable CS0618 var replayScore = CreateReplayScore(beatmap, mods); #pragma warning restore CS0618 From 2c1ccc7d365b26202949ce08ecf86d3146cae77d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 11:33:26 +0900 Subject: [PATCH 14/25] Update obsolete message to match targeted developers' use case Co-authored-by: Salman Ahmed --- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 7b9ae187ce..7e54c170bf 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Mods public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; - [Obsolete("Use CreateScoreFromReplayData(IBeatmap, IReadOnlyList) instead")] // Can be removed 20220929 + [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) From 0cac9359397ae36e322a628ec7cc8c8c5a43e2f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 11:34:23 +0900 Subject: [PATCH 15/25] Shorten class name of `ModCreatedReplayUser` --- .../Mods/EmptyFreeformModAutoplay.cs | 2 +- .../Mods/PippidonModAutoplay.cs | 2 +- .../Mods/EmptyScrollingModAutoplay.cs | 2 +- .../Mods/PippidonModAutoplay.cs | 2 +- osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs | 2 +- osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs | 2 +- osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs | 2 +- .../TestSceneMissHitWindowJudgements.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs | 2 +- osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs | 2 +- osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs | 2 +- osu.Game/Rulesets/Mods/ICreateReplay.cs | 2 +- osu.Game/Rulesets/Mods/ICreateReplayData.cs | 8 ++++---- osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 +- 16 files changed, 19 insertions(+), 19 deletions(-) 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 dfa0615604..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 @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.EmptyFreeform.Mods public class EmptyFreeformModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new EmptyFreeformAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "sample" }); + => 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 6a24812ce8..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 @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Pippidon.Mods public class PippidonModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new PippidonAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "sample" }); + => 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 cd0233fb51..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 @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.EmptyScrolling.Mods public class EmptyScrollingModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new EmptyScrollingAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "sample" }); + => 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 6a24812ce8..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 @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Pippidon.Mods public class PippidonModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new PippidonAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "sample" }); + => 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 08deb8378a..50e48101d3 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModAutoplay.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Catch.Mods public class CatchModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new CatchAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "osu!salad" }); + => 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 d499348a09..7eda6b37d3 100644 --- a/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs +++ b/osu.Game.Rulesets.Catch/Mods/CatchModCinema.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Catch.Mods public class CatchModCinema : ModCinema { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new CatchAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "osu!salad" }); + => 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 9ea7852808..d444c9b634 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModAutoplay.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), new ModCreatedReplayUser { Username = "osu!topus" }); + => 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 a5d33261c5..f0db742eac 100644 --- a/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs +++ b/osu.Game.Rulesets.Mania/Mods/ManiaModCinema.cs @@ -13,6 +13,6 @@ namespace osu.Game.Rulesets.Mania.Mods public class ManiaModCinema : ModCinema { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(), new ModCreatedReplayUser { Username = "osu!topus" }); + => 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 124a519ab3..a9325f98f7 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneMissHitWindowJudgements.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Osu.Tests private class TestAutoMod : OsuModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new MissingAutoGenerator(beatmap, mods).Generate(), new ModCreatedReplayUser { Username = "Autoplay" }); + => 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 51283e171b..31179cdf4a 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutoplay.cs @@ -15,6 +15,6 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAimAssist), typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedReplayUser { Username = "Autoplay" }); + => 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 6ecf8b73d2..d677ab43d0 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModCinema.cs @@ -16,6 +16,6 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAimAssist), typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray(); public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new OsuAutoGenerator(beatmap, mods).Generate(), new ModCreatedReplayUser { Username = "Autoplay" }); + => 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 1579a121b6..4b74b4991e 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModAutoplay.cs @@ -11,6 +11,6 @@ namespace osu.Game.Rulesets.Taiko.Mods public class TaikoModAutoplay : ModAutoplay { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "mekkadosu!" }); + => 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 831e182193..fee0cb2744 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModCinema.cs @@ -12,6 +12,6 @@ namespace osu.Game.Rulesets.Taiko.Mods public class TaikoModCinema : ModCinema { public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) - => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedReplayUser { Username = "mekkadosu!" }); + => new ModReplayData(new TaikoAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "mekkadosu!" }); } } diff --git a/osu.Game/Rulesets/Mods/ICreateReplay.cs b/osu.Game/Rulesets/Mods/ICreateReplay.cs index 4883ce5842..1e5eeca92c 100644 --- a/osu.Game/Rulesets/Mods/ICreateReplay.cs +++ b/osu.Game/Rulesets/Mods/ICreateReplay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mods ModReplayData ICreateReplayData.CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) { var replayScore = CreateReplayScore(beatmap, mods); - return new ModReplayData(replayScore.Replay, new ModCreatedReplayUser { Username = replayScore.ScoreInfo.User.Username }); + 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 index 2b8305ac78..7d208e9000 100644 --- a/osu.Game/Rulesets/Mods/ICreateReplayData.cs +++ b/osu.Game/Rulesets/Mods/ICreateReplayData.cs @@ -41,19 +41,19 @@ namespace osu.Game.Rulesets.Mods /// /// Placeholder user data to show in place of the local user when the associated mod is active. /// - public readonly ModCreatedReplayUser User; + public readonly ModCreatedUser User; - public ModReplayData(Replay replay, ModCreatedReplayUser user = null) + public ModReplayData(Replay replay, ModCreatedUser user = null) { Replay = replay; - User = user ?? new ModCreatedReplayUser(); + User = user ?? new ModCreatedUser(); } } /// /// A user which is associated with a replay that was created by a mod (ie. autoplay or cinema). /// - public class ModCreatedReplayUser : IUser + public class ModCreatedUser : IUser { public int OnlineID => APIUser.SYSTEM_USER_ID; public bool IsBot => true; diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 7e54c170bf..7a68de49b3 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Mods var replayScore = CreateReplayScore(beatmap, mods); #pragma warning restore CS0618 - return new ModReplayData(replayScore.Replay, new ModCreatedReplayUser { Username = replayScore.ScoreInfo.User.Username }); + return new ModReplayData(replayScore.Replay, new ModCreatedUser { Username = replayScore.ScoreInfo.User.Username }); } } } From e0d434b89fc51a91301cc0bbb953b4457b8386cf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 11:34:32 +0900 Subject: [PATCH 16/25] Remove unused using statement --- osu.Game/Rulesets/Mods/ModAutoplay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 7a68de49b3..87dc627b19 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics.Sprites; -using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Replays; From 6e94a9780bbe26d5a182fed29d7908f34c21baba Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 31 Mar 2022 12:22:56 +0900 Subject: [PATCH 17/25] Remove ScoreInfo allocations in multi leaderboard --- .../Play/HUD/MultiplayerGameplayLeaderboard.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 71998622ef..4832ee04af 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -228,6 +228,7 @@ namespace osu.Game.Screens.Play.HUD public int? Team => (User.MatchState as TeamVersusUserState)?.TeamID; private readonly RulesetInfo ruleset; + private readonly ScoreInfo scoreInfo; public TrackedUserData(MultiplayerRoomUser user, RulesetInfo ruleset, ScoreProcessor scoreProcessor) { @@ -236,6 +237,8 @@ namespace osu.Game.Screens.Play.HUD User = user; ScoreProcessor = scoreProcessor; + scoreInfo = new ScoreInfo { Ruleset = ruleset }; + ScoringMode.BindValueChanged(_ => UpdateScore()); } @@ -253,12 +256,10 @@ namespace osu.Game.Screens.Play.HUD { var header = frame.Header; - Score.Value = ScoreProcessor.ComputePartialScore(ScoringMode.Value, new ScoreInfo - { - Ruleset = ruleset, - MaxCombo = header.MaxCombo, - Statistics = header.Statistics - }); + scoreInfo.MaxCombo = header.MaxCombo; + scoreInfo.Statistics = header.Statistics; + + Score.Value = ScoreProcessor.ComputePartialScore(ScoringMode.Value, scoreInfo); Accuracy.Value = header.Accuracy; CurrentCombo.Value = header.Combo; From 9c19ae1df8061373e8a2f9481d17885def75d691 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 31 Mar 2022 06:40:38 +0300 Subject: [PATCH 18/25] Remove no longer necessary ruleset field --- osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs index 4832ee04af..4f5edab526 100644 --- a/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs +++ b/osu.Game/Screens/Play/HUD/MultiplayerGameplayLeaderboard.cs @@ -227,13 +227,10 @@ namespace osu.Game.Screens.Play.HUD public int? Team => (User.MatchState as TeamVersusUserState)?.TeamID; - private readonly RulesetInfo ruleset; private readonly ScoreInfo scoreInfo; public TrackedUserData(MultiplayerRoomUser user, RulesetInfo ruleset, ScoreProcessor scoreProcessor) { - this.ruleset = ruleset; - User = user; ScoreProcessor = scoreProcessor; From 36c02573a8e137a5e24d622b6f50893eade5b740 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Wed, 30 Mar 2022 21:26:30 -0700 Subject: [PATCH 19/25] Fix osu! logo being clicked when exiting via cmd-q on initial state --- osu.Game/Screens/Menu/ButtonSystem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Menu/ButtonSystem.cs b/osu.Game/Screens/Menu/ButtonSystem.cs index a1f0d22efc..8eeb90a3fd 100644 --- a/osu.Game/Screens/Menu/ButtonSystem.cs +++ b/osu.Game/Screens/Menu/ButtonSystem.cs @@ -207,6 +207,9 @@ namespace osu.Game.Screens.Menu protected override bool OnKeyDown(KeyDownEvent e) { + if (e.Repeat || e.ControlPressed || e.ShiftPressed || e.AltPressed || e.SuperPressed) + return false; + if (State == ButtonSystemState.Initial) { if (buttonsTopLevel.Any(b => e.Key == b.TriggerKey)) From 615e4f0f3b3c7a8872c27b70017a4ad385697780 Mon Sep 17 00:00:00 2001 From: Joseph Madamba Date: Mon, 28 Mar 2022 15:16:37 -0700 Subject: [PATCH 20/25] Ignore line ending normalisation commit from blame --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..8be6479043 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Normalize all the line endings +32a74f95a5c80a0ed18e693f13a47522099df5c3 From e8a295a61bc548ca8878ea2ca92f6aa04ec20d9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 15:18:24 +0900 Subject: [PATCH 21/25] Add test coverage of textbox focus in settings panels when switching between nested panels --- .../Visual/Settings/TestSceneSettingsPanel.cs | 57 ++++++++++++++++++- osu.Game/Overlays/SettingsSubPanel.cs | 2 +- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs index 0af77b3b5a..f9c9b2a68b 100644 --- a/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs +++ b/osu.Game.Tests/Visual/Settings/TestSceneSettingsPanel.cs @@ -1,16 +1,21 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Testing; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; +using osu.Game.Overlays.Settings.Sections; +using osu.Game.Overlays.Settings.Sections.Input; +using osuTK.Input; namespace osu.Game.Tests.Visual.Settings { [TestFixture] - public class TestSceneSettingsPanel : OsuTestScene + public class TestSceneSettingsPanel : OsuManualInputManagerTestScene { private SettingsPanel settings; private DialogOverlay dialogOverlay; @@ -33,7 +38,55 @@ namespace osu.Game.Tests.Visual.Settings public void ToggleVisibility() { AddWaitStep("wait some", 5); - AddToggleStep("toggle editor visibility", visible => settings.ToggleVisibility()); + AddToggleStep("toggle visibility", visible => settings.ToggleVisibility()); + } + + [Test] + public void TestTextboxFocusAfterNestedPanelBackButton() + { + AddUntilStep("sections loaded", () => settings.SectionsContainer.Children.Count > 0); + AddUntilStep("top-level textbox focused", () => settings.SectionsContainer.ChildrenOfType().FirstOrDefault()?.HasFocus == true); + + AddStep("open key binding subpanel", () => + { + settings.SectionsContainer + .ChildrenOfType().FirstOrDefault()? + .ChildrenOfType().FirstOrDefault()? + .TriggerClick(); + }); + + AddUntilStep("binding panel textbox focused", () => settings + .ChildrenOfType().FirstOrDefault()? + .ChildrenOfType().FirstOrDefault()?.HasFocus == true); + + AddStep("Press back", () => settings + .ChildrenOfType().FirstOrDefault()? + .ChildrenOfType().FirstOrDefault()?.TriggerClick()); + + AddUntilStep("top-level textbox focused", () => settings.SectionsContainer.ChildrenOfType().FirstOrDefault()?.HasFocus == true); + } + + [Test] + public void TestTextboxFocusAfterNestedPanelEscape() + { + AddUntilStep("sections loaded", () => settings.SectionsContainer.Children.Count > 0); + AddUntilStep("top-level textbox focused", () => settings.SectionsContainer.ChildrenOfType().FirstOrDefault()?.HasFocus == true); + + AddStep("open key binding subpanel", () => + { + settings.SectionsContainer + .ChildrenOfType().FirstOrDefault()? + .ChildrenOfType().FirstOrDefault()? + .TriggerClick(); + }); + + AddUntilStep("binding panel textbox focused", () => settings + .ChildrenOfType().FirstOrDefault()? + .ChildrenOfType().FirstOrDefault()?.HasFocus == true); + + AddStep("Escape", () => InputManager.Key(Key.Escape)); + + AddUntilStep("top-level textbox focused", () => settings.SectionsContainer.ChildrenOfType().FirstOrDefault()?.HasFocus == true); } [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/SettingsSubPanel.cs b/osu.Game/Overlays/SettingsSubPanel.cs index da806c09d3..d55c609d3f 100644 --- a/osu.Game/Overlays/SettingsSubPanel.cs +++ b/osu.Game/Overlays/SettingsSubPanel.cs @@ -32,7 +32,7 @@ namespace osu.Game.Overlays protected override bool DimMainContent => false; // dimming is handled by main overlay - private class BackButton : SidebarButton + public class BackButton : SidebarButton { private Container content; From 726b49fdf3e170d67a9d07e54de12e1df0c741f0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 15:19:34 +0900 Subject: [PATCH 22/25] Focus focus not being transferred correctly to parent settings panel on exiting nested panel Seemingly harmless schedule delay ommission meant that the textbox may not be in a state it can handle the incoming focus event. Regressed in https://github.com/ppy/osu/pull/14345#discussion_r690697501. --- osu.Game/Graphics/UserInterface/FocusedTextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs index 578ff3c618..d3a76a0f1a 100644 --- a/osu.Game/Graphics/UserInterface/FocusedTextBox.cs +++ b/osu.Game/Graphics/UserInterface/FocusedTextBox.cs @@ -28,7 +28,7 @@ namespace osu.Game.Graphics.UserInterface if (!allowImmediateFocus) return; - Scheduler.Add(() => GetContainingInputManager().ChangeFocus(this), false); + Scheduler.Add(() => GetContainingInputManager().ChangeFocus(this)); } public new void KillFocus() => base.KillFocus(); From ef5e37c47a1099c393238d53e8e80f9621c1b06a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 16:18:26 +0900 Subject: [PATCH 23/25] Fix multiplayer sounds playing too much after gameplay Regressed in https://github.com/ppy/osu/pull/15936. Closes #17295. --- .../OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs index d467a32acb..49b5b7fed9 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerRoomSounds.cs @@ -37,21 +37,21 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer { base.UserJoined(user); - userJoinedSample?.Play(); + Scheduler.AddOnce(() => userJoinedSample?.Play()); } protected override void UserLeft(MultiplayerRoomUser user) { base.UserLeft(user); - userLeftSample?.Play(); + Scheduler.AddOnce(() => userLeftSample?.Play()); } protected override void UserKicked(MultiplayerRoomUser user) { base.UserKicked(user); - userKickedSample?.Play(); + Scheduler.AddOnce(() => userKickedSample?.Play()); } private void hostChanged(ValueChangedEvent value) @@ -59,7 +59,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer // only play sound when the host changes from an already-existing host. if (value.OldValue == null) return; - hostChangedSample?.Play(); + Scheduler.AddOnce(() => hostChangedSample?.Play()); } } } From a7a7584d3ec5077c98fa7c8bb02aa7beb5bda09e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 18:31:18 +0900 Subject: [PATCH 24/25] Add test coverage ensuring ruleset ID is correct after bracket read Historically, tournament client may have written incorrect `OnlineID` values. We wanted to use `ShortName` to re-fetch the ruleset. This test ensures this flow is working correctly. --- .../NonVisual/DataLoadTest.cs | 60 ++++++++++++++++++- osu.Game.Tournament/TournamentGameBase.cs | 4 +- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs index 65753bfe00..4c1256df2e 100644 --- a/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs +++ b/osu.Game.Tournament.Tests/NonVisual/DataLoadTest.cs @@ -1,9 +1,13 @@ // 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.IO; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions; using osu.Framework.Platform; using osu.Game.Rulesets; using osu.Game.Tests; @@ -12,6 +16,45 @@ namespace osu.Game.Tournament.Tests.NonVisual { public class DataLoadTest : TournamentHostTest { + [Test] + public void TestRulesetGetsValidOnlineID() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost()) + { + try + { + var osu = new TestTournament(runOnLoadComplete: () => + { + // ReSharper disable once AccessToDisposedClosure + var storage = host.Storage.GetStorageForDirectory(Path.Combine("tournaments", "default")); + + using (var stream = storage.GetStream("bracket.json", FileAccess.Write, FileMode.Create)) + using (var writer = new StreamWriter(stream)) + { + writer.Write(@"{ + ""Ruleset"": { + ""ShortName"": ""taiko"", + ""OnlineID"": -1, + ""Name"": ""osu!taiko"", + ""InstantiationInfo"": ""osu.Game.Rulesets.OsuTaiko.TaikoRuleset, osu.Game.Rulesets.Taiko"", + ""Available"": true + } }"); + } + }); + + LoadTournament(host, osu); + + osu.BracketLoadTask.WaitSafely(); + + Assert.That(osu.Dependencies.Get>().Value.OnlineID, Is.EqualTo(1)); + } + finally + { + host.Exit(); + } + } + } + [Test] public void TestUnavailableRuleset() { @@ -19,7 +62,7 @@ namespace osu.Game.Tournament.Tests.NonVisual { try { - var osu = new TestTournament(); + var osu = new TestTournament(true); LoadTournament(host, osu); var storage = osu.Dependencies.Get(); @@ -35,10 +78,23 @@ namespace osu.Game.Tournament.Tests.NonVisual public class TestTournament : TournamentGameBase { + private readonly bool resetRuleset; + private readonly Action runOnLoadComplete; + + public new Task BracketLoadTask => base.BracketLoadTask; + + public TestTournament(bool resetRuleset = false, Action runOnLoadComplete = null) + { + this.resetRuleset = resetRuleset; + this.runOnLoadComplete = runOnLoadComplete; + } + protected override void LoadComplete() { + runOnLoadComplete?.Invoke(); base.LoadComplete(); - Ruleset.Value = new RulesetInfo(); // not available + if (resetRuleset) + Ruleset.Value = new RulesetInfo(); // not available } } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index f318c8bd85..b88f4edaa6 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -64,8 +64,6 @@ namespace osu.Game.Tournament Textures.AddStore(new TextureLoaderStore(new StorageBackedResourceStore(storage))); dependencies.CacheAs(new StableInfo(storage)); - - Task.Run(readBracket); } private void readBracket() @@ -290,6 +288,8 @@ namespace osu.Game.Tournament MenuCursorContainer.Cursor.Alpha = 0; base.LoadComplete(); + + Task.Run(readBracket); } protected virtual void SaveChanges() From a06b0a49662c94b53c05d1c482d6457cf1c3bb98 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Mar 2022 18:40:58 +0900 Subject: [PATCH 25/25] Fix tournament bracket parsing's ruleset refetch logic not working correctly Due to equality being based on `ShortName`, it was feasible that the re-fetch exited early (in bindable shortcutting logic) causing the ruleset's `OnlineID` to remain `-1` or something equally wrong. Resolves issue pointed out at https://github.com/ppy/osu/discussions/17538#discussioncomment-2471746. --- osu.Game.Tournament/TournamentGameBase.cs | 30 +++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index b88f4edaa6..a251a043f7 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -66,6 +66,18 @@ namespace osu.Game.Tournament dependencies.CacheAs(new StableInfo(storage)); } + protected override void LoadComplete() + { + MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display + + // we don't want to show the menu cursor as it would appear on stream output. + MenuCursorContainer.Cursor.Alpha = 0; + + base.LoadComplete(); + + Task.Run(readBracket); + } + private void readBracket() { try @@ -79,10 +91,14 @@ namespace osu.Game.Tournament ladder ??= new LadderInfo(); - ladder.Ruleset.Value = ladder.Ruleset.Value != null + var resolvedRuleset = ladder.Ruleset.Value != null ? RulesetStore.GetRuleset(ladder.Ruleset.Value.ShortName) : RulesetStore.AvailableRulesets.First(); + // Must set to null initially to avoid the following re-fetch hitting `ShortName` based equality check. + ladder.Ruleset.Value = null; + ladder.Ruleset.Value = resolvedRuleset; + bool addedInfo = false; // assign teams @@ -280,18 +296,6 @@ namespace osu.Game.Tournament } } - protected override void LoadComplete() - { - MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display - - // we don't want to show the menu cursor as it would appear on stream output. - MenuCursorContainer.Cursor.Alpha = 0; - - base.LoadComplete(); - - Task.Run(readBracket); - } - protected virtual void SaveChanges() { if (!bracketLoadTaskCompletionSource.Task.IsCompletedSuccessfully)