Skip to content

Commit

Permalink
fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
rushiiMachine committed Mar 28, 2024
1 parent 3b34f39 commit 95040d3
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 335 deletions.
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;
}
}
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

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 68 in Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 68 in Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.

Check warning on line 68 in Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackComboBreakingSliders.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference return.
}
}

// [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 Osu.Patcher.Hook/Patches/ShowComboBreaks/PatchTrackScoreClear.cs
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 Osu.Patcher.Hook/Patches/ShowComboBreaks/ShowComboBreaksUtil.cs
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;
}
}
37 changes: 37 additions & 0 deletions Osu.Stubs/SliderOsu.cs
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!;
}
32 changes: 0 additions & 32 deletions OsuHook/Osu/Stubs/Ruleset.cs

This file was deleted.

35 changes: 0 additions & 35 deletions OsuHook/Osu/Stubs/SliderOsu.cs

This file was deleted.

Loading

0 comments on commit 95040d3

Please sign in to comment.