Browse Source

Utilize preloader environment variables and allow customizable BepInEx directory location

Bepis 5 years ago
parent
commit
4fac0f7bed

+ 1 - 0
BepInEx.Preloader/BepInEx.Preloader.csproj

@@ -39,6 +39,7 @@
     <Reference Include="System.Core" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="EnvVars.cs" />
     <Compile Include="Patching\AssemblyPatcher.cs" />
     <Compile Include="Entrypoint.cs" />
     <Compile Include="Patching\PatcherPlugin.cs" />

+ 6 - 1
BepInEx.Preloader/Entrypoint.cs

@@ -1,4 +1,5 @@
 using System;
+using System.IO;
 using System.Linq;
 using System.Reflection;
 
@@ -15,7 +16,11 @@ namespace BepInEx.Preloader
 		/// </param>
 		public static void Main(string[] args)
 		{
-			Paths.SetExecutablePath(args[0]);
+			EnvVars.LoadVars();
+
+			string bepinPath = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH)));
+
+			Paths.SetExecutablePath(args[0], bepinPath, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR);
 			AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
 
 			Preloader.Run();

+ 27 - 0
BepInEx.Preloader/EnvVars.cs

@@ -0,0 +1,27 @@
+using System;
+
+namespace BepInEx.Preloader
+{
+	/// <summary>
+	/// Doorstop environment variables, passed into the BepInEx preloader.
+	/// <para>https://github.com/NeighTools/UnityDoorstop/wiki#environment-variables</para>
+	/// </summary>
+	public static class EnvVars
+	{
+		/// <summary>
+		/// Path to the assembly that was invoked via Doorstop. Contains the same value as in "targetAssembly" configuration option in the config file.
+		/// </summary>
+		public static string DOORSTOP_INVOKE_DLL_PATH { get; private set; }
+
+		/// <summary>
+		/// Full path to the game's "Managed" folder that contains all the game's managed assemblies
+		/// </summary>
+		public static string DOORSTOP_MANAGED_FOLDER_DIR { get; private set; }
+
+		internal static void LoadVars()
+		{
+			DOORSTOP_INVOKE_DLL_PATH = Environment.GetEnvironmentVariable("DOORSTOP_INVOKE_DLL_PATH");
+			DOORSTOP_MANAGED_FOLDER_DIR = Environment.GetEnvironmentVariable("DOORSTOP_MANAGED_FOLDER_DIR");
+		}
+	}
+}

+ 3 - 3
BepInEx.Preloader/Preloader.cs

@@ -279,11 +279,11 @@ namespace BepInEx.Preloader
 					var ins = il.Body.Instructions.First();
 
 					il.InsertBefore(ins,
-						il.Create(OpCodes.Ldstr, Paths.ExecutablePath)); //containerExePath
+						il.Create(OpCodes.Ldnull)); // gameExePath (always null, we initialize the Paths class in Entrypoint
 					il.InsertBefore(ins,
-						il.Create(OpCodes.Ldc_I4_0)); //startConsole (always false, we already load the console in Preloader)
+						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 gameExePath, bool startConsole = true)
 					il.InsertBefore(ins,
 						il.Create(OpCodes.Call, startMethod));
 				}

+ 11 - 5
BepInEx/Bootstrap/Chainloader.cs

@@ -36,24 +36,30 @@ namespace BepInEx.Bootstrap
 		/// <summary>
         /// Initializes BepInEx to be able to start the chainloader.
         /// </summary>
-        public static void Initialize(string containerExePath, bool startConsole = true)
+        public static void Initialize(string gameExePath, bool startConsole = true)
 		{
 			if (_initialized)
 				return;
 
-			//Set vitals
-			Paths.SetExecutablePath(containerExePath);
+			// Set vitals
+
+			if (gameExePath != null)
+			{
+				// Checking for null allows a more advanced initialization workflow, where the Paths class has been initialized before calling Chainloader.Initialize
+				// This is used by Preloader to use environment variables, for example
+				Paths.SetExecutablePath(gameExePath);
+			}
 
 			Paths.SetPluginPath(ConfigPluginsDirectory.Value);
 
-            //Start logging
+            // Start logging
             if (ConsoleWindow.ConfigConsoleEnabled.Value && startConsole)
 			{
 				ConsoleWindow.Attach();
 				Logger.Listeners.Add(new ConsoleLogListener());
             }
 
-			//Fix for standard output getting overwritten by UnityLogger
+			// Fix for standard output getting overwritten by UnityLogger
 			if (ConsoleWindow.StandardOut != null)
 			{
 				Console.SetOut(ConsoleWindow.StandardOut);

+ 3 - 3
BepInEx/Paths.cs

@@ -8,13 +8,13 @@ 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)
 		{
 			ExecutablePath = executablePath;
 			ProcessName = Path.GetFileNameWithoutExtension(executablePath);
 			GameRootPath = Path.GetDirectoryName(executablePath);
-			ManagedPath = Utility.CombinePaths(GameRootPath, $"{ProcessName}_Data", "Managed");
-			BepInExRootPath = Path.Combine(GameRootPath, "BepInEx");
+			ManagedPath = managedPath ?? Utility.CombinePaths(GameRootPath, $"{ProcessName}_Data", "Managed");
+			BepInExRootPath = bepinRootPath ?? Path.Combine(GameRootPath, "BepInEx");
 			ConfigPath = Path.Combine(BepInExRootPath, "config");
 			BepInExConfigPath = Path.Combine(ConfigPath, "BepInEx.cfg");
 			PluginPath = Path.Combine(BepInExRootPath, "plugins");