diff --git a/BepInEx/Bootstrap/Chainloader.cs b/BepInEx/Bootstrap/Chainloader.cs
index babc88e..667a7e4 100644
--- a/BepInEx/Bootstrap/Chainloader.cs
+++ b/BepInEx/Bootstrap/Chainloader.cs
@@ -79,6 +79,44 @@ namespace BepInEx.Bootstrap
_initialized = true;
}
+ private static PluginInfo ToPluginInfo(TypeDefinition type)
+ {
+ if (type.IsInterface || type.IsAbstract || !type.IsSubtypeOf(typeof(BaseUnityPlugin)))
+ return null;
+
+ var metadata = BepInPlugin.FromCecilType(type);
+
+ if (metadata == null)
+ {
+ Logger.LogWarning($"Skipping over type [{type.Name}] as no metadata attribute is specified");
+ return null;
+ }
+
+ //Perform a filter for currently running process
+ var filters = BepInProcess.FromCecilType(type);
+
+ bool invalidProcessName = filters.Any(x => x.ProcessName.ToLower().Replace(".exe", "") == Paths.ProcessName);
+
+ if (invalidProcessName)
+ {
+ Logger.LogWarning($"Skipping over plugin [{metadata.GUID}] due to process filter");
+ return null;
+ }
+
+ var dependencies = BepInDependency.FromCecilType(type);
+
+ Logger.LogInfo($"Type path: {type.Module.FileName}");
+
+ return new PluginInfo
+ {
+ Metadata = metadata,
+ Processes = filters,
+ Dependencies = dependencies,
+ CecilType = type,
+ Location = type.Module.FileName
+ };
+ }
+
///
/// The entrypoint for the BepInEx plugin system.
///
@@ -108,7 +146,7 @@ namespace BepInEx.Bootstrap
UnityEngine.Object.DontDestroyOnLoad(ManagerObject);
- var pluginsToLoad = TypeLoader.FindPluginTypes(Paths.PluginPath);
+ var pluginsToLoad = TypeLoader.FindPluginTypes(Paths.PluginPath, ToPluginInfo);
var pluginInfos = pluginsToLoad.SelectMany(p => p.Value).ToList();
@@ -184,8 +222,8 @@ namespace BepInEx.Bootstrap
if (missingDependencies.Count != 0)
{
Logger.LogError($@"Missing the following dependencies for [{pluginInfo.Metadata.Name}]: {"\r\n"}{
- string.Join("\r\n", missingDependencies.Select(s => $"- {s}").ToArray())
- }{"\r\n"}Loading will be skipped; expect further errors and unstabilities.");
+ string.Join("\r\n", missingDependencies.Select(s => $"- {s}").ToArray())
+ }{"\r\n"}Loading will be skipped; expect further errors and unstabilities.");
invalidPlugins.Add(pluginGUID);
continue;
diff --git a/BepInEx/Bootstrap/TypeLoader.cs b/BepInEx/Bootstrap/TypeLoader.cs
index 3fab44a..ad2ab5f 100644
--- a/BepInEx/Bootstrap/TypeLoader.cs
+++ b/BepInEx/Bootstrap/TypeLoader.cs
@@ -16,13 +16,6 @@ namespace BepInEx.Bootstrap
///
public static class TypeLoader
{
- private static bool Is(this TypeDefinition self, Type td)
- {
- if (self.FullName == td.FullName)
- return true;
- return self.FullName != "System.Object" && (self.BaseType?.Resolve().Is(td) ?? false);
- }
-
private static DefaultAssemblyResolver resolver;
private static ReaderParameters readerParameters;
@@ -35,7 +28,9 @@ namespace BepInEx.Bootstrap
{
var name = new AssemblyName(reference.FullName);
- if (Utility.TryResolveDllAssembly(name, Paths.BepInExAssemblyDirectory, readerParameters, out AssemblyDefinition assembly) || Utility.TryResolveDllAssembly(name, Paths.PluginPath, readerParameters, out assembly) || Utility.TryResolveDllAssembly(name, Paths.ManagedPath, readerParameters, out assembly))
+ if (Utility.TryResolveDllAssembly(name, Paths.BepInExAssemblyDirectory, readerParameters, out AssemblyDefinition assembly) ||
+ Utility.TryResolveDllAssembly(name, Paths.PluginPath, readerParameters, out assembly) ||
+ Utility.TryResolveDllAssembly(name, Paths.ManagedPath, readerParameters, out assembly))
return assembly;
return null;
@@ -48,11 +43,9 @@ namespace BepInEx.Bootstrap
/// The specific base type to search for.
/// The directory to search for assemblies.
/// Returns a list of found derivative types.
- public static Dictionary> FindPluginTypes(string directory)
+ public static Dictionary> FindPluginTypes(string directory, Func typeSelector) where T : class
{
- var result = new Dictionary>();
- var pluginType = typeof(BaseUnityPlugin);
- string currentProcess = Process.GetCurrentProcess().ProcessName.ToLower();
+ var result = new Dictionary>();
foreach (string dll in Directory.GetFiles(Path.GetFullPath(directory), "*.dll", SearchOption.AllDirectories))
{
@@ -60,47 +53,15 @@ namespace BepInEx.Bootstrap
{
var ass = AssemblyDefinition.ReadAssembly(dll, readerParameters);
- var matchingTypes = ass.MainModule.Types.Where(t => !t.IsInterface && !t.IsAbstract && t.Is(pluginType)).ToList();
+ var matches = ass.MainModule.Types.Select(typeSelector).Where(t => t != null).ToList();
- if (matchingTypes.Count == 0)
- continue;
-
- var pluginInfos = new List();
-
- foreach (var pluginTypeDefinition in matchingTypes)
+ if (matches.Count == 0)
{
- var metadata = BepInPlugin.FromCecilType(pluginTypeDefinition);
-
- if (metadata == null)
- {
- Logger.LogWarning($"Skipping over type [{pluginTypeDefinition.Name}] as no metadata attribute is specified");
- continue;
- }
-
- //Perform a filter for currently running process
- var filters = BepInProcess.FromCecilType(pluginTypeDefinition);
-
- bool invalidProcessName = filters.Any(x => x.ProcessName.ToLower().Replace(".exe", "") == currentProcess);
-
- if (invalidProcessName)
- {
- Logger.LogInfo($"Skipping over plugin [{metadata.GUID}] due to process filter");
- continue;
- }
-
- var dependencies = BepInDependency.FromCecilType(pluginTypeDefinition);
-
- pluginInfos.Add(new PluginInfo
- {
- Metadata = metadata,
- Processes = filters,
- Dependencies = dependencies,
- CecilType = pluginTypeDefinition,
- Location = dll
- });
+ ass.Dispose();
+ continue;
}
- result[ass] = pluginInfos;
+ result[ass] = matches;
}
catch (Exception e)
{
diff --git a/BepInEx/Utility.cs b/BepInEx/Utility.cs
index 76373fd..0e922d0 100644
--- a/BepInEx/Utility.cs
+++ b/BepInEx/Utility.cs
@@ -25,7 +25,7 @@ namespace BepInEx
/// The string to parse
/// The value to return if parsing is unsuccessful.
/// Boolean value of input if able to be parsed, otherwise default value.
- public static bool SafeParseBool(string input, bool defaultValue = false) { return bool.TryParse(input, out bool result) ? result : defaultValue; }
+ public static bool SafeParseBool(string input, bool defaultValue = false) { return Boolean.TryParse(input, out bool result) ? result : defaultValue; }
///
/// Converts a file path into a UnityEngine.WWW format.
@@ -39,7 +39,7 @@ namespace BepInEx
///
/// The string to test.
/// True if the value parameter is null or empty, or if value consists exclusively of white-space characters.
- public static bool IsNullOrWhiteSpace(this string self) { return self == null || self.All(char.IsWhiteSpace); }
+ public static bool IsNullOrWhiteSpace(this string self) { return self == null || self.All(Char.IsWhiteSpace); }
public static IEnumerable TopologicalSort(IEnumerable nodes, Func> dependencySelector)
{
@@ -128,14 +128,21 @@ namespace BepInEx
return false;
}
+ public static bool IsSubtypeOf(this TypeDefinition self, Type td)
+ {
+ if (self.FullName == td.FullName)
+ return true;
+ return self.FullName != "System.Object" && (self.BaseType?.Resolve().IsSubtypeOf(td) ?? false);
+ }
+
///
- /// Try to resolve and load the given assembly DLL.
- ///
- /// Name of the assembly, of the type .
- /// Directory to search the assembly from.
- /// The loaded assembly.
- /// True, if the assembly was found and loaded. Otherwise, false.
- public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return TryResolveDllAssembly(assemblyName, directory, Assembly.LoadFile, out assembly); }
+ /// Try to resolve and load the given assembly DLL.
+ ///
+ /// Name of the assembly, of the type .
+ /// Directory to search the assembly from.
+ /// The loaded assembly.
+ /// True, if the assembly was found and loaded. Otherwise, false.
+ public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return TryResolveDllAssembly(assemblyName, directory, Assembly.LoadFile, out assembly); }
///
/// Try to resolve and load the given assembly DLL.