|
1 | | -using System.Diagnostics; |
| 1 | +using System; |
| 2 | +using System.Diagnostics; |
2 | 3 | using System.IO; |
3 | 4 | using System.Reflection; |
4 | 5 | using System.Runtime.CompilerServices; |
|
10 | 11 | using MonoMod.Utils; |
11 | 12 | using UnityEngine; |
12 | 13 | using Logger = BepInEx.Logging.Logger; |
| 14 | +using Object = UnityEngine.Object; |
| 15 | + |
| 16 | +[assembly: InternalsVisibleTo("UnityEngine")] |
| 17 | +[assembly: InternalsVisibleTo("UnityEngine.Core")] |
13 | 18 |
|
14 | 19 | namespace BepInEx.Unity.Bootstrap; |
15 | 20 |
|
@@ -53,31 +58,81 @@ private static string UnityVersion |
53 | 58 | get => Application.unityVersion; |
54 | 59 | } |
55 | 60 |
|
56 | | - private static void StaticStart(string gameExePath = null) |
| 61 | + private static Version UnityVersionAsVersion => new Version(UnityVersion.Substring(0, UnityVersion.LastIndexOf('.') + 2)); |
| 62 | + |
| 63 | + private static bool staticStartHasBeenCalled = false; |
| 64 | + |
| 65 | + /// <summary> |
| 66 | + /// This method is public so that BepInEx can correctly initialize on some versions of Unity that do not respect InternalsVisibleToAttribute. Do not call this yourself |
| 67 | + /// </summary> |
| 68 | + [Obsolete("This method is public so that BepInEx can correctly initialize on some versions of Unity that do not respect InternalsVisibleToAttribute. DO NOT CALL", true)] |
| 69 | + public static void StaticStart(string gameExePath = null) |
57 | 70 | { |
58 | | - var instance = new UnityChainloader(); |
59 | | - instance.Initialize(gameExePath); |
60 | | - instance.Execute(); |
| 71 | + try |
| 72 | + { |
| 73 | + if (staticStartHasBeenCalled) |
| 74 | + throw new InvalidOperationException("Cannot call StaticStart again"); |
| 75 | + |
| 76 | + Logger.Log(LogLevel.Debug, "Entering chainloader StaticStart"); |
| 77 | + |
| 78 | + var instance = new UnityChainloader(); |
| 79 | + instance.Initialize(gameExePath); |
| 80 | + instance.Execute(); |
| 81 | + |
| 82 | + staticStartHasBeenCalled = true; |
| 83 | + |
| 84 | + Logger.Log(LogLevel.Debug, "Exiting chainloader StaticStart"); |
| 85 | + } |
| 86 | + catch (Exception ex) |
| 87 | + { |
| 88 | + Logger.Log(LogLevel.Fatal, $"Unable to complete chainloader StaticStart: {ex.Message}"); |
| 89 | + Logger.Log(LogLevel.Fatal, ex.StackTrace); |
| 90 | + } |
61 | 91 | } |
62 | 92 |
|
63 | 93 |
|
64 | 94 | public override void Initialize(string gameExePath = null) |
65 | 95 | { |
66 | | - Instance = this; |
| 96 | + try |
| 97 | + { |
| 98 | + Logger.Log(LogLevel.Debug, "Entering chainloader initialize"); |
| 99 | + |
| 100 | + Instance = this; |
| 101 | + |
| 102 | + UnityTomlTypeConverters.AddUnityEngineConverters(); |
| 103 | + |
| 104 | + Logger.Log(LogLevel.Debug, "Creating Manager object"); |
| 105 | + |
| 106 | + ManagerObject = new GameObject("BepInEx_Manager") { hideFlags = HideFlags.HideAndDontSave }; |
| 107 | + Object.DontDestroyOnLoad(ManagerObject); |
| 108 | + |
| 109 | + Logger.Log(LogLevel.Debug, "Getting game product name"); |
| 110 | + |
| 111 | + var productNameProp = typeof(Application).GetProperty("productName", BindingFlags.Public | BindingFlags.Static); |
67 | 112 |
|
68 | | - UnityTomlTypeConverters.AddUnityEngineConverters(); |
| 113 | + _consoleTitle = $"{CurrentAssemblyName} {CurrentAssemblyVersion} - {productNameProp?.GetValue(null, null) ?? Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName)}"; |
69 | 114 |
|
70 | | - ThreadingHelper.Initialize(); |
| 115 | + if (UnityVersionAsVersion.Major >= 5) |
| 116 | + { |
| 117 | + Logger.Log(LogLevel.Debug, "Initializing ThreadingHelper"); |
| 118 | + ThreadingHelper.Initialize(); |
| 119 | + } |
| 120 | + else |
| 121 | + { |
| 122 | + Logger.Log(LogLevel.Debug, "Skipping ThreadingHelper init due to unity version (<= 4)"); |
| 123 | + } |
71 | 124 |
|
72 | | - ManagerObject = new GameObject("BepInEx_Manager") { hideFlags = HideFlags.HideAndDontSave }; |
73 | | - Object.DontDestroyOnLoad(ManagerObject); |
| 125 | + Logger.Log(LogLevel.Debug, "Falling back to BaseChainloader initializer"); |
74 | 126 |
|
75 | | - var productNameProp = |
76 | | - typeof(Application).GetProperty("productName", BindingFlags.Public | BindingFlags.Static); |
77 | | - _consoleTitle = |
78 | | - $"{CurrentAssemblyName} {CurrentAssemblyVersion} - {productNameProp?.GetValue(null, null) ?? Path.GetFileNameWithoutExtension(Process.GetCurrentProcess().ProcessName)}"; |
| 127 | + base.Initialize(gameExePath); |
79 | 128 |
|
80 | | - base.Initialize(gameExePath); |
| 129 | + Logger.Log(LogLevel.Debug, "Exiting chainloader initialize"); |
| 130 | + } |
| 131 | + catch (Exception ex) |
| 132 | + { |
| 133 | + Logger.Log(LogLevel.Fatal, $"Unable to complete chainloader init: {ex.Message}"); |
| 134 | + Logger.Log(LogLevel.Fatal, ex.StackTrace); |
| 135 | + } |
81 | 136 | } |
82 | 137 |
|
83 | 138 | protected override void InitializeLoggers() |
|
0 commit comments