Skip to content
This repository was archived by the owner on Nov 20, 2021. It is now read-only.

Commit

Permalink
codematchers
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeroluna committed Aug 1, 2021
1 parent 3b23834 commit 2d38edd
Show file tree
Hide file tree
Showing 19 changed files with 257 additions and 569 deletions.
39 changes: 12 additions & 27 deletions NoodleExtensions/HarmonyPatches/BeatmapDataTransformHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,18 @@ internal static class BeatmapDataTransformHelperCreateTransformedBeatmapData

private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> instructionList = instructions.ToList();
bool foundBeatmapData = false;
for (int i = 0; i < instructionList.Count; i++)
{
if (!foundBeatmapData &&
instructionList[i].opcode == OpCodes.Callvirt &&
((MethodInfo)instructionList[i].operand).Name == "GetCopy")
{
foundBeatmapData = true;

// yoink label5 so we can insert our code w/o breaking shit
CodeInstruction sourceLabel = instructionList[i - 4];
CodeInstruction newLabel = new CodeInstruction(instructionList[i - 4]);
sourceLabel.labels.Clear();

instructionList.Insert(i - 4, newLabel);
instructionList.Insert(i - 3, new CodeInstruction(OpCodes.Call, _reorderLineData));
instructionList.Insert(i - 2, new CodeInstruction(OpCodes.Stloc_0));
}
}

if (!foundBeatmapData)
{
Logger.Log("Failed to find GetCopy!", IPA.Logging.Logger.Level.Error);
}

return instructionList.AsEnumerable();
return new CodeMatcher(instructions)
.MatchForward(
false,
new CodeMatch(OpCodes.Ldloc_0),
new CodeMatch(OpCodes.Ldarg_0),
new CodeMatch(OpCodes.Bne_Un))
.Advance(1)
.InsertAndAdvance(
new CodeInstruction(OpCodes.Call, _reorderLineData),
new CodeInstruction(OpCodes.Stloc_0),
new CodeInstruction(OpCodes.Ldloc_0)) // Replace the opcode we replace
.InstructionEnumeration();
}

private static IReadonlyBeatmapData ReorderLineData(IReadonlyBeatmapData beatmapData)
Expand Down
34 changes: 11 additions & 23 deletions NoodleExtensions/HarmonyPatches/BeatmapObjectCallBackController.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace NoodleExtensions.HarmonyPatches
{
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using CustomJSONData.CustomBeatmap;
Expand All @@ -13,33 +12,22 @@
[HeckPatch("LateUpdate")]
internal static class BeatmapObjectCallBackControllerLateUpdate
{
private static readonly FieldInfo _aheadTimeField = AccessTools.Field(typeof(BeatmapObjectCallbackData), nameof(BeatmapObjectCallbackData.aheadTime));

private static readonly MethodInfo _getAheadTime = AccessTools.Method(typeof(BeatmapObjectCallBackControllerLateUpdate), nameof(GetAheadTime));
private static readonly MethodInfo _beatmapObjectSpawnControllerCallback = AccessTools.Method(typeof(BeatmapObjectSpawnController), nameof(BeatmapObjectSpawnController.HandleBeatmapObjectCallback));

private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> instructionList = instructions.ToList();
bool foundAheadTime = false;
for (int i = 0; i < instructionList.Count; i++)
{
if (!foundAheadTime &&
instructionList[i].opcode == OpCodes.Ldfld &&
((FieldInfo)instructionList[i].operand).Name == "aheadTime")
{
foundAheadTime = true;

instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, _getAheadTime));
instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldloc_3));
instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldloc_1));
}
}

if (!foundAheadTime)
{
Plugin.Logger.Log("Failed to find aheadTime ldfld!", IPA.Logging.Logger.Level.Error);
}

return instructionList.AsEnumerable();
return new CodeMatcher(instructions)
.MatchForward(false, new CodeMatch(OpCodes.Ldfld, _aheadTimeField))
.Advance(-1)
.InsertAndAdvance(
new CodeInstruction(OpCodes.Ldloc_1),
new CodeInstruction(OpCodes.Ldloc_3))
.Advance(2)
.Insert(new CodeInstruction(OpCodes.Call, _getAheadTime))
.InstructionEnumeration();
}

