From eb6f1ae72cda9baa2dc4b903724932a511163743 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 09:16:28 +0900 Subject: [PATCH 1/9] Fix spinners providing one extra combo --- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 2 -- .../Legacy/Catch/ConvertHitObjectParser.cs | 22 ++++++++++++++++--- .../Legacy/Osu/ConvertHitObjectParser.cs | 22 ++++++++++++++++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index e1a7a7c6df..1c60fd4831 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -20,8 +20,6 @@ namespace osu.Game.Rulesets.Osu.Objects /// public int SpinsRequired { get; protected set; } = 1; - public override bool NewCombo => true; - protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index fb4cde479b..cb44fb1c8c 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -18,8 +18,17 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch { } + private bool forceNewCombo; + private int extraComboOffset; + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertHit { X = position.X, @@ -30,6 +39,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertSlider { X = position.X, @@ -45,11 +60,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + forceNewCombo |= FormatVersion <= 8 || newCombo; + extraComboOffset += comboOffset; + return new ConvertSpinner { - EndTime = endTime, - NewCombo = FirstObject || newCombo, - ComboOffset = comboOffset + EndTime = endTime }; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 0823653830..497d85f849 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -19,8 +19,17 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu { } + private bool forceNewCombo; + private int extraComboOffset; + protected override HitObject CreateHit(Vector2 position, bool newCombo, int comboOffset) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertHit { Position = position, @@ -31,6 +40,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples) { + newCombo |= forceNewCombo; + comboOffset += extraComboOffset; + + forceNewCombo = false; + extraComboOffset = 0; + return new ConvertSlider { Position = position, @@ -46,12 +61,13 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + forceNewCombo |= FormatVersion <= 8 || newCombo; + extraComboOffset += comboOffset; + return new ConvertSpinner { Position = position, - EndTime = endTime, - NewCombo = FormatVersion <= 8 || FirstObject || newCombo, - ComboOffset = comboOffset + EndTime = endTime }; } From 557a2ee39d42937b5f0501ae147a86da66e45dc3 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 10:04:00 +0900 Subject: [PATCH 2/9] Add more comprehensive tests --- .../Beatmaps/OsuBeatmapConverter.cs | 2 +- .../Beatmaps/OsuBeatmapProcessor.cs | 2 +- .../Formats/LegacyBeatmapDecoderTest.cs | 38 ++++++++++++++++++- .../Resources/hitobject-combo-offset.osu | 30 ++++++++++++++- 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs index 93f3f06dc2..9e0e649eb2 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapConverter.cs @@ -12,7 +12,7 @@ using osu.Game.Rulesets.Osu.UI; namespace osu.Game.Rulesets.Osu.Beatmaps { - internal class OsuBeatmapConverter : BeatmapConverter + public class OsuBeatmapConverter : BeatmapConverter { public OsuBeatmapConverter(IBeatmap beatmap) : base(beatmap) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index bbe2d67baa..5fe2457645 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -8,7 +8,7 @@ using osu.Game.Rulesets.Osu.Objects; namespace osu.Game.Rulesets.Osu.Beatmaps { - internal class OsuBeatmapProcessor : BeatmapProcessor + public class OsuBeatmapProcessor : BeatmapProcessor { public OsuBeatmapProcessor(IBeatmap beatmap) : base(beatmap) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 0a5df0e093..d3351f86f8 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -11,7 +11,9 @@ using osu.Game.Audio; using osu.Game.Rulesets.Objects.Types; using osu.Game.Beatmaps.Formats; using osu.Game.Beatmaps.Timing; +using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Skinning; namespace osu.Game.Tests.Beatmaps.Formats @@ -187,14 +189,46 @@ namespace osu.Game.Tests.Beatmaps.Formats } [Test] - public void TestDecodeBeatmapComboOffsets() + public void TestDecodeBeatmapComboOffsetsOsu() { var decoder = new LegacyBeatmapDecoder(); using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) using (var stream = new StreamReader(resStream)) { var beatmap = decoder.Decode(stream); - Assert.AreEqual(3, ((IHasCombo)beatmap.HitObjects[0]).ComboOffset); + + var converted = new OsuBeatmapConverter(beatmap).Convert(); + new OsuBeatmapProcessor(converted).PreProcess(); + new OsuBeatmapProcessor(converted).PostProcess(); + + Assert.AreEqual(4, ((IHasComboInformation)converted.HitObjects.ElementAt(0)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(2)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(4)).ComboIndex); + Assert.AreEqual(6, ((IHasComboInformation)converted.HitObjects.ElementAt(6)).ComboIndex); + Assert.AreEqual(11, ((IHasComboInformation)converted.HitObjects.ElementAt(8)).ComboIndex); + Assert.AreEqual(14, ((IHasComboInformation)converted.HitObjects.ElementAt(11)).ComboIndex); + } + } + + [Test] + public void TestDecodeBeatmapComboOffsetsCatch() + { + var decoder = new LegacyBeatmapDecoder(); + using (var resStream = Resource.OpenResource("hitobject-combo-offset.osu")) + using (var stream = new StreamReader(resStream)) + { + var beatmap = decoder.Decode(stream); + + var converted = new CatchBeatmapConverter(beatmap).Convert(); + new CatchBeatmapProcessor(converted).PreProcess(); + new CatchBeatmapProcessor(converted).PostProcess(); + + Assert.AreEqual(4, ((IHasComboInformation)converted.HitObjects.ElementAt(0)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(2)).ComboIndex); + Assert.AreEqual(5, ((IHasComboInformation)converted.HitObjects.ElementAt(4)).ComboIndex); + Assert.AreEqual(6, ((IHasComboInformation)converted.HitObjects.ElementAt(6)).ComboIndex); + Assert.AreEqual(11, ((IHasComboInformation)converted.HitObjects.ElementAt(8)).ComboIndex); + Assert.AreEqual(14, ((IHasComboInformation)converted.HitObjects.ElementAt(11)).ComboIndex); } } diff --git a/osu.Game.Tests/Resources/hitobject-combo-offset.osu b/osu.Game.Tests/Resources/hitobject-combo-offset.osu index 4a44d31e22..c1f0dab8e9 100644 --- a/osu.Game.Tests/Resources/hitobject-combo-offset.osu +++ b/osu.Game.Tests/Resources/hitobject-combo-offset.osu @@ -1,4 +1,32 @@ osu file format v14 [HitObjects] -255,193,2170,49,0,0:0:0:0: \ No newline at end of file +// Circle with combo offset (3) +255,193,1000,49,0,0:0:0:0: +// Combo index = 4 + +// Slider with new combo followed by circle with no new combo +256,192,2000,12,0,2000,0:0:0:0: +255,193,3000,1,0,0:0:0:0: +// Combo index = 5 + +// Slider without new combo followed by circle with no new combo +256,192,4000,8,0,5000,0:0:0:0: +255,193,6000,1,0,0:0:0:0: +// Combo index = 5 + +// Slider without new combo followed by circle with new combo +256,192,7000,8,0,8000,0:0:0:0: +255,193,9000,5,0,0:0:0:0: +// Combo index = 6 + +// Slider with new combo and offset (1) followed by circle with new combo and offset (3) +256,192,10000,28,0,11000,0:0:0:0: +255,193,12000,53,0,0:0:0:0: +// Combo index = 11 + +// Slider with new combo and offset (2) followed by slider with no new combo followed by circle with no new combo +256,192,13000,44,0,14000,0:0:0:0: +256,192,15000,8,0,16000,0:0:0:0: +255,193,17000,1,0,0:0:0:0: +// Combo index = 14 \ No newline at end of file From 83dc01d07c9d61523e294d1affa9763c448b96b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 12:03:31 +0900 Subject: [PATCH 3/9] Fix multiple sentry reports arriving for similar exceptions --- osu.Desktop/Program.cs | 4 +++- osu.Game/Utils/RavenLogger.cs | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index 19ceade644..db77427f96 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -62,9 +62,11 @@ namespace osu.Desktop { bool continueExecution = Interlocked.Decrement(ref allowableExceptions) >= 0; - Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed" : "denied")} with {allowableExceptions} more allowable exceptions."); + Logger.Log($"Unhandled exception has been {(continueExecution ? "allowed with {allowableExceptions} more allowable exceptions" : "denied")} ."); + // restore the stock of allowable exceptions after a short delay. Task.Delay(1000).ContinueWith(_ => Interlocked.Increment(ref allowableExceptions)); + return continueExecution; } } diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 761bd51672..70080fefa8 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -19,18 +19,30 @@ namespace osu.Game.Utils private readonly List tasks = new List(); + private Exception lastException; + public RavenLogger(OsuGame game) { raven.Release = game.Version; - if (!game.IsDeployedBuild) return; - Logger.NewEntry += entry => { if (entry.Level < LogLevel.Verbose) return; - if (entry.Exception != null) - queuePendingTask(raven.CaptureAsync(new SentryEvent(entry.Exception))); + var exception = entry.Exception; + + if (exception != null) + { + // since we let unhandled exceptions go ignored at times, we want to ensure they don't get submitted on subsequent reports. + if (lastException != null && + lastException.Message == exception.Message && exception.StackTrace.StartsWith(lastException.StackTrace)) + { + return; + } + + lastException = exception; + queuePendingTask(raven.CaptureAsync(new SentryEvent(exception))); + } else raven.AddTrail(new Breadcrumb(entry.Target.ToString(), BreadcrumbType.Navigation) { Message = entry.Message }); }; From 0ae487b9c9a478afff2e083a07475a2da44932c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 12:27:36 +0900 Subject: [PATCH 4/9] Add back missing statement --- osu.Game/Utils/RavenLogger.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Utils/RavenLogger.cs b/osu.Game/Utils/RavenLogger.cs index 70080fefa8..b28dd1fb73 100644 --- a/osu.Game/Utils/RavenLogger.cs +++ b/osu.Game/Utils/RavenLogger.cs @@ -25,6 +25,8 @@ namespace osu.Game.Utils { raven.Release = game.Version; + if (!game.IsDeployedBuild) return; + Logger.NewEntry += entry => { if (entry.Level < LogLevel.Verbose) return; From 7a8aabc402acc6ca16b8d7dafa2419be4354623d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 13:18:48 +0900 Subject: [PATCH 5/9] Fix notifications suggesting automatic reporting in non-deployed builds --- osu.Game/OsuGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ecf5500ca4..d54bdee1b2 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -463,7 +463,7 @@ namespace osu.Game Schedule(() => notifications.Post(new SimpleNotification { Icon = entry.Level == LogLevel.Important ? FontAwesome.fa_exclamation_circle : FontAwesome.fa_bomb, - Text = entry.Message + (entry.Exception != null ? "\n\nThis error has been automatically reported to the devs." : string.Empty), + Text = entry.Message + (entry.Exception != null && IsDeployedBuild ? "\n\nThis error has been automatically reported to the devs." : string.Empty), })); } else if (recentLogCount == short_term_display_limit) From 3d6721111a8159a0a6ad9bebb9ded491cd952cb8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 13:26:53 +0900 Subject: [PATCH 6/9] Increase the maximum allowable iterations during mania conversion --- osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs index 1eb0cdae2f..e51cbcdc60 100644 --- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs +++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/PatternGenerator.cs @@ -18,8 +18,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns /// /// An arbitrary maximum amount of iterations to perform in . /// The specific value is not super important - enough such that no false-positives occur. + /// + /// /b/933228 requires at least 23 iterations. /// - private const int max_rng_iterations = 20; + private const int max_rng_iterations = 30; /// /// The last pattern. From 583e026906c46b5861bf30a3626dadc840fb5c13 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Aug 2018 13:28:35 +0900 Subject: [PATCH 7/9] =?UTF-8?q?Don=E2=80=99t=20suppress=20unhandled=20exce?= =?UTF-8?q?ptions=20in=20debug=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- osu.Desktop/Program.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs index db77427f96..71613753bc 100644 --- a/osu.Desktop/Program.cs +++ b/osu.Desktop/Program.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using osu.Framework; +using osu.Framework.Development; using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.IPC; @@ -51,7 +52,7 @@ namespace osu.Desktop } } - private static int allowableExceptions = 1; + private static int allowableExceptions = DebugUtils.IsDebugBuild ? 0 : 1; /// /// Allow a maximum of one unhandled exception, per second of execution. From 16d30f6756d78cf9f38ac3e293c870e5b8653b0f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 13:31:12 +0900 Subject: [PATCH 8/9] Add explanatory comments --- .../Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs | 2 ++ osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index cb44fb1c8c..802080aedb 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -60,6 +60,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + // Convert spinners don't create the new combo themselves, but force the next non-spinner hitobject to create a new combo + // Their combo offset is still added to that next hitobject's combo index forceNewCombo |= FormatVersion <= 8 || newCombo; extraComboOffset += comboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index 497d85f849..acd0de8688 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -61,6 +61,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu protected override HitObject CreateSpinner(Vector2 position, bool newCombo, int comboOffset, double endTime) { + // Convert spinners don't create the new combo themselves, but force the next non-spinner hitobject to create a new combo + // Their combo offset is still added to that next hitobject's combo index forceNewCombo |= FormatVersion <= 8 || newCombo; extraComboOffset += comboOffset; From 83bda313d1dc092332a71e4320d6285480fe5404 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 Aug 2018 13:50:27 +0900 Subject: [PATCH 9/9] Output the currently importing model --- osu.Game/Database/ArchiveModelManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index c00df59e3e..ac79a8f565 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -198,6 +198,8 @@ namespace osu.Game.Database try { + Logger.Log($"Importing {item}...", LoggingTarget.Database); + using (var write = ContextFactory.GetForWrite()) // used to share a context for full import. keep in mind this will block all writes. { try