-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathHarmony.cs
153 lines (127 loc) · 4.6 KB
/
Harmony.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using Harmony;
using MU3.Battle;
using NekoClient.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace UnityParrot
{
public enum PatchType
{
Prefix,
Postfix,
Transpiler
};
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MethodPatchAttribute : Attribute
{
public Type TargetType;
public string TargetMethod;
public PatchType PatchType;
public MethodPatchAttribute(PatchType patchType, Type targetType, string targetMethod)
{
PatchType = patchType;
TargetType = targetType;
TargetMethod = targetMethod;
}
}
public static class Harmony
{
private static readonly HarmonyInstance ms_harmony;
public static HarmonyInstance Instance
=> ms_harmony;
public static HarmonyMethod GetPatch(string name, Type type, BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic)
=> new HarmonyMethod(type.GetMethod(name, flags)
?? type.GetProperties().FirstOrDefault((PropertyInfo p) => p.GetGetMethod().Name == name)?.GetGetMethod());
public static void PatchAllInType(Type targetType)
{
var methods = targetType.GetMethods((BindingFlags)62);
foreach (var m in methods)
{
var attrs = m.GetCustomAttributes(typeof(MethodPatchAttribute), true);
if (attrs.Length > 0)
{
foreach (var attr in attrs)
{
MethodPatchAttribute a = (MethodPatchAttribute)attr;
HarmonyMethod harmonyMethod = GetPatch(m.Name, targetType);
PerformPatch($"{targetType.Name} # {a.TargetMethod} ({m.Name})",
a.TargetType.GetMethod(a.TargetMethod, (BindingFlags)62),
a.PatchType == PatchType.Prefix ? harmonyMethod : null,
a.PatchType == PatchType.Postfix ? harmonyMethod : null,
a.PatchType == PatchType.Transpiler ? harmonyMethod : null);
}
}
}
}
public static void PerformPatch(string patchName, MethodBase original, HarmonyMethod prefix = null, HarmonyMethod postfix = null, HarmonyMethod transpiler = null)
{
string logMessage = $"Performing {patchName} patch... ";
try
{
if (original == null)
{
logMessage += "failed! method does not exist! \t\t\t!!!!!";
}
else
{
ms_harmony.Patch(original, prefix, postfix, transpiler);
logMessage += "succeeded!";
}
}
catch (Exception e)
{
logMessage += $"failed! (Exception: {e.Message})";
}
Log.Info(logMessage);
}
public static void MakeRET(Type targetType, string methodName, bool retVal = false, Type[] methodTypes = null)
{
MethodInfo meth = default;
if (methodTypes != null)
{
meth = targetType.GetMethod(methodName, (BindingFlags)62, null, methodTypes, null);
}
else
{
meth = targetType.GetMethod(methodName, (BindingFlags)62);
}
var ret = meth.ReturnType;
if (ret == typeof(void))
{
PerformPatch($"MakeRET {targetType.Name} # {methodName}", meth, GetPatch("DontContinue", typeof(Harmony)));
}
else if (ret == typeof(bool))
{
PerformPatch($"MakeRET {targetType.Name} # {methodName}", meth, GetPatch(retVal ? "ReturnTrue" : "ReturnFalse", typeof(Harmony)));
}
else
{
Log.Info($"MakeRET not supported for type: {ret.FullName}");
}
}
static bool ReturnFalse(ref bool __result)
{
__result = false;
return false;
}
static bool ReturnTrue(ref bool __result)
{
__result = true;
return false;
}
static bool DontContinue()
{
return false;
}
static Harmony()
{
ms_harmony = HarmonyInstance.Create("UnityParrot.ONGEKI.Patches");
}
}
}