private static float GetAheadTime(BeatmapObjectCallbackData beatmapObjectCallbackData, BeatmapObjectData beatmapObjectData, float @default)
Expand Down
7 changes: 1 addition & 6 deletions NoodleExtensions/HarmonyPatches/Cutout/BaseNoteVisual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,7 @@ private static MethodInfo GetSetArrowTransparency(Type type)
Type baseType = type.BaseType;
////NoodleLogger.IPAlogger.Debug($"Base type is {baseType.Name}<{string.Join(", ", baseType.GenericTypeArguments.Select(t => t.Name))}>");
MethodInfo method = baseType.GetMethod("SetArrowTransparency", BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
{
throw new InvalidOperationException($"Type [{type.FullName}] does not contain method [SetArrowTransparency]");
}

_setArrowTransparencyMethods[type] = method;
_setArrowTransparencyMethods[type] = method ?? throw new InvalidOperationException($"Type [{type.FullName}] does not contain method [SetArrowTransparency]");
return method;
}
}
Expand Down
80 changes: 16 additions & 64 deletions NoodleExtensions/HarmonyPatches/FakeNotes/BeatmapData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ private static void Postfix()
[HarmonyPatch("AddBeatmapObjectData")]
internal static class BeatmapDataAddBeatmapObjectData
{
private static readonly List<object> _countGetters = new List<object>
{
AccessTools.PropertyGetter(typeof(BeatmapData), nameof(BeatmapData.obstaclesCount)),
AccessTools.PropertyGetter(typeof(BeatmapData), nameof(BeatmapData.cuttableNotesType)),
AccessTools.PropertyGetter(typeof(BeatmapData), nameof(BeatmapData.bombsCount)),
};

private static readonly MethodInfo _fakeObjectCheck = AccessTools.Method(typeof(BeatmapDataAddBeatmapObjectData), nameof(FakeObjectCheck));
private static bool _noodleRequirement;

Expand All @@ -48,71 +55,16 @@ private static void Prefix(BeatmapData __instance)

private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> instructionList = instructions.ToList();

void ModifyInstructions(int i)
{
instructionList.RemoveRange(i + 1, 5);

CodeInstruction[] codeInstructions = new CodeInstruction[]
{
return new CodeMatcher(instructions)
.MatchForward(false, new CodeMatch(OpCodes.Call) { operands = _countGetters })
.Repeat(n => n
.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0))
.Advance(1)
.InsertAndAdvance(
new CodeInstruction(OpCodes.Ldarg_1),
new CodeInstruction(OpCodes.Call, _fakeObjectCheck),
};
instructionList.InsertRange(i + 1, codeInstructions);

instructionList.Insert(i, new CodeInstruction(OpCodes.Ldarg_0));
}

bool foundObstacles = false;
bool foundNotes = false;
bool foundBombs = false;
for (int i = 0; i < instructionList.Count; i++)
{
if (!foundObstacles &&
instructionList[i].opcode == OpCodes.Call &&
((MethodInfo)instructionList[i].operand).Name == "get_obstaclesCount")
{
foundObstacles = true;

ModifyInstructions(i);
}

if (!foundNotes &&
instructionList[i].opcode == OpCodes.Call &&
((MethodInfo)instructionList[i].operand).Name == "get_cuttableNotesType")
{
foundNotes = true;

ModifyInstructions(i);
}

if (!foundBombs &&
instructionList[i].opcode == OpCodes.Call &&
((MethodInfo)instructionList[i].operand).Name == "get_bombsCount")
{
foundBombs = true;

ModifyInstructions(i);
}
}

if (!foundObstacles)
{
Plugin.Logger.Log("Failed to find call to get_obstaclesCount!", IPA.Logging.Logger.Level.Error);
}

if (!foundNotes)
{
Plugin.Logger.Log("Failed to find call to get_cuttableNotesType!", IPA.Logging.Logger.Level.Error);
}

if (!foundBombs)
{
Plugin.Logger.Log("Failed to find call to get_bombsCount!", IPA.Logging.Logger.Level.Error);
}

return instructionList.AsEnumerable();
new CodeInstruction(OpCodes.Call, _fakeObjectCheck))
.RemoveInstructions(5))
.InstructionEnumeration();
}

private static int FakeObjectCheck(int objectCount, BeatmapObjectData beatmapObjectData)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
namespace NoodleExtensions.HarmonyPatches
{
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using Heck;

Expand All @@ -13,26 +10,7 @@ internal static class BeatmapObjectExecutionRatingsRecorderUpdate
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> instructionList = instructions.ToList();
bool foundIntersectingObstacles = false;
for (int i = 0; i < instructionList.Count; i++)
{
if (!foundIntersectingObstacles &&
instructionList[i].opcode == OpCodes.Callvirt &&
((MethodInfo)instructionList[i].operand).Name == "get_intersectingObstacles")
{
foundIntersectingObstacles = true;

instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, FakeNoteHelper._obstacleFakeCheck));
}
}

if (!foundIntersectingObstacles)
{
Plugin.Logger.Log("Failed to find callvirt to get_intersectingObstacles!", IPA.Logging.Logger.Level.Error);
}

return instructionList.AsEnumerable();
return FakeNoteHelper.ObstaclesTranspiler(instructions);
}
}
}
14 changes: 13 additions & 1 deletion NoodleExtensions/HarmonyPatches/FakeNotes/FakeNoteHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using UnityEngine;
using static NoodleExtensions.NoodleObjectDataManager;

