diff --git a/IPA.Loader/Loader/PluginInitInjector.cs b/IPA.Loader/Loader/PluginInitInjector.cs
index 89556778..06196c33 100644
--- a/IPA.Loader/Loader/PluginInitInjector.cs
+++ b/IPA.Loader/Loader/PluginInitInjector.cs
@@ -13,7 +13,7 @@ using Net3_Proxy;
namespace IPA.Loader
{
///
- /// The type that handles value injecting into a plugin's Init.
+ /// The type that handles value injecting into a plugin's initialization methods.
///
public static class PluginInitInjector
{
diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs
index 7cfa36c0..c1aa84fd 100644
--- a/IPA.Loader/Loader/PluginLoader.cs
+++ b/IPA.Loader/Loader/PluginLoader.cs
@@ -29,7 +29,7 @@ namespace IPA.Loader
///
/// A type to manage the loading of plugins.
///
- public class PluginLoader
+ internal class PluginLoader
{
internal static Task LoadTask() =>
TaskEx.Run(() =>
@@ -201,7 +201,7 @@ namespace IPA.Loader
if (type.HasInterface(typeof(IPlugin).FullName))
{
Logger.loader.Warn("Interface-based plugin found");
- meta.RuntimeOptions = RuntimeOptions.SingleDynamicInit;
+ meta.IsAttributePlugin = false;
meta.PluginType = type;
return;
}
diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs
index 8dc54a24..2c4e4488 100644
--- a/IPA.Loader/Loader/PluginManager.cs
+++ b/IPA.Loader/Loader/PluginManager.cs
@@ -30,9 +30,6 @@ namespace IPA.Loader
{
#pragma warning disable CS0618 // Type or member is obsolete (IPlugin)
- ///
- /// An of new Beat Saber plugins
- ///
private static List _bsPlugins;
internal static IEnumerable BSMetas => _bsPlugins;
@@ -40,23 +37,15 @@ namespace IPA.Loader
/// Gets info about the plugin with the specified name.
///
/// the name of the plugin to get (must be an exact match)
- /// the plugin info for the requested plugin or null
+ /// the plugin metadata for the requested plugin or if it doesn't exist or is disabled
public static PluginMetadata GetPlugin(string name)
=> BSMetas.Select(p => p.Metadata).FirstOrDefault(p => p.Name == name);
- ///
- /// Gets info about the plugin with the specified ModSaber name.
- ///
- /// the ModSaber name of the plugin to get (must be an exact match)
- /// the plugin info for the requested plugin or null
- [Obsolete("Old name. Use GetPluginFromId instead.")]
- public static PluginMetadata GetPluginFromModSaberName(string name) => GetPluginFromId(name);
-
///
/// Gets info about the plugin with the specified ID.
///
/// the ID name of the plugin to get (must be an exact match)
- /// the plugin info for the requested plugin or null
+ /// the plugin metadata for the requested plugin or if it doesn't exist or is disabled
public static PluginMetadata GetPluginFromId(string name)
=> BSMetas.Select(p => p.Metadata).FirstOrDefault(p => p.Id == name);
@@ -245,7 +234,7 @@ namespace IPA.Loader
///
/// the plugin that was enabled
/// whether it needs a restart to take effect
- public delegate void PluginEnableDelegate(PluginInfo plugin, bool needsRestart);
+ public delegate void PluginEnableDelegate(PluginMetadata plugin, bool needsRestart);
///
/// An invoker for the event.
///
@@ -265,7 +254,7 @@ namespace IPA.Loader
///
/// Gets a list of all BSIPA plugins.
///
- /// a collection of all enabled plugins as s
+ /// a collection of all enabled plugins as s
public static IEnumerable AllPlugins => BSMetas.Select(p => p.Metadata);
/*
@@ -284,7 +273,7 @@ namespace IPA.Loader
*/
///
- /// An of old IPA plugins.
+ /// An of old IPA plugins.
///
/// all legacy plugin instances
[Obsolete("I mean, IPlugin shouldn't be used, so why should this? Not renaming to extend support for old plugins.")]
diff --git a/IPA.Loader/Loader/PluginMetadata.cs b/IPA.Loader/Loader/PluginMetadata.cs
index 71259d83..c6a4f2fa 100644
--- a/IPA.Loader/Loader/PluginMetadata.cs
+++ b/IPA.Loader/Loader/PluginMetadata.cs
@@ -82,7 +82,14 @@ namespace IPA.Loader
}
}
+ ///
+ /// The that the plugin specified in its .
+ ///
public RuntimeOptions RuntimeOptions { get; internal set; }
+ ///
+ /// Whether the plugin referred to by this metadata object is a BSIPA 4 attribute plugin.
+ ///
+ /// if the plugin is a BSIPA 4 plugin, if it is a BSIPA 3 plugin.
public bool IsAttributePlugin { get; internal set; } = false;
///
diff --git a/IPA.Loader/PluginInterfaces/Attributes/LifecycleAttributes.cs b/IPA.Loader/PluginInterfaces/Attributes/LifecycleAttributes.cs
index cb577c36..59ec24b5 100644
--- a/IPA.Loader/PluginInterfaces/Attributes/LifecycleAttributes.cs
+++ b/IPA.Loader/PluginInterfaces/Attributes/LifecycleAttributes.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace IPA
{
@@ -18,24 +14,84 @@ namespace IPA
// TODO: is there a better way to manage this mess?
+ ///
+ /// Indicates that the target method should be called when the plugin is enabled.
+ ///
+ ///
+ ///
+ /// This attribute is interchangable with , and is treated identically.
+ /// They are seperate to allow plugin code to more clearly describe the intent of the methods.
+ ///
+ ///
+ /// Typically, this will be used when the parameter of the plugins's
+ /// is .
+ ///
+ ///
+ ///
+ ///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnEnableAttribute : Attribute, IEdgeLifecycleAttribute
{
EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Enable;
}
+ ///
+ /// Indicates that the target method should be called when the game starts.
+ ///
+ ///
+ ///
+ /// This attribute is interchangable with , and is treated identically.
+ /// They are seperate to allow plugin code to more clearly describe the intent of the methods.
+ ///
+ ///
+ /// Typically, this will be used when the parameter of the plugins's
+ /// is .
+ ///
+ ///
+ ///
+ ///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnStartAttribute : Attribute, IEdgeLifecycleAttribute
{
EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Enable;
}
+ ///
+ /// Indicates that the target method should be called when the plugin is disabled.
+ ///
+ ///
+ ///
+ /// This attribute is interchangable with , and is treated identically.
+ /// They are seperate to allow plugin code to more clearly describe the intent of the methods.
+ ///
+ ///
+ /// Typically, this will be used when the parameter of the plugins's
+ /// is .
+ ///
+ ///
+ ///
+ ///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnDisableAttribute : Attribute, IEdgeLifecycleAttribute
{
EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Disable;
}
+ ///
+ /// Indicates that the target method should be called when the game exits.
+ ///
+ ///
+ ///
+ /// This attribute is interchangable with , and is treated identically.
+ /// They are seperate to allow plugin code to more clearly describe the intent of the methods.
+ ///
+ ///
+ /// Typically, this will be used when the parameter of the plugins's
+ /// is .
+ ///
+ ///
+ ///
+ ///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnExitAttribute : Attribute, IEdgeLifecycleAttribute
{
diff --git a/IPA.Loader/PluginInterfaces/Attributes/PluginAttribute.cs b/IPA.Loader/PluginInterfaces/Attributes/PluginAttribute.cs
index 44caf8f6..b39ceb22 100644
--- a/IPA.Loader/PluginInterfaces/Attributes/PluginAttribute.cs
+++ b/IPA.Loader/PluginInterfaces/Attributes/PluginAttribute.cs
@@ -1,32 +1,88 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using IPA.Loader;
+using System;
namespace IPA
{
+ ///
+ /// Marks a class as being a BSIPA plugin.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class PluginAttribute : Attribute
{
+ ///
+ /// The passed into the constructor of this attribute.
+ ///
// whenever this changes, PluginLoader.LoadMetadata must also change
public RuntimeOptions RuntimeOptions { get; }
+ ///
+ /// Initializes a with the given
+ /// to indicate the runtime capabilities of the plugin.
+ ///
+ /// the options to use for this plugin
public PluginAttribute(RuntimeOptions runtimeOptions)
{
RuntimeOptions = runtimeOptions;
}
}
+ ///
+ /// Options that a plugin must specify to describe how it expects to be run.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
// TODO: figure out a better name for this
public enum RuntimeOptions
{
+ ///
+ /// Indicates that this plugin expects to be initialized and enabled with the game, and disabled with the game.
+ ///
+ ///
+ /// With this option set, whether or not the plugin is disabled during a given run is constant for that entire run.
+ ///
SingleStartInit,
- DynamicInit,
-
- // TODO: do I want this?
- SingleDynamicInit
+ ///
+ /// Indicates that this plugin supports runtime enabling and disabling.
+ ///
+ ///
+ ///
+ /// When this is set, the plugin may be disabled at reasonable points during runtime. As with ,
+ /// it will be initialized and enabled with the game if it is enabled on startup, and disabled with the game if it is enabled
+ /// on shutdown.
+ ///
+ ///
+ /// When a plugin with this set is enabled mid-game, the first time it is enabled, its initialization methods will be called,
+ /// then its enable methods. All subsequent enables will NOT re-initialize, however the enable methods will be called.
+ ///
+ ///
+ /// When a plugin with this set is disabled mid-game, the plugin instance will NOT be destroyed, and will instead be
+ /// re-used for subsequent enables. The plugin is expected to handle this gracefully, and behave in a way that makes sense.
+ ///
+ ///
+ DynamicInit
}
+ ///
+ /// Marks a method or a constructor as an inialization method.
+ ///
+ ///
+ ///
+ /// If more than one constructor is marked with this attribute, the one with the most parameters, whether or not they can be injected, will be used.
+ ///
+ ///
+ /// Parameter injection is done with .
+ ///
+ ///
+ ///
+ ///
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
public sealed class InitAttribute : Attribute { }
}