mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Unify Paths initializers; refactor preloader to unify build into one
This commit is contained in:
1 parent
c8118efcc0
commit
ba51ca8d8c
6 files changed
+77
-86
No files matched your search
@@ -9,8 +9,9 @@ namespace BepInEx.Preloader
|
||||
{
|
||||
public static void PreloaderMain(string[] args)
|
||||
{
|
||||
Paths.SetExecutablePath(args[0]);
|
||||
Paths.SetManagedPath(Environment.GetEnvironmentVariable("DOORSTOP_MANAGED_FOLDER_DIR"));
|
||||
Paths.SetExecutablePath(args[0],
|
||||
Path.GetDirectoryName(Path.GetDirectoryName(Path.GetFullPath(Environment.GetEnvironmentVariable("DOORSTOP_INVOKE_DLL_PATH")))),
|
||||
Environment.GetEnvironmentVariable("DOORSTOP_MANAGED_FOLDER_DIR"));
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
|
||||
Preloader.Run();
|
||||
|
||||
@@ -41,20 +41,50 @@ namespace BepInEx.Preloader.Patching
|
||||
|
||||
private static T CreateDelegate<T>(MethodInfo method) where T : class => method != null ? Delegate.CreateDelegate(typeof(T), method) as T : null;
|
||||
|
||||
private static PatcherPlugin ToPatcherPlugin(TypeDefinition type)
|
||||
{
|
||||
if (type.IsInterface || type.IsAbstract && !type.IsSealed)
|
||||
return null;
|
||||
|
||||
var targetDlls = type.Methods.FirstOrDefault(m => m.Name.Equals("get_TargetDLLs", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
m.IsPublic &&
|
||||
m.IsStatic);
|
||||
|
||||
if (targetDlls == null ||
|
||||
targetDlls.ReturnType.FullName != "System.Collections.Generic.IEnumerable`1<System.String>")
|
||||
return null;
|
||||
|
||||
var patch = type.Methods.FirstOrDefault(m => m.Name.Equals("Patch") &&
|
||||
m.IsPublic &&
|
||||
m.IsStatic &&
|
||||
m.ReturnType.FullName == "System.Void" &&
|
||||
m.Parameters.Count == 1 &&
|
||||
(m.Parameters[0].ParameterType.FullName == "Mono.Cecil.AssemblyDefinition&" ||
|
||||
m.Parameters[0].ParameterType.FullName == "Mono.Cecil.AssemblyDefinition"));
|
||||
|
||||
if (patch == null)
|
||||
return null;
|
||||
|
||||
return new PatcherPlugin
|
||||
{
|
||||
Type = type,
|
||||
Name = type.FullName
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds all patchers from all managed assemblies specified in a directory.
|
||||
/// </summary>
|
||||
/// <param name="directory">Directory to search patcher DLLs from.</param>
|
||||
/// <param name="patcherLocator">A function that locates assembly patchers in a given managed assembly.</param>
|
||||
public static void AddPatchersFromDirectory(string directory,
|
||||
Func<TypeDefinition, PatcherPlugin> patcherLocator)
|
||||
/// Adds all patchers from all managed assemblies specified in a directory.
|
||||
/// </summary>
|
||||
/// <param name="directory">Directory to search patcher DLLs from.</param>
|
||||
/// <param name="patcherLocator">A function that locates assembly patchers in a given managed assembly.</param>
|
||||
public static void AddPatchersFromDirectory(string directory)
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
return;
|
||||
|
||||
var sortedPatchers = new SortedDictionary<string, PatcherPlugin>();
|
||||
|
||||
var patchers = TypeLoader.FindPluginTypes(directory, patcherLocator);
|
||||
var patchers = TypeLoader.FindPluginTypes(directory, ToPatcherPlugin);
|
||||
|
||||
foreach (var keyValuePair in patchers)
|
||||
{
|
||||
@@ -83,7 +113,7 @@ namespace BepInEx.Preloader.Patching
|
||||
|
||||
var patcher = methods.FirstOrDefault(m => m.Name.Equals("Patch", StringComparison.CurrentCultureIgnoreCase) &&
|
||||
m.ReturnType == typeof(void) &&
|
||||
m.GetParameters().Length == 0 &&
|
||||
m.GetParameters().Length == 1 &&
|
||||
(m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition) ||
|
||||
m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition).MakeByRefType()));
|
||||
|
||||
@@ -209,7 +239,7 @@ namespace BepInEx.Preloader.Patching
|
||||
|
||||
if (ConfigBreakBeforeLoadAssemblies.Value)
|
||||
{
|
||||
Logger.LogInfo($"BepInEx is about load the following assemblies:\n{string.Join("\n", patchedAssemblies.ToArray())}");
|
||||
Logger.LogInfo($"BepInEx is about load the following assemblies:\n{String.Join("\n", patchedAssemblies.ToArray())}");
|
||||
Logger.LogInfo($"The assemblies were dumped into {DumpedAssembliesPath}");
|
||||
Logger.LogInfo("Load any assemblies into the debugger, set breakpoints and continue execution.");
|
||||
Debugger.Break();
|
||||
|
||||
@@ -26,6 +26,20 @@ namespace BepInEx.Preloader
|
||||
/// </summary>
|
||||
private static PreloaderConsoleListener PreloaderLog { get; set; }
|
||||
|
||||
public static bool IsPostUnity2017 { get; } = File.Exists(Path.Combine(Paths.ManagedPath, "UnityEngine.CoreModule.dll"));
|
||||
|
||||
public static bool IsDotNet46 { get; } = string.Compare("4.0.30319.42000", Environment.Version.ToString(), StringComparison.Ordinal) <= 0;
|
||||
|
||||
static Preloader()
|
||||
{
|
||||
ConfigEntrypointAssembly = ConfigFile.CoreConfig.Wrap(
|
||||
"Preloader.Entrypoint",
|
||||
"Assembly",
|
||||
"The local filename of the assembly to target.",
|
||||
IsPostUnity2017 ? "UnityEngine.CoreModule.dll" : "UnityEngine.dll"
|
||||
);
|
||||
}
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
try
|
||||
@@ -57,13 +71,8 @@ namespace BepInEx.Preloader
|
||||
Logger.LogMessage(attribute.Info);
|
||||
}
|
||||
|
||||
#if UNITY_2018
|
||||
Logger.LogMessage("Compiled in Unity v2018 mode");
|
||||
#else
|
||||
Logger.LogMessage("Compiled in Legacy Unity mode");
|
||||
#endif
|
||||
|
||||
Logger.LogInfo($"Running under Unity v{Process.GetCurrentProcess().MainModule.FileVersionInfo.FileVersion}");
|
||||
Logger.LogInfo($"Running under Unity v{FileVersionInfo.GetVersionInfo(Paths.ExecutablePath).FileVersion}");
|
||||
Logger.LogInfo($"CLR runtime version: {Environment.Version}");
|
||||
|
||||
Logger.LogMessage("Preloader started");
|
||||
|
||||
@@ -75,7 +84,7 @@ namespace BepInEx.Preloader
|
||||
Name = "BepInEx.Chainloader"
|
||||
});
|
||||
|
||||
AssemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath, ToPatcherPlugin);
|
||||
AssemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);
|
||||
|
||||
Logger.LogInfo($"{AssemblyPatcher.PatcherPlugins.Count} patcher plugin(s) loaded");
|
||||
|
||||
@@ -123,36 +132,6 @@ namespace BepInEx.Preloader
|
||||
}
|
||||
}
|
||||
|
||||
public static PatcherPlugin ToPatcherPlugin(TypeDefinition type)
|
||||
{
|
||||
if (type.IsInterface || type.IsAbstract)
|
||||
return null;
|
||||
|
||||
var targetDlls = type.Methods.FirstOrDefault(m => m.Name.Equals("get_TargetDLLs", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
m.IsPublic &&
|
||||
m.IsStatic);
|
||||
|
||||
if (targetDlls == null ||
|
||||
targetDlls.ReturnType.FullName != "System.Collections.Generic.IEnumerable`1<System.String>")
|
||||
return null;
|
||||
|
||||
var patch = type.Methods.FirstOrDefault(m => m.Name.Equals("Patch") &&
|
||||
m.IsPublic &&
|
||||
m.IsStatic &&
|
||||
m.ReturnType.FullName == "System.Void" &&
|
||||
m.Parameters.Count == 1 &&
|
||||
(m.Parameters[0].ParameterType.FullName == "Mono.Cecil.AssemblyDefinition&" ||
|
||||
m.Parameters[0].ParameterType.FullName == "Mono.Cecil.AssemblyDefinition"));
|
||||
|
||||
if (patch == null)
|
||||
return null;
|
||||
|
||||
return new PatcherPlugin
|
||||
{
|
||||
Type = type
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts BepInEx's own chainloader entrypoint into UnityEngine.
|
||||
/// </summary>
|
||||
@@ -223,7 +202,7 @@ namespace BepInEx.Preloader
|
||||
il.InsertBefore(ins,
|
||||
il.Create(OpCodes.Ldc_I4_0)); //startConsole (always false, we already load the console in Preloader)
|
||||
il.InsertBefore(ins,
|
||||
il.Create(OpCodes.Call, initMethod)); //Chainloader.Initialize(string containerExePath, bool startConsole = true)
|
||||
il.Create(OpCodes.Call, initMethod)); // Chainloader.Initialize(string containerExePath, string managedPath = null, bool startConsole = true)
|
||||
il.InsertBefore(ins,
|
||||
il.Create(OpCodes.Call, startMethod));
|
||||
}
|
||||
@@ -259,16 +238,7 @@ namespace BepInEx.Preloader
|
||||
|
||||
#region Config
|
||||
|
||||
private static readonly ConfigWrapper<string> ConfigEntrypointAssembly = ConfigFile.CoreConfig.Wrap(
|
||||
"Preloader.Entrypoint",
|
||||
"Assembly",
|
||||
"The local filename of the assembly to target.",
|
||||
#if UNITY_2018
|
||||
"UnityEngine.CoreModule.dll"
|
||||
#else
|
||||
"UnityEngine.dll"
|
||||
#endif
|
||||
);
|
||||
private static readonly ConfigWrapper<string> ConfigEntrypointAssembly;
|
||||
|
||||
private static readonly ConfigWrapper<string> ConfigEntrypointType = ConfigFile.CoreConfig.Wrap(
|
||||
"Preloader.Entrypoint",
|
||||
|
||||
@@ -40,17 +40,13 @@ namespace BepInEx.Preloader.RuntimeFixes
|
||||
__result = $"file://{location.Replace('\\', '/')}";
|
||||
}
|
||||
|
||||
#if UNITY_2018
|
||||
/*
|
||||
* DESC: Workaround for Trace class not working because of missing .config file
|
||||
* AFFECTS: Unity 2018+ (not .NET Standard / MonoBleedingEdge runtimes)
|
||||
*/
|
||||
[HarmonyPostfix, HarmonyPatch(typeof(AppDomain), nameof(AppDomain.SetupInformation), MethodType.Getter)]
|
||||
public static void GetExeConfigName(AppDomainSetup __result)
|
||||
{
|
||||
if (!Preloader.IsDotNet46)
|
||||
return;
|
||||
__result.ApplicationBase = $"file://{Paths.GameRootPath}";
|
||||
__result.ConfigurationFile = "app.config";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -39,15 +39,13 @@ namespace BepInEx.Bootstrap
|
||||
/// <summary>
|
||||
/// Initializes BepInEx to be able to start the chainloader.
|
||||
/// </summary>
|
||||
public static void Initialize(string containerExePath, string managedPath = null, bool startConsole = true)
|
||||
public static void Initialize(string containerExePath, bool startConsole = true)
|
||||
{
|
||||
if (_initialized)
|
||||
return;
|
||||
|
||||
//Set vitals
|
||||
Paths.SetExecutablePath(containerExePath);
|
||||
Paths.SetManagedPath(managedPath);
|
||||
Paths.SetPluginPath(ConfigPluginsDirectory.Value);
|
||||
Paths.SetExecutablePath(containerExePath, pluginPath: ConfigPluginsDirectory.Value);
|
||||
|
||||
//Start logging
|
||||
if (ConsoleWindow.ConfigConsoleEnabled.Value && startConsole)
|
||||
|
||||
+12
-16
@@ -8,33 +8,29 @@ namespace BepInEx
|
||||
/// </summary>
|
||||
public static class Paths
|
||||
{
|
||||
internal static void SetExecutablePath(string executablePath)
|
||||
internal static void SetExecutablePath(string executablePath, string bepinRootPath = null, string managedPath = null, string pluginPath = null)
|
||||
{
|
||||
ExecutablePath = executablePath;
|
||||
ProcessName = Path.GetFileNameWithoutExtension(executablePath);
|
||||
GameRootPath = Path.GetDirectoryName(executablePath);
|
||||
ManagedPath = Utility.CombinePaths(GameRootPath, $"{ProcessName}_Data", "Managed");
|
||||
BepInExRootPath = Path.Combine(GameRootPath, "BepInEx");
|
||||
|
||||
if (ManagedPath == null || managedPath != null)
|
||||
ManagedPath = managedPath ?? Utility.CombinePaths(GameRootPath, $"{ProcessName}_Data", "Managed");
|
||||
|
||||
if (BepInExRootPath == null || bepinRootPath != null)
|
||||
BepInExRootPath = bepinRootPath ?? Path.Combine(GameRootPath, "BepInEx");
|
||||
|
||||
ConfigPath = Path.Combine(BepInExRootPath, "config");
|
||||
BepInExConfigPath = Path.Combine(ConfigPath, "BepInEx.cfg");
|
||||
PluginPath = Path.Combine(BepInExRootPath, "plugins");
|
||||
|
||||
if (PluginPath == null || pluginPath != null)
|
||||
PluginPath = pluginPath ?? Path.Combine(BepInExRootPath, "plugins");
|
||||
|
||||
PatcherPluginPath = Path.Combine(BepInExRootPath, "patchers");
|
||||
BepInExAssemblyDirectory = Path.Combine(BepInExRootPath, "core");
|
||||
BepInExAssemblyPath = Path.Combine(BepInExAssemblyDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.dll");
|
||||
}
|
||||
|
||||
internal static void SetManagedPath(string managedPath)
|
||||
{
|
||||
if (managedPath == null)
|
||||
return;
|
||||
ManagedPath = managedPath;
|
||||
}
|
||||
|
||||
internal static void SetPluginPath(string pluginPath)
|
||||
{
|
||||
PluginPath = Utility.CombinePaths(BepInExRootPath, pluginPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The directory that the core BepInEx DLLs reside in.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user