|
1 | | -using System.IO; |
| 1 | +using System.IO; |
2 | 2 | using System.Linq; |
3 | 3 | using System.Reflection; |
4 | 4 | using MonoMod.Utils; |
@@ -106,9 +106,23 @@ public static void SetExecutablePath(string executablePath, |
106 | 106 | ? Utility.ParentDirectory(executablePath, 4) |
107 | 107 | : Path.GetDirectoryName(executablePath); |
108 | 108 |
|
109 | | - GameDataPath = managedPath != null && gameDataRelativeToManaged |
110 | | - ? Path.GetDirectoryName(managedPath) |
111 | | - : Path.Combine(GameRootPath, $"{ProcessName}_Data"); |
| 109 | + if (managedPath != null && gameDataRelativeToManaged) |
| 110 | + { |
| 111 | + GameDataPath = Path.GetDirectoryName(managedPath); |
| 112 | + } |
| 113 | + else |
| 114 | + { |
| 115 | + // According to some experiments, Unity checks whether globalgamemanagers/data.unity3d exists in the data folder before picking it. |
| 116 | + // 'ProcessName_Data' folder is checked first, then if that fails 'Data' folder is checked. If neither is valid, the player crashes. |
| 117 | + // A simple Directory.Exists check is accurate enough while being less likely to break in case these conditions change. |
| 118 | + GameDataPath = Path.Combine(GameRootPath, $"{ProcessName}_Data"); |
| 119 | + if (!Directory.Exists(GameDataPath)) |
| 120 | + GameDataPath = Path.Combine(GameRootPath, "Data"); |
| 121 | + } |
| 122 | + |
| 123 | + if (string.IsNullOrEmpty(GameDataPath) || !Directory.Exists(GameDataPath)) |
| 124 | + throw new DirectoryNotFoundException("Failed to extract valid GameDataPath from executablePath: " + executablePath); |
| 125 | + |
112 | 126 | ManagedPath = managedPath ?? Path.Combine(GameDataPath, "Managed"); |
113 | 127 | BepInExRootPath = bepinRootPath ?? Path.Combine(GameRootPath, "BepInEx"); |
114 | 128 | ConfigPath = Path.Combine(BepInExRootPath, "config"); |
|
0 commit comments