diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs index 66f15670f5..7a38d213d9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapCarousel.cs @@ -15,6 +15,7 @@ using osu.Framework.Utils; using osu.Game.Beatmaps; using osu.Game.Configuration; using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Carousel; using osu.Game.Screens.Select.Filter; @@ -684,6 +685,7 @@ namespace osu.Game.Tests.Visual.SongSelect set.Beatmaps.Add(new BeatmapInfo { Version = $"Stars: {i}", + Ruleset = new OsuRuleset().RulesetInfo, StarDifficulty = i, }); } @@ -868,6 +870,7 @@ namespace osu.Game.Tests.Visual.SongSelect OnlineBeatmapID = id++ * 10, Version = version, StarDifficulty = diff, + Ruleset = new OsuRuleset().RulesetInfo, BaseDifficulty = new BeatmapDifficulty { OverallDifficulty = diff, diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 880d70aec2..64412675bb 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -37,10 +37,10 @@ namespace osu.Game.Beatmaps.Drawables } [NotNull] - private readonly BeatmapInfo beatmapInfo; + private readonly IBeatmapInfo beatmapInfo; [CanBeNull] - private readonly RulesetInfo ruleset; + private readonly IRulesetInfo ruleset; [CanBeNull] private readonly IReadOnlyList mods; @@ -60,7 +60,7 @@ namespace osu.Game.Beatmaps.Drawables /// The ruleset to show the difficulty with. /// The mods to show the difficulty with. /// Whether to display a tooltip when hovered. - public DifficultyIcon([NotNull] BeatmapInfo beatmapInfo, [CanBeNull] RulesetInfo ruleset, [CanBeNull] IReadOnlyList mods, bool shouldShowTooltip = true) + public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo ruleset, [CanBeNull] IReadOnlyList mods, bool shouldShowTooltip = true) : this(beatmapInfo, shouldShowTooltip) { this.ruleset = ruleset ?? beatmapInfo.Ruleset; @@ -73,7 +73,7 @@ namespace osu.Game.Beatmaps.Drawables /// The beatmap to show the difficulty of. /// Whether to display a tooltip when hovered. /// Whether to perform difficulty lookup (including calculation if necessary). - public DifficultyIcon([NotNull] BeatmapInfo beatmapInfo, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true) + public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true) { this.beatmapInfo = beatmapInfo ?? throw new ArgumentNullException(nameof(beatmapInfo)); this.shouldShowTooltip = shouldShowTooltip; @@ -84,6 +84,9 @@ namespace osu.Game.Beatmaps.Drawables InternalChild = iconContainer = new Container { Size = new Vector2(20f) }; } + [Resolved] + private RulesetStore rulesets { get; set; } + [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -105,7 +108,7 @@ namespace osu.Game.Beatmaps.Drawables Child = background = new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.ForStarDifficulty(beatmapInfo.StarDifficulty) // Default value that will be re-populated once difficulty calculation completes + Colour = colours.ForStarDifficulty(beatmapInfo.StarRating) // Default value that will be re-populated once difficulty calculation completes }, }, new ConstrainedIconContainer @@ -114,18 +117,28 @@ namespace osu.Game.Beatmaps.Drawables Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, // the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment) - Icon = (ruleset ?? beatmapInfo.Ruleset)?.CreateInstance()?.CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle } + Icon = getRulesetIcon() }, }; if (performBackgroundDifficultyLookup) iconContainer.Add(new DelayedLoadUnloadWrapper(() => new DifficultyRetriever(beatmapInfo, ruleset, mods) { StarDifficulty = { BindTarget = difficultyBindable } }, 0)); else - difficultyBindable.Value = new StarDifficulty(beatmapInfo.StarDifficulty, 0); + difficultyBindable.Value = new StarDifficulty(beatmapInfo.StarRating, 0); difficultyBindable.BindValueChanged(difficulty => background.Colour = colours.ForStarDifficulty(difficulty.NewValue.Stars)); } + private Drawable getRulesetIcon() + { + int? onlineID = (ruleset ?? beatmapInfo.Ruleset).OnlineID; + + if (onlineID >= 0 && rulesets.GetRuleset(onlineID.Value)?.CreateInstance() is Ruleset rulesetInstance) + return rulesetInstance.CreateIcon(); + + return new SpriteIcon { Icon = FontAwesome.Regular.QuestionCircle }; + } + ITooltip IHasCustomTooltip.GetCustomTooltip() => new DifficultyIconTooltip(); DifficultyIconTooltipContent IHasCustomTooltip.TooltipContent => shouldShowTooltip ? new DifficultyIconTooltipContent(beatmapInfo, difficultyBindable) : null; @@ -134,8 +147,8 @@ namespace osu.Game.Beatmaps.Drawables { public readonly Bindable StarDifficulty = new Bindable(); - private readonly BeatmapInfo beatmapInfo; - private readonly RulesetInfo ruleset; + private readonly IBeatmapInfo beatmapInfo; + private readonly IRulesetInfo ruleset; private readonly IReadOnlyList mods; private CancellationTokenSource difficultyCancellation; @@ -143,7 +156,7 @@ namespace osu.Game.Beatmaps.Drawables [Resolved] private BeatmapDifficultyCache difficultyCache { get; set; } - public DifficultyRetriever(BeatmapInfo beatmapInfo, RulesetInfo ruleset, IReadOnlyList mods) + public DifficultyRetriever(IBeatmapInfo beatmapInfo, IRulesetInfo ruleset, IReadOnlyList mods) { this.beatmapInfo = beatmapInfo; this.ruleset = ruleset; diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs index d4c9f83a0a..ec4bcbd65f 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIconTooltip.cs @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps.Drawables public void SetContent(DifficultyIconTooltipContent content) { - difficultyName.Text = content.BeatmapInfo.Version; + difficultyName.Text = content.BeatmapInfo.DifficultyName; starDifficulty.UnbindAll(); starDifficulty.BindTo(content.Difficulty); @@ -109,10 +109,10 @@ namespace osu.Game.Beatmaps.Drawables internal class DifficultyIconTooltipContent { - public readonly BeatmapInfo BeatmapInfo; + public readonly IBeatmapInfo BeatmapInfo; public readonly IBindable Difficulty; - public DifficultyIconTooltipContent(BeatmapInfo beatmapInfo, IBindable difficulty) + public DifficultyIconTooltipContent(IBeatmapInfo beatmapInfo, IBindable difficulty) { BeatmapInfo = beatmapInfo; Difficulty = difficulty; diff --git a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs index fcee4c2f1a..799a02579e 100644 --- a/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/GroupedDifficultyIcon.cs @@ -19,8 +19,8 @@ namespace osu.Game.Beatmaps.Drawables /// public class GroupedDifficultyIcon : DifficultyIcon { - public GroupedDifficultyIcon(List beatmaps, RulesetInfo ruleset, Color4 counterColour) - : base(beatmaps.OrderBy(b => b.StarDifficulty).Last(), ruleset, null, false) + public GroupedDifficultyIcon(IEnumerable beatmaps, IRulesetInfo ruleset, Color4 counterColour) + : base(beatmaps.OrderBy(b => b.StarRating).Last(), ruleset, null, false) { AddInternal(new OsuSpriteText { @@ -29,7 +29,7 @@ namespace osu.Game.Beatmaps.Drawables Padding = new MarginPadding { Left = Size.X }, Margin = new MarginPadding { Left = 2, Right = 5 }, Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), - Text = beatmaps.Count.ToString(), + Text = beatmaps.Count().ToString(), Colour = counterColour, }); } diff --git a/osu.Game/Beatmaps/IBeatmapInfo.cs b/osu.Game/Beatmaps/IBeatmapInfo.cs index 3d51c5d4b6..d206cfaaed 100644 --- a/osu.Game/Beatmaps/IBeatmapInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapInfo.cs @@ -11,7 +11,7 @@ namespace osu.Game.Beatmaps /// /// A single beatmap difficulty. /// - public interface IBeatmapInfo : IHasOnlineID + public interface IBeatmapInfo : IHasOnlineID { /// /// The user-specified name given to this beatmap. diff --git a/osu.Game/Beatmaps/IBeatmapSetInfo.cs b/osu.Game/Beatmaps/IBeatmapSetInfo.cs index 0cfb0c4242..20c46d9063 100644 --- a/osu.Game/Beatmaps/IBeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapSetInfo.cs @@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps /// /// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive. /// - public interface IBeatmapSetInfo : IHasOnlineID + public interface IBeatmapSetInfo : IHasOnlineID { /// /// The date when this beatmap was imported. diff --git a/osu.Game/Database/IHasOnlineID.cs b/osu.Game/Database/IHasOnlineID.cs index 6e2be7e1f9..36ae4035c4 100644 --- a/osu.Game/Database/IHasOnlineID.cs +++ b/osu.Game/Database/IHasOnlineID.cs @@ -5,7 +5,7 @@ namespace osu.Game.Database { - public interface IHasOnlineID + public interface IHasOnlineID { /// /// The server-side ID representing this instance, if one exists. Any value 0 or less denotes a missing ID. @@ -14,6 +14,6 @@ namespace osu.Game.Database /// Generally we use -1 when specifying "missing" in code, but values of 0 are also considered missing as the online source /// is generally a MySQL autoincrement value, which can never be 0. /// - int OnlineID { get; } + T OnlineID { get; } } } diff --git a/osu.Game/Rulesets/IRulesetInfo.cs b/osu.Game/Rulesets/IRulesetInfo.cs index 779433dc81..c3bc6c1995 100644 --- a/osu.Game/Rulesets/IRulesetInfo.cs +++ b/osu.Game/Rulesets/IRulesetInfo.cs @@ -11,7 +11,7 @@ namespace osu.Game.Rulesets /// /// A representation of a ruleset's metadata. /// - public interface IRulesetInfo : IHasOnlineID + public interface IRulesetInfo : IHasOnlineID { /// /// The user-exposed name of this ruleset. diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 5cf22f7945..ed3b27dd22 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -19,7 +19,7 @@ using osu.Game.Utils; namespace osu.Game.Scoring { - public class ScoreInfo : IHasFiles, IHasPrimaryKey, ISoftDelete, IEquatable, IDeepCloneable + public class ScoreInfo : IHasFiles, IHasPrimaryKey, ISoftDelete, IEquatable, IDeepCloneable, IHasOnlineID { public int ID { get; set; } @@ -271,5 +271,11 @@ namespace osu.Game.Scoring return ReferenceEquals(this, other); } + + #region Implementation of IHasOnlineID + + public long OnlineID => OnlineScoreID ?? -1; + + #endregion } }