mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Implement patcher contract
This commit is contained in:
1 parent
fb96717caf
commit
b2d159943b
1 file changed
+68
-4
@@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using BepInEx.Common;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using MethodAttributes = Mono.Cecil.MethodAttributes;
|
||||
@@ -24,7 +25,9 @@ namespace BepInEx.Bootstrap
|
||||
|
||||
public static string GameRootPath => Path.GetDirectoryName(ExecutablePath);
|
||||
|
||||
public static string ManagedPath => Path.Combine(GameRootPath, Path.Combine($"{GameName}_Data", "Managed"));
|
||||
public static string ManagedPath => Utility.CombinePaths(GameRootPath, $"{GameName}_Data", "Managed");
|
||||
|
||||
public static string PatcherPluginPath => Utility.CombinePaths(GameRootPath, "BepInEx", "patchers");
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -53,18 +56,79 @@ namespace BepInEx.Bootstrap
|
||||
|
||||
try
|
||||
{
|
||||
//AssemblyPatcher.AssemblyLoad += PatchEntrypoint;
|
||||
|
||||
AddPatcher("UnityEngine.dll", PatchEntrypoint);
|
||||
|
||||
if (Directory.Exists(PatcherPluginPath))
|
||||
foreach (string assemblyPath in Directory.GetFiles(PatcherPluginPath, "*.dll"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.LoadFrom(assemblyPath);
|
||||
|
||||
foreach (var kv in GetPatcherMethods(assembly))
|
||||
foreach (var patcher in kv.Value)
|
||||
AddPatcher(kv.Key, patcher);
|
||||
}
|
||||
catch (BadImageFormatException) { } //unmanaged DLL
|
||||
catch (ReflectionTypeLoadException) { } //invalid references
|
||||
}
|
||||
|
||||
AssemblyPatcher.PatchAll(ManagedPath, PatcherDictionary);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//File.WriteAllText("B:\\test.txt", ex.ToString());
|
||||
//TODO: some proper exception handling
|
||||
}
|
||||
}
|
||||
|
||||
internal static IDictionary<string, IList<AssemblyPatcherDelegate>> GetPatcherMethods(Assembly assembly)
|
||||
{
|
||||
var patcherMethods = new Dictionary<string, IList<AssemblyPatcherDelegate>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var type in assembly.GetExportedTypes())
|
||||
{
|
||||
if (type.IsInterface)
|
||||
continue;
|
||||
|
||||
PropertyInfo targetsProperty = type.GetProperty(
|
||||
"TargetDLLs",
|
||||
BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase,
|
||||
null,
|
||||
typeof(IEnumerable<string>),
|
||||
Type.EmptyTypes,
|
||||
null);
|
||||
|
||||
MethodInfo patcher = type.GetMethod(
|
||||
"Patch",
|
||||
BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase,
|
||||
null,
|
||||
CallingConventions.Any,
|
||||
new[] { typeof(AssemblyDefinition) },
|
||||
null);
|
||||
|
||||
if (targetsProperty == null || !targetsProperty.CanRead || patcher == null)
|
||||
continue;
|
||||
|
||||
AssemblyPatcherDelegate patchDelegate = (ass) => { patcher.Invoke(null, new object[] {ass}); };
|
||||
|
||||
IEnumerable<string> targets = (IEnumerable<string>)targetsProperty.GetValue(null, null);
|
||||
|
||||
foreach (string target in targets)
|
||||
{
|
||||
if (patcherMethods.TryGetValue(target, out IList<AssemblyPatcherDelegate> patchers))
|
||||
patchers.Add(patchDelegate);
|
||||
else
|
||||
{
|
||||
patchers = new List<AssemblyPatcherDelegate>{ patchDelegate };
|
||||
|
||||
patcherMethods[target] = patchers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return patcherMethods;
|
||||
}
|
||||
|
||||
internal static void PatchEntrypoint(AssemblyDefinition assembly)
|
||||
{
|
||||
if (assembly.Name.Name == "UnityEngine")
|
||||
|
||||
Reference in new issue
Block a user