/// <summary> /// The entry point for the BepInEx plugin system, called on the very first LoadScene() from UnityEngine. /// </summary> public static void Initialize() { if (_loaded) { return; } if (!Directory.Exists(Utility.PluginsDirectory)) { Directory.CreateDirectory(Utility.PluginsDirectory); } Preloader.AllocateConsole(); try { UnityLogWriter unityLogWriter = new UnityLogWriter(); if (Preloader.PreloaderLog != null) { unityLogWriter.WriteToLog($"{Preloader.PreloaderLog}\r\n"); } Logger.SetLogger(unityLogWriter); if (bool.Parse(Config.GetEntry("log_unity_messages", "false", "Global"))) { UnityLogWriter.ListenUnityLogs(); } string consoleTile = $"BepInEx {Assembly.GetExecutingAssembly().GetName().Version} - {Application.productName}"; ConsoleWindow.Title = consoleTile; Logger.Log(LogLevel.Message, "Chainloader started"); UnityEngine.Object.DontDestroyOnLoad(ManagerObject); string currentProcess = Process.GetCurrentProcess().ProcessName.ToLower(); var pluginTypes = TypeLoader.LoadTypes <BaseUnityPlugin>(Utility.PluginsDirectory) .Where(plugin => { //Perform a filter for currently running process var filters = MetadataHelper.GetAttributes <BepInProcess>(plugin); if (!filters.Any()) { return(true); } return(filters.Any(x => x.ProcessName.ToLower().Replace(".exe", "") == currentProcess)); }) .ToList(); Logger.Log(LogLevel.Info, $"{pluginTypes.Count} plugins selected"); Dictionary <Type, IEnumerable <Type> > dependencyDict = new Dictionary <Type, IEnumerable <Type> >(); foreach (Type t in pluginTypes) { try { IEnumerable <Type> dependencies = MetadataHelper.GetDependencies(t, pluginTypes); dependencyDict[t] = dependencies; } catch (MissingDependencyException) { var metadata = MetadataHelper.GetMetadata(t); Logger.Log(LogLevel.Info, $"Cannot load [{metadata.Name}] due to missing dependencies."); } } pluginTypes = Utility.TopologicalSort(dependencyDict.Keys, x => dependencyDict[x]).ToList(); foreach (Type t in pluginTypes) { try { var metadata = MetadataHelper.GetMetadata(t); var plugin = (BaseUnityPlugin)ManagerObject.AddComponent(t); Plugins.Add(plugin); Logger.Log(LogLevel.Info, $"Loaded [{metadata.Name} {metadata.Version}]"); } catch (Exception ex) { Logger.Log(LogLevel.Info, $"Error loading [{t.Name}] : {ex.Message}"); } } } catch (Exception ex) { UnityInjector.ConsoleUtil.ConsoleWindow.Attach(); Console.WriteLine("Error occurred starting the game"); Console.WriteLine(ex.ToString()); } _loaded = true; }
/// <summary> /// The entrypoint for the BepInEx plugin system. /// </summary> public static void Start() { if (_loaded) { return; } if (!_initialized) { throw new InvalidOperationException("BepInEx has not been initialized. Please call Chainloader.Initialize prior to starting the chainloader instance."); } if (!Directory.Exists(Paths.PluginPath)) { Directory.CreateDirectory(Paths.PluginPath); } try { if (bool.Parse(Config.GetEntry("chainloader-log-unity-messages", "false", "BepInEx"))) { UnityLogWriter.ListenUnityLogs(); } var productNameProp = typeof(Application).GetProperty("productName", BindingFlags.Public | BindingFlags.Static); if (productNameProp != null) { ConsoleWindow.Title = $"BepInEx {Assembly.GetExecutingAssembly().GetName().Version} - {productNameProp.GetValue(null, null)}"; } Logger.Log(LogLevel.Message, "Chainloader started"); UnityEngine.Object.DontDestroyOnLoad(ManagerObject); string currentProcess = Process.GetCurrentProcess().ProcessName.ToLower(); var pluginTypes = TypeLoader.LoadTypes <BaseUnityPlugin>(Paths.PluginPath) .Where(plugin => { //Perform a filter for currently running process var filters = MetadataHelper.GetAttributes <BepInProcess>(plugin); if (!filters.Any()) { return(true); } return(filters.Any(x => x.ProcessName.ToLower().Replace(".exe", "") == currentProcess)); }) .ToList(); Logger.Log(LogLevel.Info, $"{pluginTypes.Count} plugins selected"); Dictionary <Type, IEnumerable <Type> > dependencyDict = new Dictionary <Type, IEnumerable <Type> >(); foreach (Type t in pluginTypes) { try { IEnumerable <Type> dependencies = MetadataHelper.GetDependencies(t, pluginTypes); dependencyDict[t] = dependencies; } catch (MissingDependencyException) { var metadata = MetadataHelper.GetMetadata(t); Logger.Log(LogLevel.Info, $"Cannot load [{metadata.Name}] due to missing dependencies."); } } pluginTypes = Utility.TopologicalSort(dependencyDict.Keys, x => dependencyDict[x]).ToList(); foreach (Type t in pluginTypes) { try { var metadata = MetadataHelper.GetMetadata(t); var plugin = (BaseUnityPlugin)ManagerObject.AddComponent(t); Plugins.Add(plugin); Logger.Log(LogLevel.Info, $"Loaded [{metadata.Name} {metadata.Version}]"); } catch (Exception ex) { Logger.Log(LogLevel.Info, $"Error loading [{t.Name}] : {ex.Message}"); } } } catch (Exception ex) { ConsoleWindow.Attach(); Console.WriteLine("Error occurred starting the game"); Console.WriteLine(ex.ToString()); } _loaded = true; }