mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Make TypeLoader generic loader
This commit is contained in:
1 parent
e1f7382d97
commit
a89ae05e40
3 files changed
+67
-61
No files matched your search
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The entrypoint for the BepInEx plugin system.
|
||||
/// </summary>
|
||||
@@ -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;
|
||||
|
||||
@@ -16,13 +16,6 @@ namespace BepInEx.Bootstrap
|
||||
/// </summary>
|
||||
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
|
||||
/// <typeparam name="T">The specific base type to search for.</typeparam>
|
||||
/// <param name="directory">The directory to search for assemblies.</param>
|
||||
/// <returns>Returns a list of found derivative types.</returns>
|
||||
public static Dictionary<AssemblyDefinition, IEnumerable<PluginInfo>> FindPluginTypes(string directory)
|
||||
public static Dictionary<AssemblyDefinition, IEnumerable<T>> FindPluginTypes<T>(string directory, Func<TypeDefinition, T> typeSelector) where T : class
|
||||
{
|
||||
var result = new Dictionary<AssemblyDefinition, IEnumerable<PluginInfo>>();
|
||||
var pluginType = typeof(BaseUnityPlugin);
|
||||
string currentProcess = Process.GetCurrentProcess().ProcessName.ToLower();
|
||||
var result = new Dictionary<AssemblyDefinition, IEnumerable<T>>();
|
||||
|
||||
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<PluginInfo>();
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
+16
-9
@@ -25,7 +25,7 @@ namespace BepInEx
|
||||
/// <param name="input">The string to parse</param>
|
||||
/// <param name="defaultValue">The value to return if parsing is unsuccessful.</param>
|
||||
/// <returns>Boolean value of input if able to be parsed, otherwise default value.</returns>
|
||||
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; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts a file path into a UnityEngine.WWW format.
|
||||
@@ -39,7 +39,7 @@ namespace BepInEx
|
||||
/// </summary>
|
||||
/// <param name="self">The string to test.</param>
|
||||
/// <returns>True if the value parameter is null or empty, or if value consists exclusively of white-space characters.</returns>
|
||||
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<TNode> TopologicalSort<TNode>(IEnumerable<TNode> nodes, Func<TNode, IEnumerable<TNode>> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to resolve and load the given assembly DLL.
|
||||
/// </summary>
|
||||
/// <param name="assemblyName">Name of the assembly, of the type <see cref="AssemblyName" />.</param>
|
||||
/// <param name="directory">Directory to search the assembly from.</param>
|
||||
/// <param name="assembly">The loaded assembly.</param>
|
||||
/// <returns>True, if the assembly was found and loaded. Otherwise, false.</returns>
|
||||
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.
|
||||
/// </summary>
|
||||
/// <param name="assemblyName">Name of the assembly, of the type <see cref="AssemblyName" />.</param>
|
||||
/// <param name="directory">Directory to search the assembly from.</param>
|
||||
/// <param name="assembly">The loaded assembly.</param>
|
||||
/// <returns>True, if the assembly was found and loaded. Otherwise, false.</returns>
|
||||
public static bool TryResolveDllAssembly(AssemblyName assemblyName, string directory, out Assembly assembly) { return TryResolveDllAssembly(assemblyName, directory, Assembly.LoadFile, out assembly); }
|
||||
|
||||
/// <summary>
|
||||
/// Try to resolve and load the given assembly DLL.
|
||||
|
||||
Reference in new issue
Block a user