using System; using System.Collections.Generic; using System.Linq; namespace BepInEx { #region BaseUnityPlugin /// /// This attribute denotes that a class is a plugin, and specifies the required metadata. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class BepInPlugin : Attribute { /// /// The unique identifier of the plugin. Should not change between plugin versions. /// public string GUID { get; protected set; } /// /// The user friendly name of the plugin. Is able to be changed between versions. /// public string Name { get; protected set; } /// /// The specfic version of the plugin. /// public Version Version { get; protected set; } /// The unique identifier of the plugin. Should not change between plugin versions. /// The user friendly name of the plugin. Is able to be changed between versions. /// The specfic version of the plugin. public BepInPlugin(string GUID, string Name, string Version) { this.GUID = GUID; this.Name = Name; this.Version = new Version(Version); } } /// /// This attribute specifies any dependencies that this plugin has on other plugins. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class BepInDependency : Attribute { public enum DependencyFlags { /// /// The plugin has a hard dependency on the referenced plugin, and will not run without it. /// HardDependency = 1, /// /// This plugin has a soft dependency on the referenced plugin, and is able to run without it. /// SoftDependency = 2, } /// /// The GUID of the referenced plugin. /// public string DependencyGUID { get; protected set; } /// /// The flags associated with this dependency definition. /// public DependencyFlags Flags { get; protected set; } /// The GUID of the referenced plugin. /// The flags associated with this dependency definition. public BepInDependency(string DependencyGUID, DependencyFlags Flags = DependencyFlags.HardDependency) { this.DependencyGUID = DependencyGUID; this.Flags = Flags; } } /// /// This attribute specifies which processes this plugin should be run for. Not specifying this attribute will load the plugin under every process. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class BepInProcess : Attribute { /// /// The name of the process that this plugin will run under. /// public string ProcessName { get; protected set; } /// The name of the process that this plugin will run under. public BepInProcess(string ProcessName) { this.ProcessName = ProcessName; } } #endregion #region MetadataHelper /// /// Helper class to use for retrieving metadata about a plugin, defined as attributes. /// public static class MetadataHelper { /// /// Retrieves the BepInPlugin metadata from a plugin instance. /// /// The plugin instance. /// The BepInPlugin metadata of the plugin instance. public static BepInPlugin GetMetadata(object plugin) { return GetMetadata(plugin.GetType()); } /// /// Retrieves the BepInPlugin metadata from a plugin type. /// /// The plugin type. /// The BepInPlugin metadata of the plugin type. public static BepInPlugin GetMetadata(Type pluginType) { object[] attributes = pluginType.GetCustomAttributes(typeof(BepInPlugin), false); if (attributes.Length == 0) return null; return (BepInPlugin)attributes[0]; } /// /// Gets the specified attributes of an instance, if they exist. /// /// The attribute type to retrieve. /// The plugin instance. /// The attributes of the instance, if existing. public static IEnumerable GetAttributes(object plugin) where T : Attribute { return GetAttributes(plugin.GetType()); } /// /// Gets the specified attributes of a type, if they exist. /// /// The attribute type to retrieve. /// The plugin type. /// The attributes of the type, if existing. public static IEnumerable GetAttributes(Type pluginType) where T : Attribute { return pluginType.GetCustomAttributes(typeof(T), true).Cast(); } /// /// Retrieves the dependencies of the specified plugin type. /// /// The plugin type. /// All currently loaded plugin types. /// A list of all plugin types that the specified plugin type depends upon. public static IEnumerable GetDependencies(Type Plugin, IEnumerable AllPlugins) { object[] attributes = Plugin.GetCustomAttributes(typeof(BepInDependency), true); List dependencyTypes = new List(); foreach (BepInDependency dependency in attributes) { Type dependencyType = AllPlugins.FirstOrDefault(x => GetMetadata(x)?.GUID == dependency.DependencyGUID); if (dependencyType == null) { if ((dependency.Flags & BepInDependency.DependencyFlags.SoftDependency) != 0) continue; //skip on soft dependencies throw new MissingDependencyException("Cannot find dependency type."); } dependencyTypes.Add(dependencyType); } return dependencyTypes; } } /// /// An exception which is thrown when a plugin's dependencies cannot be found. /// public class MissingDependencyException : Exception { public MissingDependencyException(string message) : base(message) { } } #endregion }