diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/PatchUpdatePerformanceCalculator.cs b/Osu.Patcher.Hook/Patches/LivePerformance/PatchTrackOnScoreHit.cs similarity index 58% rename from Osu.Patcher.Hook/Patches/LivePerformance/PatchUpdatePerformanceCalculator.cs rename to Osu.Patcher.Hook/Patches/LivePerformance/PatchTrackOnScoreHit.cs index 0b2dccf..587e180 100644 --- a/Osu.Patcher.Hook/Patches/LivePerformance/PatchUpdatePerformanceCalculator.cs +++ b/Osu.Patcher.Hook/Patches/LivePerformance/PatchTrackOnScoreHit.cs @@ -1,8 +1,6 @@ using System; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; -using System.Threading; using HarmonyLib; using JetBrains.Annotations; using Osu.Performance; @@ -10,38 +8,14 @@ namespace Osu.Patcher.Hook.Patches.LivePerformance; +/// +/// Hooks Ruleset::OnIncreaseScoreHit(...) to send score updates to our performance calculator +/// so it can recalculate based on new HitObject judgements. +/// [HarmonyPatch] [UsedImplicitly] -public static class PatchUpdatePerformanceCalculator +public static class PatchTrackOnScoreHit { - private static OsuPerformance? _performance; - - internal static void ResetCalculator() => new Thread(() => - { - Debug.WriteLine("Resetting performance calculator"); - - _performance?.Dispose(); - _performance = null; - - var currentScore = Player.CurrentScore.Get(); - if (currentScore == null) return; - - var modsObfuscated = Score.EnabledMods.Get(currentScore); - var mods = Score.EnabledModsGetValue.Invoke(modsObfuscated); - - // Clear relax mod for now (live pp calculations for relax are fucking garbage) - mods &= ~(1 << 7); - - var beatmap = Score.Beatmap.Get(currentScore); - if (beatmap == null) return; - - var beatmapPath = Beatmap.GetBeatmapPath(beatmap); - if (beatmapPath == null) return; - - _performance = new OsuPerformance(beatmapPath, (uint)mods); - _performance.OnNewCalculation += Console.WriteLine; - }).Start(); - [UsedImplicitly] [HarmonyTargetMethod] private static MethodBase Target() => Ruleset.OnIncreaseScoreHit.Reference; @@ -54,7 +28,12 @@ private static void After( [HarmonyArgument(0)] int increaseScoreType, [HarmonyArgument(2)] bool increaseCombo) { - if (_performance == null) return; + Console.WriteLine(increaseScoreType); + if (!PerformanceCalculator.IsInitialized) + { + Console.WriteLine("OnIncreaseScoreHit called before performance calculator initialized!"); + return; + } var judgement = (increaseScoreType & ~IncreaseScoreType.OsuComboModifiers) switch { @@ -74,7 +53,7 @@ private static void After( var CurrentScore = Ruleset.CurrentScore.Get(__instance); var MaxCombo = Score.MaxCombo.Get(CurrentScore); - _performance.AddJudgement(judgement, (uint)MaxCombo); + PerformanceCalculator.Calculator?.AddJudgement(judgement, (uint)MaxCombo); } [UsedImplicitly] @@ -84,7 +63,7 @@ private static void Finalizer(Exception? __exception) { if (__exception != null) { - Console.WriteLine($"Exception due to {nameof(PatchUpdatePerformanceCalculator)}: {__exception}"); + Console.WriteLine($"Exception due to {nameof(PatchTrackOnScoreHit)}: {__exception}"); } } } \ No newline at end of file diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/PatchClearPerformanceCalculator.cs b/Osu.Patcher.Hook/Patches/LivePerformance/PatchTrackResetScore.cs similarity index 65% rename from Osu.Patcher.Hook/Patches/LivePerformance/PatchClearPerformanceCalculator.cs rename to Osu.Patcher.Hook/Patches/LivePerformance/PatchTrackResetScore.cs index 30c5e8a..e30e2a9 100644 --- a/Osu.Patcher.Hook/Patches/LivePerformance/PatchClearPerformanceCalculator.cs +++ b/Osu.Patcher.Hook/Patches/LivePerformance/PatchTrackResetScore.cs @@ -7,9 +7,12 @@ namespace Osu.Patcher.Hook.Patches.LivePerformance; +/// +/// Hooks Ruleset::ResetScore() to also reset our performance calculator. +/// [HarmonyPatch] [UsedImplicitly] -internal class PatchClearPerformanceCalculator +internal class PatchTrackResetScore { [UsedImplicitly] [HarmonyTargetMethod] @@ -17,7 +20,7 @@ internal class PatchClearPerformanceCalculator [UsedImplicitly] [HarmonyPostfix] - private static void After() => PatchUpdatePerformanceCalculator.ResetCalculator(); + private static void After() => PerformanceCalculator.ResetCalculator(); [UsedImplicitly] [HarmonyFinalizer] @@ -26,7 +29,7 @@ private static void Finalizer(Exception? __exception) { if (__exception != null) { - Console.WriteLine($"Exception due to {nameof(PatchClearPerformanceCalculator)}: {__exception}"); + Console.WriteLine($"Exception due to {nameof(PatchTrackResetScore)}: {__exception}"); } } } \ No newline at end of file diff --git a/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs b/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs new file mode 100644 index 0000000..e2abaa2 --- /dev/null +++ b/Osu.Patcher.Hook/Patches/LivePerformance/PerformanceCalculator.cs @@ -0,0 +1,61 @@ +using System; +using System.Diagnostics; +using Osu.Performance; +using Osu.Stubs; + +namespace Osu.Patcher.Hook.Patches.LivePerformance; + +/// +/// Handles initializing and disposing the performance calculator based on current score and settings. +/// +internal static class PerformanceCalculator +{ + public static OsuPerformance? Calculator { get; private set; } + + public static bool IsInitialized => Calculator != null; + + /// + /// Disposes the existing performance calculator, and initializes a new one according to the current score info. + /// This must be called after Ruleset::ResetScore() + /// + public static void ResetCalculator() + { + try + { + ResetCalculatorSync(); + } + catch (Exception e) + { + Console.WriteLine($"Failed to reset performance calculator: {e}"); + } + } + + private static void ResetCalculatorSync() + { + Debug.WriteLine("Resetting performance calculator"); + + // TODO: don't dispose it if the beatmap is the same, reuse parsed beatmap in native side + Calculator?.Dispose(); + Calculator = null; + + var currentScore = Player.CurrentScore.Get(); + if (currentScore == null) return; + + var modsObfuscated = Score.EnabledMods.Get(currentScore); + var mods = Score.EnabledModsGetValue.Invoke(modsObfuscated); + + // Clear relax mod for now (live pp calculations for relax are fucking garbage) + mods &= ~(1 << 7); + + var beatmap = Score.Beatmap.Get(currentScore); + if (beatmap == null) return; + + var beatmapPath = Beatmap.GetBeatmapPath(beatmap); + if (beatmapPath == null) return; + + Calculator = new OsuPerformance(beatmapPath, (uint)mods); + Calculator.OnNewCalculation += Console.WriteLine; + + Debug.WriteLine("Initialized performance calculator!"); + } +} \ No newline at end of file