From 6b38cee1277f4e3da5f2f685aee8b503a14d4054 Mon Sep 17 00:00:00 2001 From: ManlyMarco <39247311+ManlyMarco@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:26:49 +0200 Subject: [PATCH] Fix failing to initialize if game's Data folder is just 'Data' (#975) Any Unity game can have its _Data folder renamed to just Data and continue working just fine. --- BepInEx.Core/Paths.cs | 22 +++++++++++++++---- .../Il2CppInteropManager.cs | 3 +-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/BepInEx.Core/Paths.cs b/BepInEx.Core/Paths.cs index 34d3e98..6a37342 100644 --- a/BepInEx.Core/Paths.cs +++ b/BepInEx.Core/Paths.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Linq; using System.Reflection; using MonoMod.Utils; @@ -106,9 +106,23 @@ public static class Paths ? Utility.ParentDirectory(executablePath, 4) : Path.GetDirectoryName(executablePath); - GameDataPath = managedPath != null && gameDataRelativeToManaged - ? Path.GetDirectoryName(managedPath) - : Path.Combine(GameRootPath, $"{ProcessName}_Data"); + if (managedPath != null && gameDataRelativeToManaged) + { + GameDataPath = Path.GetDirectoryName(managedPath); + } + else + { + // According to some experiments, Unity checks whether globalgamemanagers/data.unity3d exists in the data folder before picking it. + // 'ProcessName_Data' folder is checked first, then if that fails 'Data' folder is checked. If neither is valid, the player crashes. + // A simple Directory.Exists check is accurate enough while being less likely to break in case these conditions change. + GameDataPath = Path.Combine(GameRootPath, $"{ProcessName}_Data"); + if (!Directory.Exists(GameDataPath)) + GameDataPath = Path.Combine(GameRootPath, "Data"); + } + + if (string.IsNullOrEmpty(GameDataPath) || !Directory.Exists(GameDataPath)) + throw new DirectoryNotFoundException("Failed to extract valid GameDataPath from executablePath: " + executablePath); + ManagedPath = managedPath ?? Path.Combine(GameDataPath, "Managed"); BepInExRootPath = bepinRootPath ?? Path.Combine(GameRootPath, "BepInEx"); ConfigPath = Path.Combine(BepInExRootPath, "config"); diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs b/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs index cc43fac..4e2761a 100644 --- a/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/Il2CppInteropManager.cs @@ -281,8 +281,7 @@ internal static partial class Il2CppInteropManager { Logger.LogMessage("Running Cpp2IL to generate dummy assemblies"); - var metadataPath = Path.Combine(Paths.GameRootPath, - $"{Paths.ProcessName}_Data", + var metadataPath = Path.Combine(Paths.GameDataPath, "il2cpp_data", "Metadata", "global-metadata.dat");