using BepInEx.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using BepInEx.Logging;
using UnityEngine;
using UnityInjector.ConsoleUtil;
using UnityLogWriter = BepInEx.Logging.UnityLogWriter;
namespace BepInEx.Bootstrap
{
///
/// The manager and loader for all plugins, and the entry point for BepInEx.
///
public class Chainloader
{
///
/// The loaded and initialized list of plugins.
///
public static List Plugins { get; protected set; } = new List();
///
/// The GameObject that all plugins are attached to as components.
///
public static GameObject ManagerObject { get; protected set; } = new GameObject("BepInEx_Manager");
private static bool _loaded = false;
///
/// The entry point for BepInEx, called on the very first LoadScene() from UnityEngine.
///
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);
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(Utility.PluginsDirectory)
.Where(plugin =>
{
//Perform a filter for currently running process
var filters = MetadataHelper.GetAttributes(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> dependencyDict = new Dictionary>();
foreach (Type t in pluginTypes)
{
try
{
IEnumerable 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;
}
}
}