mirror of
https://github.com/BepInEx/BepInEx.git
synced 2026-10-20 01:46:13 +00:00
Use attributes instead of abstract properties for metadata
This commit is contained in:
1 parent
0ac964a7ce
commit
2cc67b441b
7 files changed
+170
-62
No files matched your search
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
|
||||
namespace BepInEx
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class BepInPlugin : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique identifier of the plugin. Should not change between plugin versions.
|
||||
/// </summary>
|
||||
public string GUID { get; protected set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The user friendly name of the plugin. Is able to be changed between versions.
|
||||
/// </summary>
|
||||
public string Name { get; protected set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The specfic version of the plugin.
|
||||
/// </summary>
|
||||
public Version Version { get; protected set; }
|
||||
|
||||
public BepInPlugin(string GUID, string Name, Version Version)
|
||||
{
|
||||
this.GUID = GUID;
|
||||
this.Name = Name;
|
||||
this.Version = Version;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class BepInDependency : Attribute
|
||||
{
|
||||
public enum DependencyFlags
|
||||
{
|
||||
HardDependency = 1,
|
||||
SoftDependency = 2
|
||||
}
|
||||
|
||||
public string refGUID { get; protected set; }
|
||||
|
||||
public DependencyFlags Flags { get; protected set; }
|
||||
|
||||
public BepInDependency(string refGUID, DependencyFlags Flags = DependencyFlags.HardDependency)
|
||||
{
|
||||
this.refGUID = refGUID;
|
||||
this.Flags = Flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,19 +8,6 @@ namespace BepInEx
|
||||
/// </summary>
|
||||
public abstract class BaseUnityPlugin : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique identifier of the plugin. Should not change between plugin versions.
|
||||
/// </summary>
|
||||
public abstract string ID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The user friendly name of the plugin. Is able to be changed between versions.
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The specfic version of the plugin.
|
||||
/// </summary>
|
||||
public abstract Version Version { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-42
@@ -50,7 +50,9 @@ namespace BepInEx
|
||||
|
||||
if (Directory.Exists(Utility.PluginsDirectory))
|
||||
{
|
||||
var pluginTypes = LoadTypes<BaseUnityPlugin>(Utility.PluginsDirectory);
|
||||
var pluginTypes = TypeLoader.LoadTypes<BaseUnityPlugin>(Utility.PluginsDirectory).ToList();
|
||||
|
||||
pluginTypes = TopologicalSort(pluginTypes, x => TypeLoader.GetDependencies(x, pluginTypes)).ToList();
|
||||
|
||||
BepInLogger.Log($"{pluginTypes.Count} plugins found");
|
||||
|
||||
@@ -58,7 +60,10 @@ namespace BepInEx
|
||||
{
|
||||
try
|
||||
{
|
||||
var metadata = TypeLoader.GetMetadata(t);
|
||||
|
||||
var plugin = (BaseUnityPlugin)ManagerObject.AddComponent(t);
|
||||
|
||||
Plugins.Add(plugin);
|
||||
BepInLogger.Log($"Loaded [{plugin.Name}]");
|
||||
}
|
||||
@@ -80,58 +85,39 @@ namespace BepInEx
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks all plugins to see if a plugin with a certain ID is loaded.
|
||||
/// </summary>
|
||||
/// <param name="ID">The ID to check for.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsIDLoaded(string ID)
|
||||
protected static IEnumerable<TNode> TopologicalSort<TNode>(
|
||||
IEnumerable<TNode> nodes,
|
||||
Func<TNode, IEnumerable<TNode>> dependencySelector)
|
||||
{
|
||||
foreach (var plugin in Plugins)
|
||||
if (plugin != null && plugin.enabled && plugin.ID == ID)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
List<TNode> sorted_list = new List<TNode>();
|
||||
|
||||
/// <summary>
|
||||
/// Loads a list of types from a directory containing assemblies, that derive from a base type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The specfiic 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 List<Type> LoadTypes<T>(string directory)
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
Type pluginType = typeof(T);
|
||||
HashSet<TNode> visited = new HashSet<TNode>();
|
||||
HashSet<TNode> sorted = new HashSet<TNode>();
|
||||
|
||||
foreach (string dll in Directory.GetFiles(Path.GetFullPath(directory), "*.dll"))
|
||||
foreach (TNode input in nodes)
|
||||
Visit(input);
|
||||
|
||||
return sorted_list;
|
||||
|
||||
void Visit(TNode node)
|
||||
{
|
||||
try
|
||||
if (visited.Contains(node))
|
||||
{
|
||||
AssemblyName an = AssemblyName.GetAssemblyName(dll);
|
||||
Assembly assembly = Assembly.Load(an);
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
if (type.IsInterface || type.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type.BaseType == pluginType)
|
||||
types.Add(type);
|
||||
}
|
||||
}
|
||||
if (!sorted.Contains(node))
|
||||
throw new Exception("Cyclic Dependency");
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
else
|
||||
{
|
||||
visited.Add(node);
|
||||
|
||||
foreach (var dep in dependencySelector(node))
|
||||
Visit(dep);
|
||||
|
||||
sorted.Add(node);
|
||||
sorted_list.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -203,17 +203,17 @@ namespace BepInEx
|
||||
|
||||
public static string GetEntry(this BaseUnityPlugin plugin, string key, string defaultValue = "")
|
||||
{
|
||||
return GetEntry(key, defaultValue, plugin.ID);
|
||||
return GetEntry(key, defaultValue, TypeLoader.GetMetadata(plugin).GUID);
|
||||
}
|
||||
|
||||
public static void SetEntry(this BaseUnityPlugin plugin, string key, string value)
|
||||
{
|
||||
SetEntry(key, value, plugin.ID);
|
||||
SetEntry(key, value, TypeLoader.GetMetadata(plugin).GUID);
|
||||
}
|
||||
|
||||
public static bool HasEntry(this BaseUnityPlugin plugin, string key)
|
||||
{
|
||||
return HasEntry(key, plugin.ID);
|
||||
return HasEntry(key, TypeLoader.GetMetadata(plugin).GUID);
|
||||
}
|
||||
#endregion Extensions
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace BepInEx
|
||||
|
||||
public ConfigWrapper(string key, BaseUnityPlugin plugin, T @default = default(T)) : this(key, @default)
|
||||
{
|
||||
Section = plugin.ID;
|
||||
Section = TypeLoader.GetMetadata(plugin).GUID;
|
||||
}
|
||||
|
||||
public ConfigWrapper(string key, string section, T @default = default(T)) : this(key, @default)
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("3.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("3.0.0.0")]
|
||||
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace BepInEx
|
||||
{
|
||||
public static class TypeLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads a list of types from a directory containing assemblies, that derive from a base type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The specfiic 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 IEnumerable<Type> LoadTypes<T>(string directory)
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
Type pluginType = typeof(T);
|
||||
|
||||
foreach (string dll in Directory.GetFiles(Path.GetFullPath(directory), "*.dll"))
|
||||
{
|
||||
try
|
||||
{
|
||||
AssemblyName an = AssemblyName.GetAssemblyName(dll);
|
||||
Assembly assembly = Assembly.Load(an);
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
if (type.IsInterface || type.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type.BaseType == pluginType)
|
||||
types.Add(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (BadImageFormatException) { }
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
public static BepInPlugin GetMetadata(object Plugin)
|
||||
{
|
||||
return GetMetadata(Plugin.GetType());
|
||||
}
|
||||
|
||||
public static BepInPlugin GetMetadata(Type PluginType)
|
||||
{
|
||||
object[] attributes = PluginType.GetCustomAttributes(typeof(BepInPlugin), false);
|
||||
|
||||
if (attributes.Length == 0)
|
||||
return null;
|
||||
|
||||
return (BepInPlugin)attributes[0];
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetDependencies(Type Plugin, IEnumerable<Type> AllPlugins)
|
||||
{
|
||||
object[] attributes = Plugin.GetCustomAttributes(typeof(BepInDependency), true);
|
||||
|
||||
List<Type> dependencyTypes = new List<Type>();
|
||||
|
||||
foreach (BepInDependency dependency in attributes)
|
||||
{
|
||||
Type dependencyType = AllPlugins.FirstOrDefault(x => GetMetadata(x)?.GUID == dependency.refGUID);
|
||||
|
||||
if (dependencyType == null)
|
||||
throw new Exception("Cannot find dependency type.");
|
||||
|
||||
dependencyTypes.Add(dependencyType);
|
||||
}
|
||||
|
||||
return dependencyTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user