From 996bc659e4ed9806edf9d1f433afc6c03ad7b621 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Dec 2023 14:29:51 +0900 Subject: [PATCH 1/8] Adjust some mod multipliers for initial leaderboard sanity --- osu.Game/Rulesets/Mods/ModClassic.cs | 2 +- osu.Game/Rulesets/Mods/ModSynesthesia.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModClassic.cs b/osu.Game/Rulesets/Mods/ModClassic.cs index 55b16297e2..42fdee0402 100644 --- a/osu.Game/Rulesets/Mods/ModClassic.cs +++ b/osu.Game/Rulesets/Mods/ModClassic.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods public override string Acronym => "CL"; - public override double ScoreMultiplier => 1; + public override double ScoreMultiplier => 0.5; public override IconUsage? Icon => FontAwesome.Solid.History; diff --git a/osu.Game/Rulesets/Mods/ModSynesthesia.cs b/osu.Game/Rulesets/Mods/ModSynesthesia.cs index 23cb135c50..9084127f33 100644 --- a/osu.Game/Rulesets/Mods/ModSynesthesia.cs +++ b/osu.Game/Rulesets/Mods/ModSynesthesia.cs @@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mods public override string Name => "Synesthesia"; public override string Acronym => "SY"; public override LocalisableString Description => "Colours hit objects based on the rhythm."; - public override double ScoreMultiplier => 1; + public override double ScoreMultiplier => 0.8; public override ModType Type => ModType.Fun; } } From 4983845041794eb5acff6037be4e163b50ae8418 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Dec 2023 15:51:26 +0900 Subject: [PATCH 2/8] Update HT mod multiplier to match stable better --- osu.Game/Rulesets/Mods/RateAdjustModHelper.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs b/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs index ffd4de0e90..8bc481921f 100644 --- a/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs +++ b/osu.Game/Rulesets/Mods/RateAdjustModHelper.cs @@ -32,9 +32,9 @@ namespace osu.Game.Rulesets.Mods value -= 1; if (SpeedChange.Value >= 1) - value /= 5; - - return 1 + value; + return 1 + value / 5; + else + return 0.6 + value; } } From 110749205d7366f05ca5d56dd2f037bc7770bff2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Dec 2023 16:13:08 +0900 Subject: [PATCH 3/8] Cache `GameplayClockContainer` to allow usage of `OnSeek` --- osu.Game/Screens/Play/GameplayClockContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 5a713fdae7..4def1d36bb 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -17,6 +17,7 @@ namespace osu.Game.Screens.Play /// Encapsulates gameplay timing logic and provides a via DI for gameplay components to use. /// [Cached(typeof(IGameplayClock))] + [Cached(typeof(GameplayClockContainer))] public partial class GameplayClockContainer : Container, IAdjustableClock, IGameplayClock { public IBindable IsPaused => isPaused; From f2c6c348be850bb07347bfb46a9c836c6304895f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Dec 2023 16:13:23 +0900 Subject: [PATCH 4/8] Fix `HitError` `Clear` methods not correctly returning pooled drawables --- .../Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 6 +++++- .../Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index eb5221aa45..a9141110c5 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -485,7 +485,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters } } - public override void Clear() => judgementsContainer.Clear(); + public override void Clear() + { + foreach (var j in judgementsContainer) + j.FadeOut().Expire(); + } public enum CentreMarkerStyles { diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index 5793713fca..d95959bf9e 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -63,7 +63,11 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters judgementsFlow.Push(GetColourForHitResult(judgement.Type)); } - public override void Clear() => judgementsFlow.Clear(); + public override void Clear() + { + foreach (var j in judgementsFlow) + j.FadeOut().Expire(); + } private partial class JudgementFlow : FillFlowContainer { From 3131d376218af0673a1b79190f52f7aaf576105e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Dec 2023 17:00:21 +0900 Subject: [PATCH 5/8] Clear transformations with more fire --- osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 5 ++++- .../Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index a9141110c5..443863fb2f 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -488,7 +488,10 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public override void Clear() { foreach (var j in judgementsContainer) - j.FadeOut().Expire(); + { + j.ClearTransforms(); + j.Expire(); + } } public enum CentreMarkerStyles diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs index d95959bf9e..65f4b50dde 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs @@ -66,7 +66,10 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters public override void Clear() { foreach (var j in judgementsFlow) - j.FadeOut().Expire(); + { + j.ClearTransforms(); + j.Expire(); + } } private partial class JudgementFlow : FillFlowContainer From e865de7a6b8cdbef85211b1d74571d1c8ac9b8b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 13 Dec 2023 09:25:56 +0100 Subject: [PATCH 6/8] Update test assertions in line with half time mod multiplier changes --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index f0822ce2a8..fed5f68449 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -787,7 +787,8 @@ namespace osu.Game.Tests.Visual.UserInterface InputManager.MoveMouseTo(this.ChildrenOfType().Single(preset => preset.Preset.Value.Name == "Half Time 0.5x")); InputManager.Click(MouseButton.Left); }); - AddAssert("difficulty multiplier display shows correct value", () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.5)); + AddAssert("difficulty multiplier display shows correct value", + () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.1).Within(Precision.DOUBLE_EPSILON)); // this is highly unorthodox in a test, but because the `ModSettingChangeTracker` machinery heavily leans on events and object disposal and re-creation, // it is instrumental in the reproduction of the failure scenario that this test is supposed to cover. @@ -796,7 +797,8 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("open customisation area", () => modSelectOverlay.CustomisationButton!.TriggerClick()); AddStep("reset half time speed to default", () => modSelectOverlay.ChildrenOfType().Single() .ChildrenOfType>().Single().TriggerClick()); - AddUntilStep("difficulty multiplier display shows correct value", () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.7)); + AddUntilStep("difficulty multiplier display shows correct value", + () => modSelectOverlay.ChildrenOfType().Single().Current.Value, () => Is.EqualTo(0.3).Within(Precision.DOUBLE_EPSILON)); } private void waitForColumnLoad() => AddUntilStep("all column content loaded", () => From 01710780525bca3126764bb77805964968ed19d6 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 13 Dec 2023 17:33:24 +0900 Subject: [PATCH 7/8] Move object counts to BeatmapInfo --- osu.Game.Tournament/Models/TournamentBeatmap.cs | 6 ++++++ osu.Game/BackgroundDataStoreProcessor.cs | 11 +++++++---- osu.Game/Beatmaps/BeatmapDifficulty.cs | 9 --------- osu.Game/Beatmaps/BeatmapImporter.cs | 6 +++--- osu.Game/Beatmaps/BeatmapInfo.cs | 4 ++++ osu.Game/Beatmaps/BeatmapUpdater.cs | 4 ++-- osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs | 13 ------------- osu.Game/Beatmaps/IBeatmapInfo.cs | 13 +++++++++++++ .../Online/API/Requests/Responses/APIBeatmap.cs | 8 +++++--- .../Legacy/LegacyBeatmapConversionDifficultyInfo.cs | 4 ++-- 10 files changed, 42 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tournament/Models/TournamentBeatmap.cs b/osu.Game.Tournament/Models/TournamentBeatmap.cs index 7f57b6a151..a7ba5b7db1 100644 --- a/osu.Game.Tournament/Models/TournamentBeatmap.cs +++ b/osu.Game.Tournament/Models/TournamentBeatmap.cs @@ -21,6 +21,10 @@ namespace osu.Game.Tournament.Models public double StarRating { get; set; } + public int EndTimeObjectCount { get; set; } + + public int TotalObjectCount { get; set; } + public IBeatmapMetadataInfo Metadata { get; set; } = new BeatmapMetadata(); public IBeatmapDifficultyInfo Difficulty { get; set; } = new BeatmapDifficulty(); @@ -41,6 +45,8 @@ namespace osu.Game.Tournament.Models Metadata = beatmap.Metadata; Difficulty = beatmap.Difficulty; Covers = beatmap.BeatmapSet?.Covers ?? new BeatmapSetOnlineCovers(); + EndTimeObjectCount = beatmap.EndTimeObjectCount; + TotalObjectCount = beatmap.TotalObjectCount; } public bool Equals(IBeatmapInfo? other) => other is TournamentBeatmap b && this.MatchesOnlineID(b); diff --git a/osu.Game/BackgroundDataStoreProcessor.cs b/osu.Game/BackgroundDataStoreProcessor.cs index c8a108a5f6..10cc13dc29 100644 --- a/osu.Game/BackgroundDataStoreProcessor.cs +++ b/osu.Game/BackgroundDataStoreProcessor.cs @@ -20,7 +20,6 @@ using osu.Game.Rulesets; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Screens.Play; -using Realms; namespace osu.Game { @@ -177,9 +176,13 @@ namespace osu.Game { Logger.Log("Querying for beatmaps with missing hitobject counts to reprocess..."); - HashSet beatmapIds = realmAccess.Run(r => new HashSet(r.All() - .Filter($"{nameof(BeatmapInfo.Difficulty)}.{nameof(BeatmapDifficulty.TotalObjectCount)} == 0") - .AsEnumerable().Select(b => b.ID))); + HashSet beatmapIds = new HashSet(); + + realmAccess.Run(r => + { + foreach (var b in r.All().Where(b => b.TotalObjectCount == 0)) + beatmapIds.Add(b.ID); + }); Logger.Log($"Found {beatmapIds.Count} beatmaps which require reprocessing."); diff --git a/osu.Game/Beatmaps/BeatmapDifficulty.cs b/osu.Game/Beatmaps/BeatmapDifficulty.cs index 785728141e..ac2267380d 100644 --- a/osu.Game/Beatmaps/BeatmapDifficulty.cs +++ b/osu.Game/Beatmaps/BeatmapDifficulty.cs @@ -21,9 +21,6 @@ namespace osu.Game.Beatmaps public double SliderMultiplier { get; set; } = 1.4; public double SliderTickRate { get; set; } = 1; - public int EndTimeObjectCount { get; set; } - public int TotalObjectCount { get; set; } - public BeatmapDifficulty() { } @@ -47,9 +44,6 @@ namespace osu.Game.Beatmaps difficulty.SliderMultiplier = SliderMultiplier; difficulty.SliderTickRate = SliderTickRate; - - difficulty.EndTimeObjectCount = EndTimeObjectCount; - difficulty.TotalObjectCount = TotalObjectCount; } public virtual void CopyFrom(IBeatmapDifficultyInfo other) @@ -61,9 +55,6 @@ namespace osu.Game.Beatmaps SliderMultiplier = other.SliderMultiplier; SliderTickRate = other.SliderTickRate; - - EndTimeObjectCount = other.EndTimeObjectCount; - TotalObjectCount = other.TotalObjectCount; } } } diff --git a/osu.Game/Beatmaps/BeatmapImporter.cs b/osu.Game/Beatmaps/BeatmapImporter.cs index 31d6b0108e..7bb52eef52 100644 --- a/osu.Game/Beatmaps/BeatmapImporter.cs +++ b/osu.Game/Beatmaps/BeatmapImporter.cs @@ -388,9 +388,7 @@ namespace osu.Game.Beatmaps OverallDifficulty = decodedDifficulty.OverallDifficulty, ApproachRate = decodedDifficulty.ApproachRate, SliderMultiplier = decodedDifficulty.SliderMultiplier, - SliderTickRate = decodedDifficulty.SliderTickRate, - EndTimeObjectCount = decoded.HitObjects.Count(h => h is IHasDuration), - TotalObjectCount = decoded.HitObjects.Count + SliderTickRate = decodedDifficulty.SliderTickRate }; var metadata = new BeatmapMetadata @@ -428,6 +426,8 @@ namespace osu.Game.Beatmaps GridSize = decodedInfo.GridSize, TimelineZoom = decodedInfo.TimelineZoom, MD5Hash = memoryStream.ComputeMD5Hash(), + EndTimeObjectCount = decoded.HitObjects.Count(h => h is IHasDuration), + TotalObjectCount = decoded.HitObjects.Count }; beatmaps.Add(beatmap); diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index c1aeec1f71..2d04732f91 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -120,6 +120,10 @@ namespace osu.Game.Beatmaps [JsonIgnore] public bool Hidden { get; set; } + public int EndTimeObjectCount { get; set; } + + public int TotalObjectCount { get; set; } + /// /// Reset any fetched online linking information (and history). /// diff --git a/osu.Game/Beatmaps/BeatmapUpdater.cs b/osu.Game/Beatmaps/BeatmapUpdater.cs index 472ac26ebe..27492b8bac 100644 --- a/osu.Game/Beatmaps/BeatmapUpdater.cs +++ b/osu.Game/Beatmaps/BeatmapUpdater.cs @@ -91,8 +91,8 @@ namespace osu.Game.Beatmaps var working = workingBeatmapCache.GetWorkingBeatmap(beatmapInfo); var beatmap = working.Beatmap; - beatmapInfo.Difficulty.EndTimeObjectCount = beatmap.HitObjects.Count(h => h is IHasDuration); - beatmapInfo.Difficulty.TotalObjectCount = beatmap.HitObjects.Count; + beatmapInfo.EndTimeObjectCount = beatmap.HitObjects.Count(h => h is IHasDuration); + beatmapInfo.TotalObjectCount = beatmap.HitObjects.Count; // And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required. workingBeatmapCache.Invalidate(beatmapInfo); diff --git a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs index 47b261d1f6..e7a3d87d0a 100644 --- a/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapDifficultyInfo.cs @@ -44,19 +44,6 @@ namespace osu.Game.Beatmaps /// double SliderTickRate { get; } - /// - /// The number of hitobjects in the beatmap with a distinct end time. - /// - /// - /// Canonically, these are hitobjects are either sliders or spinners. - /// - int EndTimeObjectCount { get; } - - /// - /// The total number of hitobjects in the beatmap. - /// - int TotalObjectCount { get; } - /// /// Maps a difficulty value [0, 10] to a two-piece linear range of values. /// diff --git a/osu.Game/Beatmaps/IBeatmapInfo.cs b/osu.Game/Beatmaps/IBeatmapInfo.cs index b8c69cc525..9dcff5ce5e 100644 --- a/osu.Game/Beatmaps/IBeatmapInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapInfo.cs @@ -61,5 +61,18 @@ namespace osu.Game.Beatmaps /// The basic star rating for this beatmap (with no mods applied). /// double StarRating { get; } + + /// + /// The number of hitobjects in the beatmap with a distinct end time. + /// + /// + /// Canonically, these are hitobjects are either sliders or spinners. + /// + int EndTimeObjectCount { get; } + + /// + /// The total number of hitobjects in the beatmap. + /// + int TotalObjectCount { get; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index c1ceff7c43..e5ecfe2c99 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -41,6 +41,10 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"difficulty_rating")] public double StarRating { get; set; } + public int EndTimeObjectCount => SliderCount + SpinnerCount; + + public int TotalObjectCount => CircleCount + SliderCount + SpinnerCount; + [JsonProperty(@"drain")] public float DrainRate { get; set; } @@ -108,9 +112,7 @@ namespace osu.Game.Online.API.Requests.Responses DrainRate = DrainRate, CircleSize = CircleSize, ApproachRate = ApproachRate, - OverallDifficulty = OverallDifficulty, - EndTimeObjectCount = SliderCount + SpinnerCount, - TotalObjectCount = CircleCount + SliderCount + SpinnerCount + OverallDifficulty = OverallDifficulty }; IBeatmapSetInfo? IBeatmapInfo.BeatmapSet => BeatmapSet; diff --git a/osu.Game/Rulesets/Scoring/Legacy/LegacyBeatmapConversionDifficultyInfo.cs b/osu.Game/Rulesets/Scoring/Legacy/LegacyBeatmapConversionDifficultyInfo.cs index 2021aa127d..7d69069455 100644 --- a/osu.Game/Rulesets/Scoring/Legacy/LegacyBeatmapConversionDifficultyInfo.cs +++ b/osu.Game/Rulesets/Scoring/Legacy/LegacyBeatmapConversionDifficultyInfo.cs @@ -62,8 +62,8 @@ namespace osu.Game.Rulesets.Scoring.Legacy SourceRuleset = beatmapInfo.Ruleset, CircleSize = beatmapInfo.Difficulty.CircleSize, OverallDifficulty = beatmapInfo.Difficulty.OverallDifficulty, - EndTimeObjectCount = beatmapInfo.Difficulty.EndTimeObjectCount, - TotalObjectCount = beatmapInfo.Difficulty.TotalObjectCount + EndTimeObjectCount = beatmapInfo.EndTimeObjectCount, + TotalObjectCount = beatmapInfo.TotalObjectCount }; } } From 812f52e793b4729548e1b452a063591fb28c546d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 13 Dec 2023 17:38:16 +0900 Subject: [PATCH 8/8] Bump version number --- osu.Game/Database/RealmAccess.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 9c7fe464dd..191bb49b0c 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -88,9 +88,9 @@ namespace osu.Game.Database /// 34 2023-08-21 Add BackgroundReprocessingFailed flag to ScoreInfo to track upgrade failures. /// 35 2023-10-16 Clear key combinations of keybindings that are assigned to more than one action in a given settings section. /// 36 2023-10-26 Add LegacyOnlineID to ScoreInfo. Move osu_scores_*_high IDs stored in OnlineID to LegacyOnlineID. Reset anomalous OnlineIDs. - /// 37 2023-12-10 Add EndTimeObjectCount and TotalObjectCount to BeatmapDifficulty. + /// 38 2023-12-10 Add EndTimeObjectCount and TotalObjectCount to BeatmapInfo. /// - private const int schema_version = 37; + private const int schema_version = 38; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods.