From e88dff0c8771e68ea59e34e610ca2bf27138233a Mon Sep 17 00:00:00 2001 From: minisbett <39670899+minisbett@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:31:36 +0100 Subject: [PATCH] turn difficulty attributes into a struct --- .../EmptyFreeformDifficultyCalculator.cs | 4 +- .../PippidonDifficultyCalculator.cs | 4 +- .../EmptyScrollingDifficultyCalculator.cs | 4 +- .../PippidonDifficultyCalculator.cs | 4 +- .../Difficulty/CatchDifficultyAttributes.cs | 34 ++++++---- .../Difficulty/CatchDifficultyCalculator.cs | 2 +- .../Difficulty/CatchPerformanceCalculator.cs | 2 +- .../Difficulty/ManiaDifficultyAttributes.cs | 34 ++++++---- .../Difficulty/ManiaDifficultyCalculator.cs | 2 +- .../Difficulty/ManiaPerformanceCalculator.cs | 2 +- .../Difficulty/OsuDifficultyAttributes.cs | 65 +++++++++++-------- .../Difficulty/OsuDifficultyCalculator.cs | 2 +- .../Difficulty/OsuPerformanceCalculator.cs | 2 +- .../Difficulty/TaikoDifficultyAttributes.cs | 39 +++++++---- .../Difficulty/TaikoDifficultyCalculator.cs | 2 +- .../Difficulty/TaikoPerformanceCalculator.cs | 2 +- ...DifficultyAdjustmentModCombinationsTest.cs | 2 +- .../TestSceneTimedDifficultyCalculation.cs | 4 +- osu.Game/Beatmaps/StarDifficulty.cs | 8 +-- .../Difficulty/DifficultyCalculator.cs | 10 +-- ...Attributes.cs => IDifficultyAttributes.cs} | 37 ++--------- ...ttributes.cs => IPerformanceAttributes.cs} | 0 .../Difficulty/PerformanceCalculator.cs | 6 +- .../Difficulty/TimedDifficultyAttributes.cs | 6 +- .../Play/HUD/PerformancePointsCounter.cs | 2 +- 25 files changed, 147 insertions(+), 132 deletions(-) rename osu.Game/Rulesets/Difficulty/{DifficultyAttributes.cs => IDifficultyAttributes.cs} (65%) rename osu.Game/Rulesets/Difficulty/{PerformanceAttributes.cs => IPerformanceAttributes.cs} (100%) diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs index 312d3d5e9a..2178941fd8 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/EmptyFreeformDifficultyCalculator.cs @@ -19,9 +19,9 @@ namespace osu.Game.Rulesets.EmptyFreeform { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - return new DifficultyAttributes(mods, 0); + return new IDifficultyAttributes(mods, 0); } protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs index f6addab279..55cf4fb42d 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs @@ -19,9 +19,9 @@ namespace osu.Game.Rulesets.Pippidon { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - return new DifficultyAttributes(mods, 0); + return new IDifficultyAttributes(mods, 0); } protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs index a4dc1762d5..47215ce7d9 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/EmptyScrollingDifficultyCalculator.cs @@ -19,9 +19,9 @@ namespace osu.Game.Rulesets.EmptyScrolling { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - return new DifficultyAttributes(mods, 0); + return new IDifficultyAttributes(mods, 0); } protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs index f6addab279..55cf4fb42d 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/PippidonDifficultyCalculator.cs @@ -19,9 +19,9 @@ namespace osu.Game.Rulesets.Pippidon { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { - return new DifficultyAttributes(mods, 0); + return new IDifficultyAttributes(mods, 0); } protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty(); diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs index 5c64643fd4..3ff1c0dd01 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyAttributes.cs @@ -1,15 +1,28 @@ // 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 Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Catch.Difficulty { - public class CatchDifficultyAttributes : DifficultyAttributes + public struct CatchDifficultyAttributes : IDifficultyAttributes { + public CatchDifficultyAttributes() { } + + /// + public Mod[] Mods { get; set; } = Array.Empty(); + + /// + public double StarRating { get; set; } + + /// + public int MaxCombo { get; set; } + /// /// The perceived approach rate inclusive of rate-adjusting mods (DT/HT/etc). /// @@ -19,22 +32,19 @@ namespace osu.Game.Rulesets.Catch.Difficulty [JsonProperty("approach_rate")] public double ApproachRate { get; set; } - public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + public IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() { - foreach (var v in base.ToDatabaseAttributes()) - yield return v; - + yield return (IDifficultyAttributes.ATTRIB_ID_MAX_COMBO, MaxCombo); // Todo: osu!catch should not output star rating in the 'aim' attribute. - yield return (ATTRIB_ID_AIM, StarRating); - yield return (ATTRIB_ID_APPROACH_RATE, ApproachRate); + yield return (IDifficultyAttributes.ATTRIB_ID_AIM, StarRating); + yield return (IDifficultyAttributes.ATTRIB_ID_APPROACH_RATE, ApproachRate); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) + public void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values, onlineInfo); - - StarRating = values[ATTRIB_ID_AIM]; - ApproachRate = values[ATTRIB_ID_APPROACH_RATE]; + MaxCombo = (int)values[IDifficultyAttributes.ATTRIB_ID_MAX_COMBO]; + StarRating = values[IDifficultyAttributes.ATTRIB_ID_AIM]; + ApproachRate = values[IDifficultyAttributes.ATTRIB_ID_APPROACH_RATE]; } } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index 7d21409ee8..4637fd3c0a 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) return new CatchDifficultyAttributes { Mods = mods }; diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index efca1e5e77..a8a0e3c444 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { } - protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, IDifficultyAttributes attributes) { var catchAttributes = (CatchDifficultyAttributes)attributes; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs index db60e757e1..8244334748 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyAttributes.cs @@ -1,15 +1,28 @@ // 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 Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Mania.Difficulty { - public class ManiaDifficultyAttributes : DifficultyAttributes + public struct ManiaDifficultyAttributes : IDifficultyAttributes { + public ManiaDifficultyAttributes() { } + + /// + public Mod[] Mods { get; set; } = Array.Empty(); + + /// + public double StarRating { get; set; } + + /// + public int MaxCombo { get; set; } + /// /// The hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc). /// @@ -19,21 +32,18 @@ namespace osu.Game.Rulesets.Mania.Difficulty [JsonProperty("great_hit_window")] public double GreatHitWindow { get; set; } - public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + public IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() { - foreach (var v in base.ToDatabaseAttributes()) - yield return v; - - yield return (ATTRIB_ID_DIFFICULTY, StarRating); - yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); + yield return (IDifficultyAttributes.ATTRIB_ID_MAX_COMBO, MaxCombo); + yield return (IDifficultyAttributes.ATTRIB_ID_DIFFICULTY, StarRating); + yield return (IDifficultyAttributes.ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) + public void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values, onlineInfo); - - StarRating = values[ATTRIB_ID_DIFFICULTY]; - GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; + MaxCombo = (int)values[IDifficultyAttributes.ATTRIB_ID_MAX_COMBO]; + StarRating = values[IDifficultyAttributes.ATTRIB_ID_DIFFICULTY]; + GreatHitWindow = values[IDifficultyAttributes.ATTRIB_ID_GREAT_HIT_WINDOW]; } } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs index ff9aa4aa7b..ae49c495c5 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty; } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) return new ManiaDifficultyAttributes { Mods = mods }; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 4d1b9b5766..b01bcc2d04 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty { } - protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, IDifficultyAttributes attributes) { var maniaAttributes = (ManiaDifficultyAttributes)attributes; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs index a3c0209a08..315b7b5fbc 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs @@ -1,6 +1,7 @@ // 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 System.Linq; using JetBrains.Annotations; @@ -11,8 +12,19 @@ using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Osu.Difficulty { - public class OsuDifficultyAttributes : DifficultyAttributes + public struct OsuDifficultyAttributes : IDifficultyAttributes { + public OsuDifficultyAttributes() { } + + /// + public Mod[] Mods { get; set; } = Array.Empty(); + + /// + public double StarRating { get; set; } + + /// + public int MaxCombo { get; set; } + /// /// The difficulty corresponding to the aim skill. /// @@ -90,41 +102,38 @@ namespace osu.Game.Rulesets.Osu.Difficulty /// public int SpinnerCount { get; set; } - public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + public IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() { - foreach (var v in base.ToDatabaseAttributes()) - yield return v; - - yield return (ATTRIB_ID_AIM, AimDifficulty); - yield return (ATTRIB_ID_SPEED, SpeedDifficulty); - yield return (ATTRIB_ID_OVERALL_DIFFICULTY, OverallDifficulty); - yield return (ATTRIB_ID_APPROACH_RATE, ApproachRate); - yield return (ATTRIB_ID_DIFFICULTY, StarRating); + yield return (IDifficultyAttributes.ATTRIB_ID_MAX_COMBO, MaxCombo); + yield return (IDifficultyAttributes.ATTRIB_ID_AIM, AimDifficulty); + yield return (IDifficultyAttributes.ATTRIB_ID_SPEED, SpeedDifficulty); + yield return (IDifficultyAttributes.ATTRIB_ID_OVERALL_DIFFICULTY, OverallDifficulty); + yield return (IDifficultyAttributes.ATTRIB_ID_APPROACH_RATE, ApproachRate); + yield return (IDifficultyAttributes.ATTRIB_ID_DIFFICULTY, StarRating); if (ShouldSerializeFlashlightDifficulty()) - yield return (ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty); + yield return (IDifficultyAttributes.ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty); - yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor); + yield return (IDifficultyAttributes.ATTRIB_ID_SLIDER_FACTOR, SliderFactor); - yield return (ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT, AimDifficultStrainCount); - yield return (ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT, SpeedDifficultStrainCount); - yield return (ATTRIB_ID_SPEED_NOTE_COUNT, SpeedNoteCount); + yield return (IDifficultyAttributes.ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT, AimDifficultStrainCount); + yield return (IDifficultyAttributes.ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT, SpeedDifficultStrainCount); + yield return (IDifficultyAttributes.ATTRIB_ID_SPEED_NOTE_COUNT, SpeedNoteCount); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) + public void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values, onlineInfo); - - AimDifficulty = values[ATTRIB_ID_AIM]; - SpeedDifficulty = values[ATTRIB_ID_SPEED]; - OverallDifficulty = values[ATTRIB_ID_OVERALL_DIFFICULTY]; - ApproachRate = values[ATTRIB_ID_APPROACH_RATE]; - StarRating = values[ATTRIB_ID_DIFFICULTY]; - FlashlightDifficulty = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT); - SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR]; - AimDifficultStrainCount = values[ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT]; - SpeedDifficultStrainCount = values[ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT]; - SpeedNoteCount = values[ATTRIB_ID_SPEED_NOTE_COUNT]; + MaxCombo = (int)values[IDifficultyAttributes.ATTRIB_ID_MAX_COMBO]; + AimDifficulty = values[IDifficultyAttributes.ATTRIB_ID_AIM]; + SpeedDifficulty = values[IDifficultyAttributes.ATTRIB_ID_SPEED]; + OverallDifficulty = values[IDifficultyAttributes.ATTRIB_ID_OVERALL_DIFFICULTY]; + ApproachRate = values[IDifficultyAttributes.ATTRIB_ID_APPROACH_RATE]; + StarRating = values[IDifficultyAttributes.ATTRIB_ID_DIFFICULTY]; + FlashlightDifficulty = values.GetValueOrDefault(IDifficultyAttributes.ATTRIB_ID_FLASHLIGHT); + SliderFactor = values[IDifficultyAttributes.ATTRIB_ID_SLIDER_FACTOR]; + AimDifficultStrainCount = values[IDifficultyAttributes.ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT]; + SpeedDifficultStrainCount = values[IDifficultyAttributes.ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT]; + SpeedNoteCount = values[IDifficultyAttributes.ATTRIB_ID_SPEED_NOTE_COUNT]; DrainRate = onlineInfo.DrainRate; HitCircleCount = onlineInfo.CircleCount; SliderCount = onlineInfo.SliderCount; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index acf01b2a83..97603bb16a 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) return new OsuDifficultyAttributes { Mods = mods }; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index 8425f437cc..b79a8feb96 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty { } - protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, IDifficultyAttributes attributes) { var osuAttributes = (OsuDifficultyAttributes)attributes; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs index 451aed183d..337e1c1488 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyAttributes.cs @@ -1,15 +1,29 @@ // 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 Newtonsoft.Json; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; +using osu.Game.Rulesets.Mods; namespace osu.Game.Rulesets.Taiko.Difficulty { - public class TaikoDifficultyAttributes : DifficultyAttributes + public struct TaikoDifficultyAttributes : IDifficultyAttributes { + public TaikoDifficultyAttributes() { } + + /// + public Mod[] Mods { get; set; } = Array.Empty(); + + /// + public double StarRating { get; set; } + + /// + [JsonProperty("max_combo", Order = -2)] + public int MaxCombo { get; set; } + /// /// The difficulty corresponding to the stamina skill. /// @@ -52,23 +66,20 @@ namespace osu.Game.Rulesets.Taiko.Difficulty [JsonProperty("ok_hit_window")] public double OkHitWindow { get; set; } - public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + public IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() { - foreach (var v in base.ToDatabaseAttributes()) - yield return v; - - yield return (ATTRIB_ID_DIFFICULTY, StarRating); - yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); - yield return (ATTRIB_ID_OK_HIT_WINDOW, OkHitWindow); + yield return (IDifficultyAttributes.ATTRIB_ID_MAX_COMBO, MaxCombo); + yield return (IDifficultyAttributes.ATTRIB_ID_DIFFICULTY, StarRating); + yield return (IDifficultyAttributes.ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); + yield return (IDifficultyAttributes.ATTRIB_ID_OK_HIT_WINDOW, OkHitWindow); } - public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) + public void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - base.FromDatabaseAttributes(values, onlineInfo); - - StarRating = values[ATTRIB_ID_DIFFICULTY]; - GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; - OkHitWindow = values[ATTRIB_ID_OK_HIT_WINDOW]; + MaxCombo = (int)values[IDifficultyAttributes.ATTRIB_ID_MAX_COMBO]; + StarRating = values[IDifficultyAttributes.ATTRIB_ID_DIFFICULTY]; + GreatHitWindow = values[IDifficultyAttributes.ATTRIB_ID_GREAT_HIT_WINDOW]; + OkHitWindow = values[IDifficultyAttributes.ATTRIB_ID_OK_HIT_WINDOW]; } } } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs index 18223e74fa..4b86620b39 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs @@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty return difficultyHitObjects; } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) return new TaikoDifficultyAttributes { Mods = mods }; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index 29eadf417f..7373993629 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { } - protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, IDifficultyAttributes attributes) { var taikoAttributes = (TaikoDifficultyAttributes)attributes; diff --git a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs index 6b1b883ce7..7c63bbd9a3 100644 --- a/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs +++ b/osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs @@ -222,7 +222,7 @@ namespace osu.Game.Tests.NonVisual protected override Mod[] DifficultyAdjustmentMods { get; } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { throw new NotImplementedException(); } diff --git a/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs b/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs index f860cd097a..5db37dd810 100644 --- a/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs +++ b/osu.Game.Tests/NonVisual/TestSceneTimedDifficultyCalculation.cs @@ -172,7 +172,7 @@ namespace osu.Game.Tests.NonVisual { } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + protected override IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) => new TestDifficultyAttributes { Objects = beatmap.HitObjects.ToArray() }; protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) @@ -208,7 +208,7 @@ namespace osu.Game.Tests.NonVisual } } - private class TestDifficultyAttributes : DifficultyAttributes + private class TestDifficultyAttributes : IDifficultyAttributes { public HitObject[] Objects = Array.Empty(); } diff --git a/osu.Game/Beatmaps/StarDifficulty.cs b/osu.Game/Beatmaps/StarDifficulty.cs index 6aac275a6a..e0a7e724a3 100644 --- a/osu.Game/Beatmaps/StarDifficulty.cs +++ b/osu.Game/Beatmaps/StarDifficulty.cs @@ -26,13 +26,13 @@ namespace osu.Game.Beatmaps /// Might not be available if the star difficulty is associated with a beatmap that's not locally available. /// [CanBeNull] - public readonly DifficultyAttributes Attributes; + public readonly IDifficultyAttributes Attributes; /// - /// Creates a structure based on computed + /// Creates a structure based on computed /// by a . /// - public StarDifficulty([NotNull] DifficultyAttributes attributes) + public StarDifficulty([NotNull] IDifficultyAttributes attributes) { Stars = double.IsFinite(attributes.StarRating) ? attributes.StarRating : 0; MaxCombo = attributes.MaxCombo; @@ -42,7 +42,7 @@ namespace osu.Game.Beatmaps /// /// Creates a structure with a pre-populated star difficulty and max combo - /// in scenarios where computing is not feasible (i.e. when working with online sources). + /// in scenarios where computing is not feasible (i.e. when working with online sources). /// public StarDifficulty(double starDifficulty, int maxCombo) { diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index 63b27243d0..39340776f0 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Difficulty /// /// The cancellation token. /// A structure describing the difficulty of the beatmap. - public DifficultyAttributes Calculate(CancellationToken cancellationToken = default) + public IDifficultyAttributes Calculate(CancellationToken cancellationToken = default) => Calculate(Array.Empty(), cancellationToken); /// @@ -60,7 +60,7 @@ namespace osu.Game.Rulesets.Difficulty /// The mods that should be applied to the beatmap. /// The cancellation token. /// A structure describing the difficulty of the beatmap. - public DifficultyAttributes Calculate([NotNull] IEnumerable mods, CancellationToken cancellationToken = default) + public IDifficultyAttributes Calculate([NotNull] IEnumerable mods, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); preProcess(mods, cancellationToken); @@ -140,7 +140,7 @@ namespace osu.Game.Rulesets.Difficulty /// This can only be used to compute difficulties for legacy mod combinations. /// /// A collection of structures describing the difficulty of the beatmap for each mod combination. - public IEnumerable CalculateAllLegacyCombinations(CancellationToken cancellationToken = default) + public IEnumerable CalculateAllLegacyCombinations(CancellationToken cancellationToken = default) { var rulesetInstance = ruleset.CreateInstance(); @@ -263,14 +263,14 @@ namespace osu.Game.Rulesets.Difficulty protected virtual Mod[] DifficultyAdjustmentMods => Array.Empty(); /// - /// Creates to describe beatmap's calculated difficulty. + /// Creates to describe beatmap's calculated difficulty. /// /// The whose difficulty was calculated. /// This may differ from in the case of timed calculation. /// The s that difficulty was calculated with. /// The skills which processed the beatmap. /// The rate at which the gameplay clock is run at. - protected abstract DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate); + protected abstract IDifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate); /// /// Enumerates s to be processed from s in the . diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/IDifficultyAttributes.cs similarity index 65% rename from osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs rename to osu.Game/Rulesets/Difficulty/IDifficultyAttributes.cs index ae4239c148..b951b5fb11 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/IDifficultyAttributes.cs @@ -1,7 +1,6 @@ // 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 Newtonsoft.Json; using osu.Game.Beatmaps; @@ -13,7 +12,7 @@ namespace osu.Game.Rulesets.Difficulty /// Describes the difficulty of a beatmap, as output by a . /// [JsonObject(MemberSerialization.OptIn)] - public class DifficultyAttributes + public interface IDifficultyAttributes { protected const int ATTRIB_ID_AIM = 1; protected const int ATTRIB_ID_SPEED = 3; @@ -33,7 +32,7 @@ namespace osu.Game.Rulesets.Difficulty /// /// The mods which were applied to the beatmap. /// - public Mod[] Mods { get; set; } = Array.Empty(); + public Mod[] Mods { get; set; } /// /// The combined star rating of all skills. @@ -48,42 +47,18 @@ namespace osu.Game.Rulesets.Difficulty public int MaxCombo { get; set; } /// - /// Creates new . - /// - public DifficultyAttributes() - { - } - - /// - /// Creates new . - /// - /// The mods which were applied to the beatmap. - /// The combined star rating of all skills. - public DifficultyAttributes(Mod[] mods, double starRating) - { - Mods = mods; - StarRating = starRating; - } - - /// - /// Converts this to osu-web compatible database attribute mappings. + /// Converts this to osu-web compatible database attribute mappings. /// /// /// See: osu_difficulty_attribs table. /// - public virtual IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() - { - yield return (ATTRIB_ID_MAX_COMBO, MaxCombo); - } + public IEnumerable<(int attributeId, object value)> ToDatabaseAttributes(); /// - /// Reads osu-web database attribute mappings into this object. + /// Reads osu-web database attribute mappings into this object. /// /// The attribute mappings. /// The where more information about the beatmap may be extracted from (such as AR/CS/OD/etc). - public virtual void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) - { - MaxCombo = (int)values[ATTRIB_ID_MAX_COMBO]; - } + public void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo); } } diff --git a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs b/osu.Game/Rulesets/Difficulty/IPerformanceAttributes.cs similarity index 100% rename from osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs rename to osu.Game/Rulesets/Difficulty/IPerformanceAttributes.cs diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index ee7f02f9be..b7ff4b9812 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -17,10 +17,10 @@ namespace osu.Game.Rulesets.Difficulty Ruleset = ruleset; } - public Task CalculateAsync(ScoreInfo score, DifficultyAttributes attributes, CancellationToken cancellationToken) + public Task CalculateAsync(ScoreInfo score, IDifficultyAttributes attributes, CancellationToken cancellationToken) => Task.Run(() => CreatePerformanceAttributes(score, attributes), cancellationToken); - public IPerformanceAttributes Calculate(ScoreInfo score, DifficultyAttributes attributes) + public IPerformanceAttributes Calculate(ScoreInfo score, IDifficultyAttributes attributes) => CreatePerformanceAttributes(score, attributes); public IPerformanceAttributes Calculate(ScoreInfo score, IWorkingBeatmap beatmap) @@ -31,6 +31,6 @@ namespace osu.Game.Rulesets.Difficulty /// /// The score to create the attributes for. /// The difficulty attributes for the beatmap relating to the score. - protected abstract IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes); + protected abstract IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, IDifficultyAttributes attributes); } } diff --git a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs index a07827d50b..b6a7aa26da 100644 --- a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs @@ -8,7 +8,7 @@ using System; namespace osu.Game.Rulesets.Difficulty { /// - /// Wraps a object and adds a time value for which the attribute is valid. + /// Wraps a object and adds a time value for which the attribute is valid. /// Output by DifficultyCalculator.CalculateTimed methods. /// public class TimedDifficultyAttributes : IComparable @@ -21,14 +21,14 @@ namespace osu.Game.Rulesets.Difficulty /// /// The attributes. /// - public readonly DifficultyAttributes Attributes; + public readonly IDifficultyAttributes Attributes; /// /// Creates new . /// /// The non-clock-adjusted time value at which the attributes take effect. /// The attributes. - public TimedDifficultyAttributes(double time, DifficultyAttributes attributes) + public TimedDifficultyAttributes(double time, IDifficultyAttributes attributes) { Time = time; Attributes = attributes; diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index 25c1387220..a48124fb68 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Play.HUD } [CanBeNull] - private DifficultyAttributes getAttributeAtTime(JudgementResult judgement) + private IDifficultyAttributes getAttributeAtTime(JudgementResult judgement) { if (timedAttributes == null || timedAttributes.Count == 0) return null;