diff --git a/IPA.Loader/IPA.Loader.csproj b/IPA.Loader/IPA.Loader.csproj
index 0c83a962..15272b25 100644
--- a/IPA.Loader/IPA.Loader.csproj
+++ b/IPA.Loader/IPA.Loader.csproj
@@ -64,6 +64,7 @@
+
diff --git a/IPA.Loader/Loader/Features/DefineFeature.cs b/IPA.Loader/Loader/Features/DefineFeature.cs
index 15fffad0..092c90e4 100644
--- a/IPA.Loader/Loader/Features/DefineFeature.cs
+++ b/IPA.Loader/Loader/Features/DefineFeature.cs
@@ -7,7 +7,7 @@ namespace IPA.Loader.Features
{
public static bool NewFeature = true;
- internal override bool StoreOnPlugin => false;
+ protected internal override bool StoreOnPlugin => false;
public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters)
{ // parameters should be (name, fully qualified type)
diff --git a/IPA.Loader/Loader/Features/Feature.cs b/IPA.Loader/Loader/Features/Feature.cs
index ec84ec20..4b103b1b 100644
--- a/IPA.Loader/Loader/Features/Feature.cs
+++ b/IPA.Loader/Loader/Features/Feature.cs
@@ -69,7 +69,10 @@ namespace IPA.Loader.Features
/// the plugin to ensure is loaded.
protected void RequireLoaded(PluginLoader.PluginMetadata plugin) => PluginLoader.Load(plugin);
- internal virtual bool StoreOnPlugin => true;
+ ///
+ /// Defines whether or not this feature will be accessible from the plugin metadata once loaded.
+ ///
+ protected internal virtual bool StoreOnPlugin => true;
private static readonly Dictionary featureTypes = new Dictionary
{
diff --git a/IPA.Loader/Loader/Features/InitInjectorFeature.cs b/IPA.Loader/Loader/Features/InitInjectorFeature.cs
new file mode 100644
index 00000000..d4f069dc
--- /dev/null
+++ b/IPA.Loader/Loader/Features/InitInjectorFeature.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace IPA.Loader.Features
+{
+ internal class InitInjectorFeature : Feature
+ {
+ protected internal override bool StoreOnPlugin => false;
+
+ public override bool Initialize(PluginLoader.PluginMetadata meta, string[] parameters)
+ { // parameters should be (assembly qualified lookup type, [fully qualified type]:[method name])
+ // method should be static
+ if (parameters.Length != 2)
+ {
+ InvalidMessage = "Incorrect number of parameters";
+ return false;
+ }
+
+ RequireLoaded(meta);
+
+ var methodParts = parameters[1].Split(':');
+
+ var type = Type.GetType(parameters[0], false);
+ if (type == null)
+ {
+ InvalidMessage = $"Could not find type {parameters[0]}";
+ return false;
+ }
+
+ Type getType;
+ try
+ {
+ getType = meta.Assembly.GetType(methodParts[0]);
+ }
+ catch (ArgumentException)
+ {
+ InvalidMessage = $"Invalid type name {methodParts[0]}";
+ return false;
+ }
+ catch (Exception e) when (e is FileNotFoundException || e is FileLoadException || e is BadImageFormatException)
+ {
+ string filename;
+
+ switch (e)
+ {
+ case FileNotFoundException fn:
+ filename = fn.FileName;
+ goto hasFilename;
+ case FileLoadException fl:
+ filename = fl.FileName;
+ goto hasFilename;
+ case BadImageFormatException bi:
+ filename = bi.FileName;
+ hasFilename:
+ InvalidMessage = $"Could not find {filename} while loading type";
+ break;
+ default:
+ InvalidMessage = $"Error while loading type: {e}";
+ break;
+ }
+
+ return false;
+ }
+
+ MethodInfo method;
+ try
+ {
+ method = getType.GetMethod(methodParts[1], BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
+ null, new[]
+ {
+ typeof(object),
+ typeof(ParameterInfo),
+ typeof(PluginLoader.PluginMetadata)
+ }, new ParameterModifier[0]);
+ }
+ catch (Exception e)
+ {
+ InvalidMessage = $"Error while loading type: {e}";
+ return false;
+ }
+
+ if (method == null)
+ {
+ InvalidMessage = $"Could not find method {methodParts[1]} in type {methodParts[0]}";
+ return false;
+ }
+
+ try
+ {
+ var del = (PluginInitInjector.InjectParameter)Delegate.CreateDelegate(typeof(PluginInitInjector.InjectParameter), null, method);
+ PluginInitInjector.AddInjector(type, del);
+ return true;
+ }
+ catch (Exception e)
+ {
+ InvalidMessage = $"Error generated while creating delegate: {e}";
+ return false;
+ }
+ }
+ }
+}
diff --git a/IPA.Loader/Loader/manifest.json b/IPA.Loader/Loader/manifest.json
index 75855794..d754a56c 100644
--- a/IPA.Loader/Loader/manifest.json
+++ b/IPA.Loader/Loader/manifest.json
@@ -11,6 +11,7 @@
"define-feature(debug, IPA.Loader.Features.DebugFeature)",
"define-feature(warn, IPA.Loader.Features.WarnFeature)",
"define-feature(no-update, IPA.Loader.Features.NoUpdateFeature)",
- "define-feature(add-in, IPA.Loader.Features.AddInFeature)"
+ "define-feature(add-in, IPA.Loader.Features.AddInFeature)",
+ "define-feature(init-injector, IPA.Loader.Features.InitInjectorFeature)"
]
}
\ No newline at end of file