diff --git a/osu.Desktop/DiscordRichPresence.cs b/osu.Desktop/DiscordRichPresence.cs index 3642f70a56..d87b25a4c7 100644 --- a/osu.Desktop/DiscordRichPresence.cs +++ b/osu.Desktop/DiscordRichPresence.cs @@ -10,6 +10,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Game.Configuration; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; @@ -108,10 +109,7 @@ namespace osu.Desktop presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.GlobalRank > 0 ? $" (rank #{user.Value.Statistics.GlobalRank:N0})" : string.Empty); // update ruleset - int onlineID = ruleset.Value.OnlineID; - bool isLegacyRuleset = onlineID >= 0 && onlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID; - - presence.Assets.SmallImageKey = isLegacyRuleset ? $"mode_{onlineID}" : "mode_custom"; + presence.Assets.SmallImageKey = ruleset.Value.IsLegacyRuleset() ? $"mode_{ruleset.Value.OnlineID}" : "mode_custom"; presence.Assets.SmallImageText = ruleset.Value.Name; client.SetPresence(presence); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 31bd3a203c..1ed6648131 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -119,7 +119,8 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"Network failure", () => leaderboard.SetErrorState(LeaderboardState.NetworkFailure)); AddStep(@"No supporter", () => leaderboard.SetErrorState(LeaderboardState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetErrorState(LeaderboardState.NotLoggedIn)); - AddStep(@"Unavailable", () => leaderboard.SetErrorState(LeaderboardState.Unavailable)); + AddStep(@"Ruleset unavailable", () => leaderboard.SetErrorState(LeaderboardState.RulesetUnavailable)); + AddStep(@"Beatmap unavailable", () => leaderboard.SetErrorState(LeaderboardState.BeatmapUnavailable)); AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected)); } diff --git a/osu.Game/Beatmaps/DifficultyRecommender.cs b/osu.Game/Beatmaps/DifficultyRecommender.cs index 3949e84f4a..93c2fccbc7 100644 --- a/osu.Game/Beatmaps/DifficultyRecommender.cs +++ b/osu.Game/Beatmaps/DifficultyRecommender.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; @@ -83,7 +84,7 @@ namespace osu.Game.Beatmaps requestedUserId = api.LocalUser.Value.Id; // only query API for built-in rulesets - rulesets.AvailableRulesets.Where(ruleset => ruleset.OnlineID >= 0 && ruleset.OnlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID).ForEach(rulesetInfo => + rulesets.AvailableRulesets.Where(ruleset => ruleset.IsLegacyRuleset()).ForEach(rulesetInfo => { var req = new GetUserRequest(api.LocalUser.Value.Id, rulesetInfo); diff --git a/osu.Game/Extensions/ModelExtensions.cs b/osu.Game/Extensions/ModelExtensions.cs index f178a5c97b..13c25e45c8 100644 --- a/osu.Game/Extensions/ModelExtensions.cs +++ b/osu.Game/Extensions/ModelExtensions.cs @@ -72,6 +72,11 @@ namespace osu.Game.Extensions return result; } + /// + /// Check whether this 's online ID is within the range that defines it as a legacy ruleset (ie. either osu!, osu!taiko, osu!catch or osu!mania). + /// + public static bool IsLegacyRuleset(this IRulesetInfo ruleset) => ruleset.OnlineID >= 0 && ruleset.OnlineID <= ILegacyRuleset.MAX_LEGACY_RULESET_ID; + /// /// Check whether the online ID of two s match. /// diff --git a/osu.Game/Localisation/LeaderboardStrings.cs b/osu.Game/Localisation/LeaderboardStrings.cs new file mode 100644 index 0000000000..8e53f8e88c --- /dev/null +++ b/osu.Game/Localisation/LeaderboardStrings.cs @@ -0,0 +1,49 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class LeaderboardStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.Leaderboard"; + + /// + /// "Couldn't fetch scores!" + /// + public static LocalisableString CouldntFetchScores => new TranslatableString(getKey(@"couldnt_fetch_scores"), @"Couldn't fetch scores!"); + + /// + /// "Please select a beatmap!" + /// + public static LocalisableString PleaseSelectABeatmap => new TranslatableString(getKey(@"please_select_a_beatmap"), @"Please select a beatmap!"); + + /// + /// "Leaderboards are not available for this ruleset!" + /// + public static LocalisableString LeaderboardsAreNotAvailableForThisRuleset => new TranslatableString(getKey(@"leaderboards_are_not_available_for_this_ruleset"), @"Leaderboards are not available for this ruleset!"); + + /// + /// "Leaderboards are not available for this beatmap!" + /// + public static LocalisableString LeaderboardsAreNotAvailableForThisBeatmap => new TranslatableString(getKey(@"leaderboards_are_not_available_for_this_beatmap"), @"Leaderboards are not available for this beatmap!"); + + /// + /// "No records yet!" + /// + public static LocalisableString NoRecordsYet => new TranslatableString(getKey(@"no_records_yet"), @"No records yet!"); + + /// + /// "Please sign in to view online leaderboards!" + /// + public static LocalisableString PleaseSignInToViewOnlineLeaderboards => new TranslatableString(getKey(@"please_sign_in_to_view_online_leaderboards"), @"Please sign in to view online leaderboards!"); + + /// + /// "Please invest in an osu!supporter tag to view this leaderboard!" + /// + public static LocalisableString PleaseInvestInAnOsuSupporterTagToViewThisLeaderboard => new TranslatableString(getKey(@"please_invest_in_an_osu_supporter_tag_to_view_this_leaderboard"), @"Please invest in an osu!supporter tag to view this leaderboard!"); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 5dd3e46b4a..c94a6d3361 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -22,6 +22,7 @@ using osu.Game.Online.API; using osu.Game.Online.Placeholders; using osuTK; using osuTK.Graphics; +using osu.Game.Localisation; namespace osu.Game.Online.Leaderboards { @@ -311,25 +312,28 @@ namespace osu.Game.Online.Leaderboards switch (state) { case LeaderboardState.NetworkFailure: - return new ClickablePlaceholder(@"Couldn't fetch scores!", FontAwesome.Solid.Sync) + return new ClickablePlaceholder(LeaderboardStrings.CouldntFetchScores, FontAwesome.Solid.Sync) { Action = RefetchScores }; case LeaderboardState.NoneSelected: - return new MessagePlaceholder(@"Please select a beatmap!"); + return new MessagePlaceholder(LeaderboardStrings.PleaseSelectABeatmap); - case LeaderboardState.Unavailable: - return new MessagePlaceholder(@"Leaderboards are not available for this beatmap!"); + case LeaderboardState.RulesetUnavailable: + return new MessagePlaceholder(LeaderboardStrings.LeaderboardsAreNotAvailableForThisRuleset); + + case LeaderboardState.BeatmapUnavailable: + return new MessagePlaceholder(LeaderboardStrings.LeaderboardsAreNotAvailableForThisBeatmap); case LeaderboardState.NoScores: - return new MessagePlaceholder(@"No records yet!"); + return new MessagePlaceholder(LeaderboardStrings.NoRecordsYet); case LeaderboardState.NotLoggedIn: - return new LoginPlaceholder(@"Please sign in to view online leaderboards!"); + return new LoginPlaceholder(LeaderboardStrings.PleaseSignInToViewOnlineLeaderboards); case LeaderboardState.NotSupporter: - return new MessagePlaceholder(@"Please invest in an osu!supporter tag to view this leaderboard!"); + return new MessagePlaceholder(LeaderboardStrings.PleaseInvestInAnOsuSupporterTagToViewThisLeaderboard); case LeaderboardState.Retrieving: return null; diff --git a/osu.Game/Online/Leaderboards/LeaderboardState.cs b/osu.Game/Online/Leaderboards/LeaderboardState.cs index 75e2c6e6db..6b07500a98 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardState.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardState.cs @@ -8,7 +8,8 @@ namespace osu.Game.Online.Leaderboards Success, Retrieving, NetworkFailure, - Unavailable, + BeatmapUnavailable, + RulesetUnavailable, NoneSelected, NoScores, NotLoggedIn, diff --git a/osu.Game/Online/Placeholders/LoginPlaceholder.cs b/osu.Game/Online/Placeholders/LoginPlaceholder.cs index f8a326a52e..d03b3d8ffc 100644 --- a/osu.Game/Online/Placeholders/LoginPlaceholder.cs +++ b/osu.Game/Online/Placeholders/LoginPlaceholder.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Overlays; namespace osu.Game.Online.Placeholders @@ -12,7 +13,7 @@ namespace osu.Game.Online.Placeholders [Resolved(CanBeNull = true)] private LoginOverlay login { get; set; } - public LoginPlaceholder(string actionMessage) + public LoginPlaceholder(LocalisableString actionMessage) : base(actionMessage, FontAwesome.Solid.UserLock) { Action = () => login?.Show(); diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 1326395695..f0ead05280 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -7,9 +7,9 @@ using System.Linq; using System.Text; using osu.Framework.Extensions; using osu.Game.Beatmaps; +using osu.Game.Extensions; using osu.Game.IO.Legacy; using osu.Game.Replays.Legacy; -using osu.Game.Rulesets; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; using SharpCompress.Compressors.LZMA; @@ -48,7 +48,7 @@ namespace osu.Game.Scoring.Legacy if (beatmap == null && !score.Replay.Frames.All(f => f is LegacyReplayFrame)) throw new ArgumentException(@"Beatmap must be provided if frames are not already legacy frames.", nameof(beatmap)); - if (score.ScoreInfo.Ruleset.OnlineID < 0 || score.ScoreInfo.Ruleset.OnlineID > ILegacyRuleset.MAX_LEGACY_RULESET_ID) + if (!score.ScoreInfo.Ruleset.IsLegacyRuleset()) throw new ArgumentException(@"Only scores in the osu, taiko, catch, or mania rulesets can be encoded to the legacy score format.", nameof(score)); } diff --git a/osu.Game/Screens/Play/SoloPlayer.cs b/osu.Game/Screens/Play/SoloPlayer.cs index 824c0072e3..a935ce49eb 100644 --- a/osu.Game/Screens/Play/SoloPlayer.cs +++ b/osu.Game/Screens/Play/SoloPlayer.cs @@ -4,10 +4,10 @@ using System; using System.Diagnostics; using osu.Game.Beatmaps; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; -using osu.Game.Rulesets; using osu.Game.Scoring; namespace osu.Game.Screens.Play @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Play if (beatmapId <= 0) return null; - if (rulesetId < 0 || rulesetId > ILegacyRuleset.MAX_LEGACY_RULESET_ID) + if (!Ruleset.Value.IsLegacyRuleset()) return null; return new CreateSoloScoreRequest(beatmapId, rulesetId, Game.VersionHash); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 907a2c9bda..eb0addd377 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -11,6 +11,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Extensions; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Online.Leaderboards; @@ -98,6 +99,7 @@ namespace osu.Game.Screens.Select.Leaderboards protected override APIRequest FetchScores(CancellationToken cancellationToken) { var fetchBeatmapInfo = BeatmapInfo; + var fetchRuleset = ruleset.Value ?? fetchBeatmapInfo.Ruleset; if (fetchBeatmapInfo == null) { @@ -117,9 +119,15 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } + if (!fetchRuleset.IsLegacyRuleset()) + { + SetErrorState(LeaderboardState.RulesetUnavailable); + return null; + } + if (fetchBeatmapInfo.OnlineID <= 0 || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending) { - SetErrorState(LeaderboardState.Unavailable); + SetErrorState(LeaderboardState.BeatmapUnavailable); return null; } @@ -137,7 +145,7 @@ namespace osu.Game.Screens.Select.Leaderboards else if (filterMods) requestMods = mods.Value; - var req = new GetScoresRequest(fetchBeatmapInfo, ruleset.Value ?? fetchBeatmapInfo.Ruleset, Scope, requestMods); + var req = new GetScoresRequest(fetchBeatmapInfo, fetchRuleset, Scope, requestMods); req.Success += r => {