diff --git a/Dalamud.CorePlugin/PluginImpl.cs b/Dalamud.CorePlugin/PluginImpl.cs
index d6e472277..83dc32c97 100644
--- a/Dalamud.CorePlugin/PluginImpl.cs
+++ b/Dalamud.CorePlugin/PluginImpl.cs
@@ -17,16 +17,11 @@ namespace Dalamud.CorePlugin
// private Localization localizationManager;
- ///
- public string Name => "Dalamud.CorePlugin";
-
///
- /// Gets the plugin interface.
+ /// Initializes a new instance of the class.
///
- internal DalamudPluginInterface Interface { get; private set; }
-
- ///
- public void Initialize(DalamudPluginInterface pluginInterface)
+ /// Dalamud plugin interface.
+ public PluginImpl(DalamudPluginInterface pluginInterface)
{
try
{
@@ -38,8 +33,7 @@ namespace Dalamud.CorePlugin
this.Interface.UiBuilder.Draw += this.OnDraw;
this.Interface.UiBuilder.OpenConfigUi += this.OnOpenConfigUi;
- var commandManager = Service.Get();
- commandManager.AddHandler("/di", new(this.OnCommand) { HelpMessage = $"Access the {this.Name} plugin." });
+ Service.Get().AddHandler("/di", new(this.OnCommand) { HelpMessage = $"Access the {this.Name} plugin." });
}
catch (Exception ex)
{
@@ -47,10 +41,18 @@ namespace Dalamud.CorePlugin
}
}
+ ///
+ public string Name => "Dalamud.CorePlugin";
+
+ ///
+ /// Gets the plugin interface.
+ ///
+ internal DalamudPluginInterface Interface { get; private set; }
+
///
public void Dispose()
{
- this.Interface.CommandManager.RemoveHandler("/di");
+ Service.Get().RemoveHandler("/di");
this.Interface.UiBuilder.Draw -= this.OnDraw;
diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index 01e1a151d..838d5c7c8 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -91,10 +91,11 @@ namespace Dalamud
{
try
{
+ Service.Set();
+
// Initialize the process information.
Service.Set(new SigScanner(true));
Service.Set();
- Service.Set();
// Initialize FFXIVClientStructs function resolver
FFXIVClientStructs.Resolver.Initialize();
diff --git a/Dalamud/Game/ClientState/Conditions/Condition.cs b/Dalamud/Game/ClientState/Conditions/Condition.cs
index 5a4322532..4d679a180 100644
--- a/Dalamud/Game/ClientState/Conditions/Condition.cs
+++ b/Dalamud/Game/ClientState/Conditions/Condition.cs
@@ -1,10 +1,15 @@
using System;
+using Dalamud.IoC;
+using Dalamud.IoC.Internal;
+
namespace Dalamud.Game.ClientState.Conditions
{
///
/// Provides access to conditions (generally player state). You can check whether a player is in combat, mounted, etc.
///
+ [PluginInterface]
+ [InterfaceVersion("1.0")]
public class Condition
{
///
diff --git a/Dalamud/Game/ClientState/JobGauge/JobGauges.cs b/Dalamud/Game/ClientState/JobGauge/JobGauges.cs
index f3c836e10..958f78b1b 100644
--- a/Dalamud/Game/ClientState/JobGauge/JobGauges.cs
+++ b/Dalamud/Game/ClientState/JobGauge/JobGauges.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Reflection;
using Dalamud.Game.ClientState.JobGauge.Types;
+using Dalamud.IoC;
+using Dalamud.IoC.Internal;
using Serilog;
namespace Dalamud.Game.ClientState.JobGauge
@@ -10,6 +12,8 @@ namespace Dalamud.Game.ClientState.JobGauge
///
/// This class converts in-memory Job gauge data to structs.
///
+ [PluginInterface]
+ [InterfaceVersion("1.0")]
public class JobGauges
{
private Dictionary cache = new();
diff --git a/Dalamud/Game/Gui/GameGui.cs b/Dalamud/Game/Gui/GameGui.cs
index 6c65abf4b..1eaa9c60b 100644
--- a/Dalamud/Game/Gui/GameGui.cs
+++ b/Dalamud/Game/Gui/GameGui.cs
@@ -46,11 +46,10 @@ namespace Dalamud.Game.Gui
///
internal GameGui()
{
- this.address = new GameGuiAddressResolver(this.address.BaseAddress);
+ this.address = new GameGuiAddressResolver();
this.address.Setup();
Log.Verbose("===== G A M E G U I =====");
-
Log.Verbose($"GameGuiManager address 0x{this.address.BaseAddress.ToInt64():X}");
Log.Verbose($"SetGlobalBgm address 0x{this.address.SetGlobalBgm.ToInt64():X}");
Log.Verbose($"HandleItemHover address 0x{this.address.HandleItemHover.ToInt64():X}");
diff --git a/Dalamud/Game/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Gui/GameGuiAddressResolver.cs
index 52e98df6c..122a9eea2 100644
--- a/Dalamud/Game/Gui/GameGuiAddressResolver.cs
+++ b/Dalamud/Game/Gui/GameGuiAddressResolver.cs
@@ -11,10 +11,9 @@ namespace Dalamud.Game.Gui
///
/// Initializes a new instance of the class.
///
- /// The base address of the native GuiManager class.
- public GameGuiAddressResolver(IntPtr baseAddress)
+ public GameGuiAddressResolver()
{
- this.BaseAddress = baseAddress;
+ this.BaseAddress = Service.Get().Address.BaseAddress;
}
///
diff --git a/Dalamud/Interface/Internal/Scratchpad/ScratchExecutionManager.cs b/Dalamud/Interface/Internal/Scratchpad/ScratchExecutionManager.cs
index eba0b3d2a..cb3133951 100644
--- a/Dalamud/Interface/Internal/Scratchpad/ScratchExecutionManager.cs
+++ b/Dalamud/Interface/Internal/Scratchpad/ScratchExecutionManager.cs
@@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
-
+using Dalamud.IoC;
+using Dalamud.IoC.Internal;
using Dalamud.Plugin;
using ImGuiNET;
using Microsoft.CodeAnalysis.CSharp.Scripting;
@@ -79,13 +80,18 @@ namespace Dalamud.Interface.Internal.Scratchpad
{
var script = CSharpScript.Create(code, options);
- var pi = new DalamudPluginInterface("Scratch-" + doc.Id, PluginLoadReason.Unknown);
- var plugin = script.ContinueWith("return new ScratchPlugin() as IDalamudPlugin;")
+ var pluginType = script.ContinueWith("return typeof(ScratchPlugin);")
.RunAsync().GetAwaiter().GetResult().ReturnValue;
- plugin.Initialize(pi);
+ var pi = new DalamudPluginInterface($"Scratch-{doc.Id}", PluginLoadReason.Unknown);
- this.loadedScratches[doc.Id] = plugin;
+ var ioc = Service.Get();
+ var plugin = ioc.Create(pluginType, pi);
+
+ if (plugin == null)
+ throw new Exception("Could not initialize scratch plugin");
+
+ this.loadedScratches[doc.Id] = (IDalamudPlugin)plugin;
return ScratchLoadStatus.Success;
}
catch (CompilationErrorException ex)
diff --git a/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs b/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs
index 0a2e4e8fb..9ee145394 100644
--- a/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs
+++ b/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs
@@ -21,7 +21,7 @@ public class ScratchPlugin : IDalamudPlugin {
{SETUPBODY}
- public void Initialize(DalamudPluginInterface pluginInterface)
+ public ScratchPlugin(DalamudPluginInterface pluginInterface)
{
this.pi = pluginInterface;
diff --git a/Dalamud/Interface/Internal/Windows/DataWindow.cs b/Dalamud/Interface/Internal/Windows/DataWindow.cs
index d49ee8524..8fb88ef8a 100644
--- a/Dalamud/Interface/Internal/Windows/DataWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/DataWindow.cs
@@ -610,53 +610,6 @@ namespace Dalamud.Interface.Internal.Windows
private void DrawPluginIPC()
{
-#pragma warning disable CS0618 // Type or member is obsolete
- var i1 = new DalamudPluginInterface("DalamudTestSub", PluginLoadReason.Unknown);
- var i2 = new DalamudPluginInterface("DalamudTestPub", PluginLoadReason.Unknown);
-
- if (ImGui.Button("Add test sub"))
- {
- i1.Subscribe("DalamudTestPub", o =>
- {
- dynamic msg = o;
- Log.Debug(msg.Expand);
- });
- }
-
- if (ImGui.Button("Add test sub any"))
- {
- i1.SubscribeAny((o, a) =>
- {
- dynamic msg = a;
- Log.Debug($"From {o}: {msg.Expand}");
- });
- }
-
- if (ImGui.Button("Remove test sub"))
- i1.Unsubscribe("DalamudTestPub");
-
- if (ImGui.Button("Remove test sub any"))
- i1.UnsubscribeAny();
-
- if (ImGui.Button("Send test message"))
- {
- dynamic testMsg = new ExpandoObject();
- testMsg.Expand = "dong";
- i2.SendMessage(testMsg);
- }
-
- // This doesn't actually work, so don't mind it - impl relies on plugins being registered in PluginManager
- if (ImGui.Button("Send test message any"))
- {
- dynamic testMsg = new ExpandoObject();
- testMsg.Expand = "dong";
- i2.SendMessage("DalamudTestSub", testMsg);
- }
-
- var pluginManager = Service.Get();
- foreach (var ipc in pluginManager.IpcSubscriptions)
- ImGui.Text($"Source:{ipc.SourcePluginName} Sub:{ipc.SubPluginName}");
-#pragma warning restore CS0618 // Type or member is obsolete
}
private void DrawCondition()
diff --git a/Dalamud/IoC/Internal/ObjectInstance.cs b/Dalamud/IoC/Internal/ObjectInstance.cs
new file mode 100644
index 000000000..7475fcfaf
--- /dev/null
+++ b/Dalamud/IoC/Internal/ObjectInstance.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Reflection;
+
+namespace Dalamud.IoC.Internal
+{
+ ///
+ /// An object instance registered in the .
+ ///
+ internal class ObjectInstance
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The underlying instance.
+ public ObjectInstance(object instance)
+ {
+ this.Instance = new WeakReference(instance);
+ this.Version = instance.GetType().GetCustomAttribute();
+ }
+
+ ///
+ /// Gets the current version of the instance, if it exists.
+ ///
+ public InterfaceVersionAttribute? Version { get; }
+
+ ///
+ /// Gets a reference to the underlying instance.
+ ///
+ public WeakReference Instance { get; }
+ }
+}
diff --git a/Dalamud/IoC/Internal/ServiceContainer.cs b/Dalamud/IoC/Internal/ServiceContainer.cs
new file mode 100644
index 000000000..e1604c188
--- /dev/null
+++ b/Dalamud/IoC/Internal/ServiceContainer.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+using Serilog;
+
+namespace Dalamud.IoC.Internal
+{
+ ///
+ /// A simple singleton-only IOC container that provides (optional) version-based dependency resolution.
+ ///
+ internal class ServiceContainer : IServiceProvider
+ {
+ private readonly Dictionary instances = new();
+
+ ///
+ /// Register a singleton object of any type into the current IOC container.
+ ///
+ /// The existing instance to register in the container.
+ /// The interface to register.
+ public void RegisterSingleton(T instance)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException(nameof(instance));
+ }
+
+ this.instances[typeof(T)] = new(instance);
+ }
+
+ ///
+ /// Create an object.
+ ///
+ /// The type of object to create.
+ /// Scoped objects to be included in the constructor.
+ /// The created object.
+ public object? Create(Type objectType, params object[] scopedObjects)
+ {
+ var ctor = this.FindApplicableCtor(objectType, scopedObjects);
+ if (ctor == null)
+ {
+ Log.Error("Failed to create {TypeName}, unable to find any services to satisfy the dependencies in the ctor", objectType.FullName);
+ return null;
+ }
+
+ // validate dependency versions (if they exist)
+ var parameters = ctor.GetParameters().Select(p =>
+ {
+ var parameterType = p.ParameterType;
+ var requiredVersion = p.GetCustomAttribute(typeof(RequiredVersionAttribute)) as RequiredVersionAttribute;
+ return (parameterType, requiredVersion);
+ });
+
+ var versionCheck = parameters.Any(p =>
+ {
+ // if there's no required version, ignore it
+ if (p.requiredVersion == null)
+ return true;
+
+ // if there's no requested version, ignore it
+ var declVersion = p.parameterType.GetCustomAttribute();
+ if (declVersion == null)
+ return true;
+
+ if (declVersion.Version == p.requiredVersion.Version)
+ return true;
+
+ Log.Error(
+ "Requested version {ReqVersion} does not match the implemented version {ImplVersion} for param type {ParamType}",
+ p.requiredVersion.Version,
+ declVersion.Version,
+ p.parameterType.FullName);
+
+ return false;
+ });
+
+ if (!versionCheck)
+ {
+ Log.Error("Failed to create {TypeName}, a RequestedVersion could not be satisfied", objectType.FullName);
+ return null;
+ }
+
+ var resolvedParams = parameters
+ .Select(p =>
+ {
+ var service = this.GetService(p.parameterType, scopedObjects);
+
+ if (service == null)
+ {
+ Log.Error("Requested service type {TypeName} could not be satisfied", p.parameterType.FullName);
+ }
+
+ return service;
+ })
+ .ToArray();
+
+ var hasNull = resolvedParams.Any(p => p == null);
+ if (hasNull)
+ {
+ Log.Error("Failed to create {TypeName}, a requested service type could not be satisfied", objectType.FullName);
+ return null;
+ }
+
+ return Activator.CreateInstance(objectType, resolvedParams);
+ }
+
+ ///
+ object? IServiceProvider.GetService(Type serviceType) => this.GetService(serviceType);
+
+ private object? GetService(Type serviceType, object[] scopedObjects)
+ {
+ var singletonService = this.GetService(serviceType);
+ if (singletonService != null)
+ {
+ return singletonService;
+ }
+
+ // resolve dependency from scoped objects
+ var scoped = scopedObjects.FirstOrDefault(o => o.GetType() == serviceType);
+ if (scoped == default)
+ {
+ return null;
+ }
+
+ return scoped;
+ }
+
+ private object? GetService(Type serviceType)
+ {
+ var hasInstance = this.instances.TryGetValue(serviceType, out var service);
+ if (hasInstance && service.Instance.IsAlive)
+ {
+ return service.Instance.Target;
+ }
+
+ return null;
+ }
+
+ private ConstructorInfo? FindApplicableCtor(Type type, object[] scopedObjects)
+ {
+ // get a list of all the available types: scoped and singleton
+ var types = scopedObjects
+ .Select(o => o.GetType())
+ .Union(this.instances.Keys);
+
+ var ctors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var ctor in ctors)
+ {
+ var parameters = ctor.GetParameters();
+
+ var success = parameters.All(p => types.Contains(p.ParameterType));
+
+ if (success)
+ return ctor;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs
index e5494ea91..942e01b9c 100644
--- a/Dalamud/Plugin/DalamudPluginInterface.cs
+++ b/Dalamud/Plugin/DalamudPluginInterface.cs
@@ -39,22 +39,17 @@ namespace Dalamud.Plugin
internal DalamudPluginInterface(string pluginName, PluginLoadReason reason)
{
var configuration = Service.Get();
+ var dataManager = Service.Get();
var localization = Service.Get();
- this.CommandManager = Service.Get();
- this.Framework = Service.Get();
- this.ClientState = Service.Get();
this.UiBuilder = new UiBuilder(pluginName);
- this.TargetModuleScanner = Service.Get();
- this.Data = Service.Get();
- this.SeStringManager = Service.Get();
this.pluginName = pluginName;
this.configs = Service.Get().PluginConfigs;
this.Reason = reason;
this.GeneralChatType = configuration.GeneralChatType;
- this.Sanitizer = new Sanitizer(this.Data.Language);
+ this.Sanitizer = new Sanitizer(dataManager.Language);
if (configuration.LanguageOverride != null)
{
this.UiLanguage = configuration.LanguageOverride;
@@ -103,41 +98,11 @@ namespace Dalamud.Plugin
///
public FileInfo ConfigFile => this.configs.GetConfigFile(this.pluginName);
- ///
- /// Gets the CommandManager object that allows you to add and remove custom chat commands.
- ///
- public CommandManager CommandManager { get; private set; }
-
- ///
- /// Gets the ClientState object that allows you to access current client memory information like actors, territories, etc.
- ///
- public ClientState ClientState { get; private set; }
-
- ///
- /// Gets the Framework object that allows you to interact with the client.
- ///
- public Framework Framework { get; private set; }
-
///
/// Gets the instance which allows you to draw UI into the game via ImGui draw calls.
///
public UiBuilder UiBuilder { get; private set; }
- ///
- /// Gets the SigScanner instance targeting the main module of the FFXIV process.
- ///
- public SigScanner TargetModuleScanner { get; private set; }
-
- ///
- /// Gets the DataManager instance which allows you to access game data needed by the main dalamud features.
- ///
- public DataManager Data { get; private set; }
-
- ///
- /// Gets the SeStringManager instance which allows creating and parsing SeString payloads.
- ///
- public SeStringManager SeStringManager { get; private set; }
-
///
/// Gets a value indicating whether Dalamud is running in Debug mode or the /xldev menu is open. This can occur on release builds.
///
@@ -162,11 +127,6 @@ namespace Dalamud.Plugin
///
public XivChatType GeneralChatType { get; private set; }
- ///
- /// Gets the action that should be executed when any plugin sends a message.
- ///
- internal Action AnyPluginIpcAction { get; private set; }
-
#region Configuration
///
@@ -253,107 +213,6 @@ namespace Dalamud.Plugin
}
#endregion
- #region IPC
-
- ///
- /// Subscribe to an IPC message by any plugin.
- ///
- /// The action to take when a message was received.
- [Obsolete("The current IPC mechanism is obsolete and scheduled to be replaced after API level 3.")]
- public void SubscribeAny(Action action)
- {
- if (this.AnyPluginIpcAction != null)
- throw new InvalidOperationException("Can't subscribe multiple times.");
-
- this.AnyPluginIpcAction = action;
- }
-
- ///
- /// Subscribe to an IPC message by a plugin.
- ///
- /// The InternalName of the plugin to subscribe to.
- /// The action to take when a message was received.
- [Obsolete("The current IPC mechanism is obsolete and scheduled to be replaced after API level 3.")]
- public void Subscribe(string pluginName, Action action)
- {
- var pluginManager = Service.Get();
-
- if (pluginManager.IpcSubscriptions.Any(x => x.SourcePluginName == this.pluginName && x.SubPluginName == pluginName))
- throw new InvalidOperationException("Can't add multiple subscriptions for the same plugin.");
-
- pluginManager.IpcSubscriptions.Add(new(this.pluginName, pluginName, action));
- }
-
- ///
- /// Unsubscribe from messages from any plugin.
- ///
- [Obsolete("The current IPC mechanism is obsolete and scheduled to be replaced after API level 3.")]
- public void UnsubscribeAny()
- {
- if (this.AnyPluginIpcAction == null)
- throw new InvalidOperationException("Wasn't subscribed to this plugin.");
-
- this.AnyPluginIpcAction = null;
- }
-
- ///
- /// Unsubscribe from messages from a plugin.
- ///
- /// The InternalName of the plugin to unsubscribe from.
- [Obsolete("The current IPC mechanism is obsolete and scheduled to be replaced after API level 3.")]
- public void Unsubscribe(string pluginName)
- {
- var pluginManager = Service.Get();
-
- var sub = pluginManager.IpcSubscriptions.FirstOrDefault(x => x.SourcePluginName == this.pluginName && x.SubPluginName == pluginName);
- if (sub.SubAction == null)
- throw new InvalidOperationException("Wasn't subscribed to this plugin.");
-
- pluginManager.IpcSubscriptions.Remove(sub);
- }
-
- ///
- /// Send a message to all subscribed plugins.
- ///
- /// The message to send.
- [Obsolete("The current IPC mechanism is obsolete and scheduled to be replaced after API level 3.")]
- public void SendMessage(ExpandoObject message)
- {
- var pluginManager = Service.Get();
-
- var subs = pluginManager.IpcSubscriptions.Where(x => x.SubPluginName == this.pluginName);
- foreach (var sub in subs.Select(x => x.SubAction))
- {
- sub.Invoke(message);
- }
- }
-
- ///
- /// Send a message to a specific plugin.
- ///
- /// The InternalName of the plugin to send the message to.
- /// The message to send.
- /// True if the corresponding plugin was present and received the message.
- [Obsolete("The current IPC mechanism is obsolete and scheduled to be replaced after API level 3.")]
- public bool SendMessage(string pluginName, ExpandoObject message)
- {
- var pluginManager = Service.Get();
-
- var plugin = pluginManager.InstalledPlugins.FirstOrDefault(x => x.Manifest.InternalName == pluginName);
-
- if (plugin == default)
- return false;
-
- if (plugin.DalamudInterface?.AnyPluginIpcAction == null)
- return false;
-
- plugin.DalamudInterface.AnyPluginIpcAction.Invoke(this.pluginName, message);
-
- return true;
- }
-
- #endregion
-
///
/// Unregister your plugin and dispose all references. You have to call this when your IDalamudPlugin is disposed.
///
diff --git a/Dalamud/Plugin/IDalamudPlugin.cs b/Dalamud/Plugin/IDalamudPlugin.cs
index aff863eac..51d67328d 100644
--- a/Dalamud/Plugin/IDalamudPlugin.cs
+++ b/Dalamud/Plugin/IDalamudPlugin.cs
@@ -11,11 +11,5 @@ namespace Dalamud.Plugin
/// Gets the name of the plugin.
///
string Name { get; }
-
- ///
- /// Initializes a Dalamud plugin.
- ///
- /// The needed to access various Dalamud objects.
- void Initialize(DalamudPluginInterface pluginInterface);
}
}
diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs
index 80983ab2c..7c3c9ef25 100644
--- a/Dalamud/Plugin/Internal/LocalPlugin.cs
+++ b/Dalamud/Plugin/Internal/LocalPlugin.cs
@@ -5,6 +5,7 @@ using System.Reflection;
using Dalamud.Configuration.Internal;
using Dalamud.Game;
+using Dalamud.IoC.Internal;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Exceptions;
using Dalamud.Plugin.Internal.Types;
@@ -26,15 +27,15 @@ namespace Dalamud.Plugin.Internal
private PluginLoader loader;
private Assembly pluginAssembly;
- private Type pluginType;
- private IDalamudPlugin instance;
+ private Type? pluginType;
+ private IDalamudPlugin? instance;
///
/// Initializes a new instance of the class.
///
/// Path to the DLL file.
/// The plugin manifest.
- public LocalPlugin(FileInfo dllFile, LocalPluginManifest?manifest)
+ public LocalPlugin(FileInfo dllFile, LocalPluginManifest? manifest)
{
this.DllFile = dllFile;
this.State = PluginState.Unloaded;
@@ -264,8 +265,16 @@ namespace Dalamud.Plugin.Internal
// Update the location for the Location and CodeBase patches
PluginManager.PluginLocations[this.pluginType.Assembly.FullName] = new(this.DllFile);
- // Instantiate and initialize
- this.instance = Activator.CreateInstance(this.pluginType) as IDalamudPlugin;
+ this.DalamudInterface = new DalamudPluginInterface(this.pluginAssembly.GetName().Name!, reason);
+
+ var ioc = Service.Get();
+ this.instance = ioc.Create(this.pluginType, this.DalamudInterface) as IDalamudPlugin;
+ if (this.instance == null)
+ {
+ this.State = PluginState.LoadError;
+ Log.Error($"Error while loading {this.Name}, failed to bind and call the plugin constructor");
+ return;
+ }
// In-case the manifest name was a placeholder. Can occur when no manifest was included.
if (this.instance.Name != this.Manifest.Name)
@@ -274,30 +283,6 @@ namespace Dalamud.Plugin.Internal
this.Manifest.Save(this.manifestFile);
}
- this.DalamudInterface = new DalamudPluginInterface(this.pluginAssembly.GetName().Name, reason);
-
- if (this.IsDev)
- {
- // Inherit LPL's AssemblyLocation functionality
- try
- {
- var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
-
- this.instance.GetType()
- ?.GetProperty("AssemblyLocation", bindingFlags)
- ?.SetValue(this.instance, this.DllFile.FullName);
- this.instance.GetType()
- ?.GetMethod("SetLocation", bindingFlags)
- ?.Invoke(this.instance, new object[] { this.DllFile.FullName });
- }
- catch
- {
- // Ignored
- }
- }
-
- this.instance.Initialize(this.DalamudInterface);
-
this.State = PluginState.Loaded;
Log.Information($"Finished loading {this.DllFile.Name}");
}