Browse Source

Documentation

4.0.0-beta
Anairkoen Schno 4 years ago
parent
commit
9705692cbf
6 changed files with 140 additions and 32 deletions
  1. +1
    -1
      IPA.Loader/Loader/PluginInitInjector.cs
  2. +2
    -2
      IPA.Loader/Loader/PluginLoader.cs
  3. +5
    -16
      IPA.Loader/Loader/PluginManager.cs
  4. +7
    -0
      IPA.Loader/Loader/PluginMetadata.cs
  5. +60
    -4
      IPA.Loader/PluginInterfaces/Attributes/LifecycleAttributes.cs
  6. +65
    -9
      IPA.Loader/PluginInterfaces/Attributes/PluginAttribute.cs

+ 1
- 1
IPA.Loader/Loader/PluginInitInjector.cs View File

@ -13,7 +13,7 @@ using Net3_Proxy;
namespace IPA.Loader namespace IPA.Loader
{ {
/// <summary> /// <summary>
/// The type that handles value injecting into a plugin's Init.
/// The type that handles value injecting into a plugin's initialization methods.
/// </summary> /// </summary>
public static class PluginInitInjector public static class PluginInitInjector
{ {


+ 2
- 2
IPA.Loader/Loader/PluginLoader.cs View File

@ -29,7 +29,7 @@ namespace IPA.Loader
/// <summary> /// <summary>
/// A type to manage the loading of plugins. /// A type to manage the loading of plugins.
/// </summary> /// </summary>
public class PluginLoader
internal class PluginLoader
{ {
internal static Task LoadTask() => internal static Task LoadTask() =>
TaskEx.Run(() => TaskEx.Run(() =>
@ -201,7 +201,7 @@ namespace IPA.Loader
if (type.HasInterface(typeof(IPlugin).FullName)) if (type.HasInterface(typeof(IPlugin).FullName))
{ {
Logger.loader.Warn("Interface-based plugin found"); Logger.loader.Warn("Interface-based plugin found");
meta.RuntimeOptions = RuntimeOptions.SingleDynamicInit;
meta.IsAttributePlugin = false;
meta.PluginType = type; meta.PluginType = type;
return; return;
} }


+ 5
- 16
IPA.Loader/Loader/PluginManager.cs View File

@ -30,9 +30,6 @@ namespace IPA.Loader
{ {
#pragma warning disable CS0618 // Type or member is obsolete (IPlugin) #pragma warning disable CS0618 // Type or member is obsolete (IPlugin)
/// <summary>
/// An <see cref="IEnumerable"/> of new Beat Saber plugins
/// </summary>
private static List<PluginExecutor> _bsPlugins; private static List<PluginExecutor> _bsPlugins;
internal static IEnumerable<PluginExecutor> BSMetas => _bsPlugins; internal static IEnumerable<PluginExecutor> BSMetas => _bsPlugins;
@ -40,23 +37,15 @@ namespace IPA.Loader
/// Gets info about the plugin with the specified name. /// Gets info about the plugin with the specified name.
/// </summary> /// </summary>
/// <param name="name">the name of the plugin to get (must be an exact match)</param> /// <param name="name">the name of the plugin to get (must be an exact match)</param>
/// <returns>the plugin info for the requested plugin or null</returns>
/// <returns>the plugin metadata for the requested plugin or <see langword="null"/> if it doesn't exist or is disabled</returns>
public static PluginMetadata GetPlugin(string name) public static PluginMetadata GetPlugin(string name)
=> BSMetas.Select(p => p.Metadata).FirstOrDefault(p => p.Name == name); => BSMetas.Select(p => p.Metadata).FirstOrDefault(p => p.Name == name);
/// <summary>
/// Gets info about the plugin with the specified ModSaber name.
/// </summary>
/// <param name="name">the ModSaber name of the plugin to get (must be an exact match)</param>
/// <returns>the plugin info for the requested plugin or null</returns>
[Obsolete("Old name. Use GetPluginFromId instead.")]
public static PluginMetadata GetPluginFromModSaberName(string name) => GetPluginFromId(name);
/// <summary> /// <summary>
/// Gets info about the plugin with the specified ID. /// Gets info about the plugin with the specified ID.
/// </summary> /// </summary>
/// <param name="name">the ID name of the plugin to get (must be an exact match)</param> /// <param name="name">the ID name of the plugin to get (must be an exact match)</param>
/// <returns>the plugin info for the requested plugin or null</returns>
/// <returns>the plugin metadata for the requested plugin or <see langword="null"/> if it doesn't exist or is disabled</returns>
public static PluginMetadata GetPluginFromId(string name) public static PluginMetadata GetPluginFromId(string name)
=> BSMetas.Select(p => p.Metadata).FirstOrDefault(p => p.Id == name); => BSMetas.Select(p => p.Metadata).FirstOrDefault(p => p.Id == name);
@ -245,7 +234,7 @@ namespace IPA.Loader
/// </summary> /// </summary>
/// <param name="plugin">the plugin that was enabled</param> /// <param name="plugin">the plugin that was enabled</param>
/// <param name="needsRestart">whether it needs a restart to take effect</param> /// <param name="needsRestart">whether it needs a restart to take effect</param>
public delegate void PluginEnableDelegate(PluginInfo plugin, bool needsRestart);
public delegate void PluginEnableDelegate(PluginMetadata plugin, bool needsRestart);
/// <summary> /// <summary>
/// An invoker for the <see cref="PluginDisabled"/> event. /// An invoker for the <see cref="PluginDisabled"/> event.
/// </summary> /// </summary>
@ -265,7 +254,7 @@ namespace IPA.Loader
/// <summary> /// <summary>
/// Gets a list of all BSIPA plugins. /// Gets a list of all BSIPA plugins.
/// </summary> /// </summary>
/// <value>a collection of all enabled plugins as <see cref="PluginInfo"/>s</value>
/// <value>a collection of all enabled plugins as <see cref="PluginMetadata"/>s</value>
public static IEnumerable<PluginMetadata> AllPlugins => BSMetas.Select(p => p.Metadata); public static IEnumerable<PluginMetadata> AllPlugins => BSMetas.Select(p => p.Metadata);
/* /*
@ -284,7 +273,7 @@ namespace IPA.Loader
*/ */
/// <summary> /// <summary>
/// An <see cref="IEnumerable"/> of old IPA plugins.
/// An <see cref="IEnumerable{T}"/> of old IPA plugins.
/// </summary> /// </summary>
/// <value>all legacy plugin instances</value> /// <value>all legacy plugin instances</value>
[Obsolete("I mean, IPlugin shouldn't be used, so why should this? Not renaming to extend support for old plugins.")] [Obsolete("I mean, IPlugin shouldn't be used, so why should this? Not renaming to extend support for old plugins.")]


+ 7
- 0
IPA.Loader/Loader/PluginMetadata.cs View File

@ -82,7 +82,14 @@ namespace IPA.Loader
} }
} }
/// <summary>
/// The <see cref="IPA.RuntimeOptions"/> that the plugin specified in its <see cref="PluginAttribute"/>.
/// </summary>
public RuntimeOptions RuntimeOptions { get; internal set; } public RuntimeOptions RuntimeOptions { get; internal set; }
/// <summary>
/// Whether the plugin referred to by this metadata object is a BSIPA 4 attribute plugin.
/// </summary>
/// <value><see langword="true"/> if the plugin is a BSIPA 4 plugin, <see langword="false"/> if it is a BSIPA 3 plugin.</value>
public bool IsAttributePlugin { get; internal set; } = false; public bool IsAttributePlugin { get; internal set; } = false;
/// <summary> /// <summary>


+ 60
- 4
IPA.Loader/PluginInterfaces/Attributes/LifecycleAttributes.cs View File

@ -1,8 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IPA namespace IPA
{ {
@ -18,24 +14,84 @@ namespace IPA
// TODO: is there a better way to manage this mess? // TODO: is there a better way to manage this mess?
/// <summary>
/// Indicates that the target method should be called when the plugin is enabled.
/// </summary>
/// <remarks>
/// <para>
/// This attribute is interchangable with <see cref="OnStartAttribute"/>, and is treated identically.
/// They are seperate to allow plugin code to more clearly describe the intent of the methods.
/// </para>
/// <para>
/// Typically, this will be used when the <see cref="RuntimeOptions"/> parameter of the plugins's
/// <see cref="PluginAttribute"/> is <see cref="RuntimeOptions.DynamicInit"/>.
/// </para>
/// </remarks>
/// <seealso cref="PluginAttribute"/>
/// <seealso cref="OnStartAttribute"/>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnEnableAttribute : Attribute, IEdgeLifecycleAttribute public sealed class OnEnableAttribute : Attribute, IEdgeLifecycleAttribute
{ {
EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Enable; EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Enable;
} }
/// <summary>
/// Indicates that the target method should be called when the game starts.
/// </summary>
/// <remarks>
/// <para>
/// This attribute is interchangable with <see cref="OnEnableAttribute"/>, and is treated identically.
/// They are seperate to allow plugin code to more clearly describe the intent of the methods.
/// </para>
/// <para>
/// Typically, this will be used when the <see cref="RuntimeOptions"/> parameter of the plugins's
/// <see cref="PluginAttribute"/> is <see cref="RuntimeOptions.SingleStartInit"/>.
/// </para>
/// </remarks>
/// <seealso cref="PluginAttribute"/>
/// <seealso cref="OnEnableAttribute"/>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnStartAttribute : Attribute, IEdgeLifecycleAttribute public sealed class OnStartAttribute : Attribute, IEdgeLifecycleAttribute
{ {
EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Enable; EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Enable;
} }
/// <summary>
/// Indicates that the target method should be called when the plugin is disabled.
/// </summary>
/// <remarks>
/// <para>
/// This attribute is interchangable with <see cref="OnExitAttribute"/>, and is treated identically.
/// They are seperate to allow plugin code to more clearly describe the intent of the methods.
/// </para>
/// <para>
/// Typically, this will be used when the <see cref="RuntimeOptions"/> parameter of the plugins's
/// <see cref="PluginAttribute"/> is <see cref="RuntimeOptions.DynamicInit"/>.
/// </para>
/// </remarks>
/// <seealso cref="PluginAttribute"/>
/// <seealso cref="OnExitAttribute"/>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnDisableAttribute : Attribute, IEdgeLifecycleAttribute public sealed class OnDisableAttribute : Attribute, IEdgeLifecycleAttribute
{ {
EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Disable; EdgeLifecycleType IEdgeLifecycleAttribute.Type => EdgeLifecycleType.Disable;
} }
/// <summary>
/// Indicates that the target method should be called when the game exits.
/// </summary>
/// <remarks>
/// <para>
/// This attribute is interchangable with <see cref="OnDisableAttribute"/>, and is treated identically.
/// They are seperate to allow plugin code to more clearly describe the intent of the methods.
/// </para>
/// <para>
/// Typically, this will be used when the <see cref="RuntimeOptions"/> parameter of the plugins's
/// <see cref="PluginAttribute"/> is <see cref="RuntimeOptions.SingleStartInit"/>.
/// </para>
/// </remarks>
/// <seealso cref="PluginAttribute"/>
/// <seealso cref="OnDisableAttribute"/>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnExitAttribute : Attribute, IEdgeLifecycleAttribute public sealed class OnExitAttribute : Attribute, IEdgeLifecycleAttribute
{ {


+ 65
- 9
IPA.Loader/PluginInterfaces/Attributes/PluginAttribute.cs View File

@ -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 namespace IPA
{ {
/// <summary>
/// Marks a class as being a BSIPA plugin.
/// </summary>
/// <seealso cref="InitAttribute"/>
/// <seealso cref="OnEnableAttribute"/>
/// <seealso cref="OnDisableAttribute"/>
/// <seealso cref="OnStartAttribute"/>
/// <seealso cref="OnExitAttribute"/>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class PluginAttribute : Attribute public sealed class PluginAttribute : Attribute
{ {
/// <summary>
/// The <see cref="IPA.RuntimeOptions"/> passed into the constructor of this attribute.
/// </summary>
// whenever this changes, PluginLoader.LoadMetadata must also change // whenever this changes, PluginLoader.LoadMetadata must also change
public RuntimeOptions RuntimeOptions { get; } public RuntimeOptions RuntimeOptions { get; }
/// <summary>
/// Initializes a <see cref="PluginAttribute"/> with the given <see cref="IPA.RuntimeOptions"/>
/// to indicate the runtime capabilities of the plugin.
/// </summary>
/// <param name="runtimeOptions">the options to use for this plugin</param>
public PluginAttribute(RuntimeOptions runtimeOptions) public PluginAttribute(RuntimeOptions runtimeOptions)
{ {
RuntimeOptions = runtimeOptions; RuntimeOptions = runtimeOptions;
} }
} }
/// <summary>
/// Options that a plugin must specify to describe how it expects to be run.
/// </summary>
/// <seealso cref="PluginAttribute"/>
/// <seealso cref="InitAttribute"/>
/// <seealso cref="OnEnableAttribute"/>
/// <seealso cref="OnDisableAttribute"/>
/// <seealso cref="OnStartAttribute"/>
/// <seealso cref="OnExitAttribute"/>
// TODO: figure out a better name for this // TODO: figure out a better name for this
public enum RuntimeOptions public enum RuntimeOptions
{ {
/// <summary>
/// Indicates that this plugin expects to be initialized and enabled with the game, and disabled with the game.
/// </summary>
/// <remarks>
/// With this option set, whether or not the plugin is disabled during a given run is constant for that entire run.
/// </remarks>
SingleStartInit, SingleStartInit,
DynamicInit,
// TODO: do I want this?
SingleDynamicInit
/// <summary>
/// Indicates that this plugin supports runtime enabling and disabling.
/// </summary>
/// <remarks>
/// <para>
/// When this is set, the plugin may be disabled at reasonable points during runtime. As with <see cref="SingleStartInit"/>,
/// 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.
/// </para>
/// <para>
/// 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 <b>NOT</b> re-initialize, however the enable methods will be called.
/// </para>
/// <para>
/// When a plugin with this set is disabled mid-game, the plugin instance will <b>NOT</b> 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.
/// </para>
/// </remarks>
DynamicInit
} }
/// <summary>
/// Marks a method or a constructor as an inialization method.
/// </summary>
/// <remarks>
/// <para>
/// 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.
/// </para>
/// <para>
/// Parameter injection is done with <see cref="PluginInitInjector"/>.
/// </para>
/// </remarks>
/// <seealso cref="PluginAttribute"/>
/// <seealso cref="PluginInitInjector"/>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
public sealed class InitAttribute : Attribute { } public sealed class InitAttribute : Attribute { }
} }

Loading…
Cancel
Save