diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index ac808df89..3ead8d5ea 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -785,6 +785,20 @@ internal partial class PluginManager : IDisposable, IServiceType { Log.Debug($"Installing plugin {repoManifest.Name} (testing={useTesting})"); + // If this plugin is in the default profile for whatever reason, delete the state + // If it was in multiple profiles and is still, the user uninstalled it and chose to keep it in there, + // or the user removed the plugin manually in which case we don't care + if (reason == PluginLoadReason.Installer) + { + // We don't need to apply, it doesn't matter + await this.profileManager.DefaultProfile.RemoveAsync(repoManifest.InternalName, false, false); + } + else + { + // If we are doing anything other than a fresh install, not having a workingPluginId is an error that must be fixed + Debug.Assert(inheritedWorkingPluginId != null, "inheritedWorkingPluginId != null"); + } + // Ensure that we have a testing opt-in for this plugin if we are installing a testing version if (useTesting && this.configuration.PluginTestingOptIns!.All(x => x.InternalName != repoManifest.InternalName)) { diff --git a/Dalamud/Plugin/Internal/Profiles/Profile.cs b/Dalamud/Plugin/Internal/Profiles/Profile.cs index ac46d9153..0b2d62ccf 100644 --- a/Dalamud/Plugin/Internal/Profiles/Profile.cs +++ b/Dalamud/Plugin/Internal/Profiles/Profile.cs @@ -200,17 +200,22 @@ internal class Profile /// /// The internal name of the plugin. /// Whether or not the current state should immediately be applied. + /// + /// Throw if certain operations are invalid. + /// * Throw if the plugin is not in this profile. + /// * If this is the default profile, check if we are in any other, then throw if we aren't. + /// /// A representing the asynchronous operation. - public async Task RemoveAsync(string internalName, bool apply = true) + public async Task RemoveAsync(string internalName, bool apply = true, bool guardrails = true) { ProfileModelV1.ProfileModelV1Plugin entry; lock (this) { entry = this.modelV1.Plugins.FirstOrDefault(x => x.InternalName == internalName); - if (entry == null) + if (entry == null && guardrails) throw new ArgumentException($"No plugin \"{internalName}\" in profile \"{this.Guid}\""); - if (!this.modelV1.Plugins.Remove(entry)) + if (!this.modelV1.Plugins.Remove(entry) && guardrails) throw new Exception("Couldn't remove plugin from model collection"); } @@ -221,7 +226,7 @@ internal class Profile { await this.manager.DefaultProfile.AddOrUpdateAsync(internalName, this.IsEnabled && entry.IsEnabled, false); } - else + else if (guardrails) { throw new Exception("Removed plugin from default profile, but wasn't in any other profile"); }