internal static class FakeNoteHelper
{
internal static readonly MethodInfo _boundsNullCheck = AccessTools.Method(typeof(FakeNoteHelper), nameof(BoundsNullCheck));
internal static readonly MethodInfo _obstacleFakeCheck = AccessTools.Method(typeof(FakeNoteHelper), nameof(ObstacleFakeCheck));

private static readonly MethodInfo _intersectingObstaclesGetter = AccessTools.PropertyGetter(typeof(PlayerHeadAndObstacleInteraction), nameof(PlayerHeadAndObstacleInteraction.intersectingObstacles));
private static readonly MethodInfo _obstacleFakeCheck = AccessTools.Method(typeof(FakeNoteHelper), nameof(ObstacleFakeCheck));

internal static bool GetFakeNote(NoteController noteController)
{
Expand Down Expand Up @@ -42,6 +45,15 @@ internal static bool GetCuttable(NoteData noteData)
return true;
}

internal static IEnumerable<CodeInstruction> ObstaclesTranspiler(IEnumerable<CodeInstruction> instructions)
{
return new CodeMatcher(instructions)
.MatchForward(false, new CodeMatch(OpCodes.Callvirt, _intersectingObstaclesGetter))
.Advance(1)
.Insert(new CodeInstruction(OpCodes.Call, _obstacleFakeCheck))
.InstructionEnumeration();
}

private static bool BoundsNullCheck(ObstacleController obstacleController)
{
return obstacleController.bounds.size == Vector3.zero;
Expand Down
24 changes: 1 addition & 23 deletions NoodleExtensions/HarmonyPatches/FakeNotes/GameEnergyCounter.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
namespace NoodleExtensions.HarmonyPatches
{
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
using Heck;

Expand All @@ -13,26 +10,7 @@ internal static class GameEnergyCounterUpdate
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> instructionList = instructions.ToList();
bool foundIntersectingObstacles = false;
for (int i = 0; i < instructionList.Count; i++)
{
if (!foundIntersectingObstacles &&
instructionList[i].opcode == OpCodes.Callvirt &&
((MethodInfo)instructionList[i].operand).Name == "get_intersectingObstacles")
{
foundIntersectingObstacles = true;

instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Call, FakeNoteHelper._obstacleFakeCheck));
}
}

if (!foundIntersectingObstacles)
{
Plugin.Logger.Log("Failed to find callvirt to get_intersectingObstacles!", IPA.Logging.Logger.Level.Error);
}

return instructionList.AsEnumerable();
return FakeNoteHelper.ObstaclesTranspiler(instructions);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
namespace NoodleExtensions.HarmonyPatches
{
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using HarmonyLib;
Expand All @@ -11,46 +10,23 @@
[HeckPatch("Update")]
internal static class ObstacleSaberSparkleEffectManagerUpdate
{
private static readonly MethodInfo _currentGetter = AccessTools.PropertyGetter(typeof(List<ObstacleController>.Enumerator), nameof(List<ObstacleController>.Enumerator.Current));

private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> instructionList = instructions.ToList();
bool foundLabel = false;
bool foundBounds = false;
Label? label = null;
for (int i = 0; i < instructionList.Count; i++)
{
if (!foundLabel &&
instructionList[i].opcode == OpCodes.Br)
{
foundLabel = true;

label = (Label)instructionList[i].operand;
}

if (!foundBounds &&
label.HasValue &&
instructionList[i].opcode == OpCodes.Callvirt &&
((MethodInfo)instructionList[i].operand).Name == "get_bounds")
{
foundBounds = true;

instructionList.Insert(i - 1, new CodeInstruction(OpCodes.Ldloc_1));
instructionList.Insert(i, new CodeInstruction(OpCodes.Call, FakeNoteHelper._boundsNullCheck));
instructionList.Insert(i + 1, new CodeInstruction(OpCodes.Brtrue_S, label.Value));
}
}

if (!foundLabel)
{
Plugin.Logger.Log("Failed to find br to IL_0136!", IPA.Logging.Logger.Level.Error);
}
CodeMatcher codeMatcher = new CodeMatcher(instructions)
.MatchForward(false, new CodeMatch(OpCodes.Br));

if (!foundBounds)
{
Plugin.Logger.Log("Failed to find callvirt to get_bounds!", IPA.Logging.Logger.Level.Error);
}
object label = codeMatcher.Operand;

return instructionList.AsEnumerable();
return codeMatcher
.MatchForward(false, new CodeMatch(OpCodes.Call, _currentGetter))
.Advance(2)
.Insert(
new CodeInstruction(OpCodes.Ldloc_1),
new CodeInstruction(OpCodes.Call, FakeNoteHelper._boundsNullCheck),
new CodeInstruction(OpCodes.Brtrue_S, label))
.InstructionEnumeration();
}
}
}
Loading

0 comments on commit 2d38edd

Please sign in to comment.