diff --git a/IPA.Loader/Loader/Features/Feature.cs b/IPA.Loader/Loader/Features/Feature.cs new file mode 100644 index 00000000..2c2d565a --- /dev/null +++ b/IPA.Loader/Loader/Features/Feature.cs @@ -0,0 +1,38 @@ +namespace IPA.Loader.Features +{ + /// + /// The root interface for a mod Feature. + /// + public abstract class Feature + { + /// + /// Initializes the feature with the parameters provided in the definition. + /// + /// Note: When no parenthesis are provided, is null. + /// + /// the metadata of the plugin that is being prepared + /// the parameters passed to the feature definition, or null + /// if the feature is valid for the plugin, otherwise + public abstract bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters); + + /// + /// Called before a plugin is loaded. + /// + /// the plugin about to be loaded + /// whether or not the plugin should be loaded + public virtual bool BeforeLoad(PluginLoader.PluginMetadata plugin) => true; + + /// + /// Called before a plugin's Init method is called. + /// + /// the plugin to be initialized + /// whether or not to call the Init method + public virtual bool BeforeInit(PluginLoader.PluginInfo plugin) => true; + + /// + /// Called after a plugin has been fully initialized, whether or not there is an Init method. + /// + /// the plugin that was just initialized + public virtual void AfterInit(PluginLoader.PluginInfo plugin) { } + } +} \ No newline at end of file diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 4e646cc7..3233d334 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -1,14 +1,15 @@ -using System; +using IPA.Config; +using IPA.Loader.Features; +using IPA.Logging; +using IPA.Utilities; +using Mono.Cecil; +using Newtonsoft.Json; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; -using IPA.Config; -using IPA.Logging; -using IPA.Utilities; -using Mono.Cecil; -using Newtonsoft.Json; using Version = SemVer.Version; namespace IPA.Loader @@ -34,33 +35,42 @@ namespace IPA.Loader /// The assembly the plugin was loaded from. /// public Assembly Assembly { get; internal set; } + /// /// The TypeDefinition for the main type of the plugin. /// public TypeDefinition PluginType { get; internal set; } + /// /// The human readable name of the plugin. /// public string Name { get; internal set; } + /// /// The ModSaber ID of the plugin, or null if it doesn't have one. /// public string Id { get; internal set; } + /// /// The version of the plugin. /// public Version Version { get; internal set; } + /// /// The file the plugin was loaded from. /// public FileInfo File { get; internal set; } + // ReSharper disable once UnusedAutoPropertyAccessor.Global /// /// The features this plugin requests. /// - public string[] Features { get; internal set; } + public IReadOnlyList Features => InternalFeatures; + + internal List InternalFeatures = new List(); private PluginManifest manifest; + internal PluginManifest Manifest { get => manifest; @@ -70,7 +80,6 @@ namespace IPA.Loader Name = value.Name; Version = value.Version; Id = value.Id; - Features = value.Features; } } @@ -84,6 +93,7 @@ namespace IPA.Loader public class PluginInfo { internal IBeatSaberPlugin Plugin { get; set; } + /// /// Metadata for the plugin. /// @@ -133,8 +143,8 @@ namespace IPA.Loader var pluginModule = AssemblyDefinition.ReadAssembly(plugin, new ReaderParameters { - ReadingMode = ReadingMode.Immediate, - ReadWrite = false + ReadingMode = ReadingMode.Immediate, + ReadWrite = false }).MainModule; var iBeatSaberPlugin = pluginModule.ImportReference(typeof(IBeatSaberPlugin)); @@ -186,7 +196,7 @@ namespace IPA.Loader internal static void Resolve() { // resolves duplicates and conflicts, etc PluginsMetadata.Sort((a, b) => a.Version.CompareTo(b.Version)); - + var ids = new HashSet(); var ignore = new HashSet(); var resolved = new List(PluginsMetadata.Count); @@ -284,7 +294,13 @@ namespace IPA.Loader PluginsMetadata = metadata; } - internal static PluginInfo LoadPlugin(PluginMetadata meta) + internal static void Load(PluginMetadata meta) + { + if (meta.Assembly == null) + meta.Assembly = Assembly.LoadFrom(meta.File.FullName); + } + + internal static PluginInfo InitPlugin(PluginMetadata meta) { if (meta.PluginType == null) return new PluginInfo() @@ -297,8 +313,7 @@ namespace IPA.Loader try { - Logger.loader.Debug(meta.File.FullName); - meta.Assembly = Assembly.LoadFrom(meta.File.FullName); + Load(meta); var type = meta.Assembly.GetType(meta.PluginType.FullName); var instance = (IBeatSaberPlugin)Activator.CreateInstance(type); @@ -361,11 +376,6 @@ namespace IPA.Loader return info; } - internal static List LoadPlugins() - { - var list = PluginsMetadata.Select(LoadPlugin).Where(p => p != null).ToList(); - - return list; - } + internal static List LoadPlugins() => PluginsMetadata.Select(InitPlugin).Where(p => p != null).ToList(); } } \ No newline at end of file