-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3b34f39
commit 95040d3
Showing
11 changed files
with
301 additions
and
335 deletions.
There are no files selected for viewing
84 changes: 84 additions & 0 deletions
84
Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchShowSliderComboBreaks.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
using HarmonyLib; | ||
using Osu.Patcher.Hook.Patches.Relax; | ||
|
||
namespace Osu.Patcher.Hook.Patches.ShowComboBreaks; | ||
|
||
/// <summary> | ||
/// Changes the following code in <c>osu.GameplayElements.HitObjectManager:vmethod_17(HitObject)</c> | ||
/// to enable showing combo breaks on sliders using the data obtained through | ||
/// <see cref="PatchTrackComboBreakingSliders" />. | ||
/// <br /><br /> | ||
/// From: | ||
/// <code><![CDATA[ | ||
/// if (increaseScoreType < (IncreaseScoreType)0) { | ||
/// text2 = "hit0"; // string obfuscated | ||
/// } else { | ||
/// ... | ||
/// } | ||
/// ]]></code> | ||
/// To: | ||
/// <code><![CDATA[ | ||
/// if (PatchDrawSliderComboBreaks.IsObjectSliderComboBreaking(hitObject_arg1)) | ||
/// goto jmp_true: | ||
/// if (increaseScoreType < (IncreaseScoreType)0) { | ||
/// jmp_true: | ||
/// text2 = "hit0"; // string obfuscated | ||
/// } else { | ||
/// ... | ||
/// } | ||
/// ]]></code> | ||
/// </summary> | ||
// [HarmonyPatch] | ||
internal class PatchDrawSliderComboBreaks : BasePatch | ||
{ | ||
[HarmonyTargetMethod] | ||
private static MethodBase Target() => | ||
AllowRelaxDrawMisses.Target(); | ||
|
||
[HarmonyTranspiler] | ||
private static IEnumerable<CodeInstruction> Transpile( | ||
IEnumerable<CodeInstruction> instructions, | ||
ILGenerator generator) | ||
{ | ||
// Right before the "increaseScoreType < 0" | ||
var targetSignature = new[] | ||
{ | ||
OpCodes.Ldc_I4_2, | ||
OpCodes.Bgt_Un_S, | ||
OpCodes.Ldc_I4, | ||
OpCodes.Stloc_0, | ||
OpCodes.Call, | ||
OpCodes.Pop, | ||
}; | ||
|
||
var elseJmpLabel = generator.DefineLabel(); | ||
|
||
var postInsertInstructions = InsertAfterSignature( | ||
instructions, | ||
targetSignature, | ||
new[] | ||
{ | ||
// Load the first argument onto the stack (Argument 0 is `this`) | ||
new CodeInstruction(OpCodes.Ldarg_1), | ||
|
||
// Call the method below to check w/ top of stack, result pushed to stack | ||
CodeInstruction.Call(typeof(ShowComboBreaksUtil), | ||
nameof(ShowComboBreaksUtil.IsHitObjectComboBreakingSlider)), | ||
|
||
// Jmp to the if "true" block if result true | ||
new CodeInstruction(OpCodes.Brtrue_S, elseJmpLabel), | ||
} | ||
); | ||
|
||
// Find first inst of the if "true" block | ||
// TODO: find this properly | ||
postInsertInstructions.FirstOrDefault(i => i.opcode == OpCodes.Ldc_I4 && (int)i.operand == -0xFC85EE6) | ||
?.labels.Add(elseJmpLabel); | ||
|
||
return postInsertInstructions; | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using System; | ||
using System.Reflection; | ||
using HarmonyLib; | ||
using Osu.Patcher.Hook.Patches.Relax; | ||
using Osu.Stubs; | ||
using Osu.Stubs.Wrappers; | ||
|
||
// ReSharper disable UnusedType.Global UnusedMember.Local InconsistentNaming | ||
|
||
namespace Osu.Patcher.Hook.Patches.ShowComboBreaks; | ||
|
||
// [HarmonyPatch] | ||
internal class PatchTrackComboBreakingSliders : BasePatch | ||
{ | ||
[HarmonyTargetMethod] | ||
private static MethodBase Target() => | ||
AllowRelaxComboBreakSound.Target(); | ||
|
||
// Ruleset->CurrentScore->CurrentCombo | ||
private static ushort GetCombo() | ||
{ | ||
// Ruleset#CurrentScore | ||
var fCurrentScore = AccessTools.Field("#=znsd474wIu4GAJ8swgEdrqaxwLN4O:#=zW5K7ouTMxMrX"); | ||
// Score#CurrentCombo | ||
var fCurrentCombo = AccessTools.Field("#=zLBw8hg3V1k_gTYcAwmBw_YkrvWaEQzfUz_i_IrU=:#=zE49fcJU="); | ||
|
||
return (ushort)fCurrentCombo.GetValue(fCurrentScore.GetValue(null)); | ||
} | ||
|
||
[HarmonyPrefix] | ||
private static void Before( | ||
[HarmonyArgument(0)] int increaseScoreType, | ||
[HarmonyArgument(1)] object hitObject) | ||
{ | ||
// Check if slider & some sort of missed combo except for slider ends | ||
if (increaseScoreType < 0 && SliderOsu.RuntimeType.IsInstanceOfType(hitObject)) | ||
{ | ||
Console.WriteLine($"IncreaseScoreHit pre: {increaseScoreType} {hitObject}"); | ||
// Console.WriteLine($"pre combo: {GetCombo()}"); | ||
// ShowComboBreaksUtil.ComboBreakSliders[hitObject.GetHashCode()] = true; | ||
|
||
Notifications.ShowMessage("slider combo break", NotificationColor.Warning, 200); | ||
} | ||
} | ||
|
||
// [HarmonyPostfix] | ||
// private static void After( | ||
// [HarmonyArgument(0)] int increaseScoreType, | ||
// [HarmonyArgument(1)] object hitObject) | ||
// { | ||
// // Check if slider & some sort of missed combo except for slider ends | ||
// if (increaseScoreType < 0 && SliderOsu.Class.IsInstanceOfType(hitObject)) | ||
// { | ||
// Console.WriteLine($"post combo: {GetCombo()}"); | ||
// ShowComboBreaksUtil.ComboBreakSliders[hitObject.GetHashCode()] = true; | ||
// } | ||
// } | ||
|
||
[HarmonyFinalizer] | ||
private static Exception Finalizer(Exception __exception) | ||
{ | ||
if (__exception != null) | ||
{ | ||
Console.WriteLine("Exception while running patch " + | ||
$"{nameof(PatchTrackComboBreakingSliders)}: {__exception}"); | ||
} | ||
|
||
return null; | ||
Check warning on line 68 in Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs GitHub Actions / build
Check warning on line 68 in Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs GitHub Actions / build
Check warning on line 68 in Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs GitHub Actions / build
|
||
} | ||
} | ||
|
||
// [HarmonyPatch] | ||
// internal class PatchTrackComboBreakingSliders | ||
// { | ||
// [HarmonyTargetMethod] | ||
// private static MethodBase Target() | ||
// { | ||
// // osu.GameModes.Play.Rulesets.Ruleset:OnIncreaseScoreHit(IncreaseScoreType, double hpIncrease, bool increaseCombo, HitObject) | ||
// return AccessTools.DeclaredMethod("#=z04fOmc1I_BS0TV6TAo2QOUQvjceryuOcqoleWPg=:#=zBqtfszH0Yf2Z"); | ||
// } | ||
// | ||
// [HarmonyPostfix] | ||
// private static void After( | ||
// [HarmonyArgument(0)] object increaseScoreType, | ||
// [HarmonyArgument(1)] double hpIncrease, | ||
// [HarmonyArgument(2)] bool increaseCombo, | ||
// [HarmonyArgument(3)] object hitObject) | ||
// { | ||
// Console.WriteLine($"OnIncreaseScoreHit: {increaseCombo} {hpIncrease} {increaseScoreType} {hitObject}"); | ||
// // Check if slider & some sort of missed combo except for slider ends | ||
// if ((int)increaseScoreType < 0 && ShowComboBreaksUtil.TSliderOsu.IsInstanceOfType(hitObject)) | ||
// // Console.WriteLine($"OnIncreaseScoreHit: {increaseScoreType} {hitObject}"); | ||
// ShowComboBreaksUtil.ComboBreakSliders[hitObject.GetHashCode()] = true; | ||
// } | ||
// } |
20 changes: 20 additions & 0 deletions
20
Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackScoreClear.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System.Reflection; | ||
using HarmonyLib; | ||
using Osu.Stubs; | ||
|
||
// ReSharper disable UnusedType.Global UnusedMember.Local | ||
|
||
namespace Osu.Patcher.Hook.Patches.ShowComboBreaks; | ||
|
||
/// <summary> | ||
/// Clear our stored slider hit judgement results when the score is reset. | ||
/// </summary> | ||
[HarmonyPatch] | ||
internal class PatchTrackScoreClear : BasePatch | ||
{ | ||
[HarmonyTargetMethod] | ||
private static MethodBase Target() => Ruleset.ResetScore.Reference; | ||
|
||
[HarmonyPostfix] | ||
private static void After() => ShowComboBreaksUtil.Reset(); | ||
} |
65 changes: 65 additions & 0 deletions
65
Osu.Patcher.Hook/Patches/ShowComboBreaks/ShowComboBreaksUtil.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using HarmonyLib; | ||
using Osu.Stubs; | ||
|
||
namespace Osu.Patcher.Hook.Patches.ShowComboBreaks; | ||
|
||
internal static class ShowComboBreaksUtil | ||
{ | ||
// Stored by SliderOsu#GetHashCode() -> "isComboBroken" | ||
internal static readonly Dictionary<int, bool> ComboBreakSliders = new Dictionary<int, bool>(); | ||
|
||
// osu.GameplayElements.HitObjects.Osu.SliderOsu#sliderTicksHitStatus | ||
private static readonly FieldInfo FSliderOsu_sliderTicksHitStatus; | ||
|
||
// osu.GameplayElements.HitObjects.Osu.SliderOsu#sliderStartCircle | ||
private static readonly FieldInfo FSliderOsu_sliderStartCircle; | ||
|
||
// osu.GameplayElements.HitObjects.HitObject#IsHit | ||
private static readonly FieldInfo FHitObject_IsHit; | ||
|
||
static ShowComboBreaksUtil() | ||
{ | ||
FSliderOsu_sliderTicksHitStatus = SliderOsu.RuntimeType.GetRuntimeFields() | ||
.Single(f => f.FieldType.IsArray && f.FieldType.GetElementType() == typeof(bool)); | ||
|
||
FSliderOsu_sliderStartCircle = | ||
AccessTools.Field("#=zoa4eC6Sw5rwIwh2Hbi$3M6X$Z6nv8UnYgxNpICPLicAP:#=z39rOeuDVskYOgRwpx3zjK74="); | ||
|
||
FHitObject_IsHit = AccessTools.Field("#=zqwKEmiGIDb0qpLnR3aavM7g3al9jl960OQ==:#=zIDw7YQY="); | ||
|
||
// HitCicleOsu = #=zOFC2jmTKji24ougWFWDM$GEqjzktzU4gcKFF$gYj32T9m7QUzQ== | ||
} | ||
|
||
public static void Reset() | ||
{ | ||
Console.WriteLine("clearing"); | ||
ComboBreakSliders.Clear(); | ||
} | ||
|
||
/// <summary> | ||
/// Used by <see cref="PatchDrawSliderComboBreaks" /> in order to inject a call to this | ||
/// to check whether a HitObject is an std slider that has caused broken combo. | ||
/// </summary> | ||
/// <param name="hitObject"></param> | ||
/// <returns></returns> | ||
public static bool IsHitObjectComboBreakingSlider(object hitObject) | ||
{ | ||
if (SliderOsu.RuntimeType.IsInstanceOfType(hitObject)) | ||
{ | ||
var sliderTicks = (bool[])FSliderOsu_sliderTicksHitStatus.GetValue(hitObject); | ||
var startCircle = FSliderOsu_sliderStartCircle.GetValue(hitObject); | ||
var isStartCircleHit = FHitObject_IsHit.GetValue(startCircle); | ||
|
||
Console.WriteLine( | ||
$"sliderTicksHitStatus: {sliderTicks.Join()}; isStartCircleHit: {isStartCircleHit}"); | ||
} | ||
|
||
return SliderOsu.RuntimeType.IsInstanceOfType(hitObject) | ||
&& ComboBreakSliders.TryGetValue(hitObject.GetHashCode(), out var isBreaking) | ||
&& isBreaking; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System; | ||
using JetBrains.Annotations; | ||
using Osu.Utils.Lazy; | ||
using static System.Reflection.Emit.OpCodes; | ||
|
||
namespace Osu.Stubs; | ||
|
||
/// <summary> | ||
/// Original: <c>osu.GameplayElements.HitObjects.Osu.SliderOsu</c> | ||
/// b20240102.2: <c>#=zG_Fe30_qUmxpC_TyMiG8b0o7fXW0pNx67n$z1myOL9vw</c> | ||
/// </summary> | ||
[UsedImplicitly] | ||
public static class SliderOsu | ||
{ | ||
/// <summary> | ||
/// The only constructor on this class | ||
/// </summary> | ||
private static readonly LazyMethod Constructor = new( | ||
"SliderOsu#SliderOsu", | ||
new[] | ||
{ | ||
Ldc_I4_5, | ||
Ldc_I4_5, | ||
Ldc_I4_5, | ||
Newobj, | ||
Ldnull, | ||
Newobj, | ||
Stfld, | ||
Ldarg_0, | ||
Ldnull, | ||
}, | ||
true | ||
); | ||
|
||
[UsedImplicitly] | ||
public static Type RuntimeType => Constructor.Reference.DeclaringType!; | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.