diff --git a/BepInEx/Attributes.cs b/BepInEx/Attributes.cs
new file mode 100644
index 0000000..4334cd1
--- /dev/null
+++ b/BepInEx/Attributes.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace BepInEx
+{
+ [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; }
+
+ 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;
+ }
+ }
+}
diff --git a/BepInEx/BaseUnityPlugin.cs b/BepInEx/BaseUnityPlugin.cs
index 7341c58..670c322 100644
--- a/BepInEx/BaseUnityPlugin.cs
+++ b/BepInEx/BaseUnityPlugin.cs
@@ -8,19 +8,6 @@ namespace BepInEx
///
public abstract class BaseUnityPlugin : MonoBehaviour
{
- ///
- /// The unique identifier of the plugin. Should not change between plugin versions.
- ///
- public abstract string ID { get; }
- ///
- /// The user friendly name of the plugin. Is able to be changed between versions.
- ///
- public abstract string Name { get; }
-
- ///
- /// The specfic version of the plugin.
- ///
- public abstract Version Version { get; }
}
-}
+}
\ No newline at end of file
diff --git a/BepInEx/Chainloader.cs b/BepInEx/Chainloader.cs
index a95c1c6..ea7468f 100644
--- a/BepInEx/Chainloader.cs
+++ b/BepInEx/Chainloader.cs
@@ -50,7 +50,9 @@ namespace BepInEx
if (Directory.Exists(Utility.PluginsDirectory))
{
- var pluginTypes = LoadTypes(Utility.PluginsDirectory);
+ var pluginTypes = TypeLoader.LoadTypes(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;
}
- ///
- /// Checks all plugins to see if a plugin with a certain ID is loaded.
- ///
- /// The ID to check for.
- ///
- public static bool IsIDLoaded(string ID)
+ protected static IEnumerable TopologicalSort(
+ IEnumerable nodes,
+ Func> dependencySelector)
{
- foreach (var plugin in Plugins)
- if (plugin != null && plugin.enabled && plugin.ID == ID)
- return true;
- return false;
- }
+ List sorted_list = new List();
- ///
- /// Loads a list of types from a directory containing assemblies, that derive from a base type.
- ///
- /// The specfiic base type to search for.
- /// The directory to search for assemblies.
- /// Returns a list of found derivative types.
- public static List LoadTypes(string directory)
- {
- List types = new List();
- Type pluginType = typeof(T);
+ HashSet visited = new HashSet();
+ HashSet sorted = new HashSet();
- 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;
}
}
}
diff --git a/BepInEx/Config.cs b/BepInEx/Config.cs
index 27baf68..9932978 100644
--- a/BepInEx/Config.cs
+++ b/BepInEx/Config.cs
@@ -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
}
diff --git a/BepInEx/ConfigWrapper.cs b/BepInEx/ConfigWrapper.cs
index b8eebdc..0217fae 100644
--- a/BepInEx/ConfigWrapper.cs
+++ b/BepInEx/ConfigWrapper.cs
@@ -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)
diff --git a/BepInEx/Properties/AssemblyInfo.cs b/BepInEx/Properties/AssemblyInfo.cs
index c168196..0bd46e1 100644
--- a/BepInEx/Properties/AssemblyInfo.cs
+++ b/BepInEx/Properties/AssemblyInfo.cs
@@ -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")]
diff --git a/BepInEx/TypeLoader.cs b/BepInEx/TypeLoader.cs
new file mode 100644
index 0000000..9e366da
--- /dev/null
+++ b/BepInEx/TypeLoader.cs
@@ -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
+ {
+ ///
+ /// Loads a list of types from a directory containing assemblies, that derive from a base type.
+ ///
+ /// The specfiic base type to search for.
+ /// The directory to search for assemblies.
+ /// Returns a list of found derivative types.
+ public static IEnumerable LoadTypes(string directory)
+ {
+ List types = new List();
+ 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 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.refGUID);
+
+ if (dependencyType == null)
+ throw new Exception("Cannot find dependency type.");
+
+ dependencyTypes.Add(dependencyType);
+ }
+
+ return dependencyTypes;
+ }
+ }
+}