From 913d4732b5c64ead4aedb888d006a94cda006d9f Mon Sep 17 00:00:00 2001 From: goat Date: Tue, 14 May 2024 00:27:11 +0200 Subject: [PATCH] don't write to the manifest when reloading dev plugins(fixes #1328) genericizes the way WorkingPluginId is accessed away from the manifest, since we probably don't want to have it there in the future for regular plugins either --- .../Game/Addon/Events/AddonEventManager.cs | 8 ++-- .../PluginInstaller/PluginInstallerWindow.cs | 36 ++++++++-------- .../PluginInstaller/ProfileManagerWidget.cs | 6 +-- Dalamud/Plugin/DalamudPluginInterface.cs | 4 +- Dalamud/Plugin/Internal/PluginManager.cs | 30 +++++++------- .../Internal/Profiles/ProfileManager.cs | 6 +-- .../Plugin/Internal/Types/LocalDevPlugin.cs | 30 ++++++++++---- Dalamud/Plugin/Internal/Types/LocalPlugin.cs | 41 ++++++++----------- 8 files changed, 82 insertions(+), 79 deletions(-) diff --git a/Dalamud/Game/Addon/Events/AddonEventManager.cs b/Dalamud/Game/Addon/Events/AddonEventManager.cs index a9b9ef5fa..8af02ba70 100644 --- a/Dalamud/Game/Addon/Events/AddonEventManager.cs +++ b/Dalamud/Game/Addon/Events/AddonEventManager.cs @@ -221,7 +221,7 @@ internal class AddonEventManagerPluginScoped : IInternalDisposableService, IAddo { this.plugin = plugin; - this.eventManagerService.AddPluginEventController(plugin.Manifest.WorkingPluginId); + this.eventManagerService.AddPluginEventController(plugin.EffectiveWorkingPluginId); } /// @@ -233,16 +233,16 @@ internal class AddonEventManagerPluginScoped : IInternalDisposableService, IAddo this.eventManagerService.ResetCursor(); } - this.eventManagerService.RemovePluginEventController(this.plugin.Manifest.WorkingPluginId); + this.eventManagerService.RemovePluginEventController(this.plugin.EffectiveWorkingPluginId); } /// public IAddonEventHandle? AddEvent(IntPtr atkUnitBase, IntPtr atkResNode, AddonEventType eventType, IAddonEventManager.AddonEventHandler eventHandler) - => this.eventManagerService.AddEvent(this.plugin.Manifest.WorkingPluginId, atkUnitBase, atkResNode, eventType, eventHandler); + => this.eventManagerService.AddEvent(this.plugin.EffectiveWorkingPluginId, atkUnitBase, atkResNode, eventType, eventHandler); /// public void RemoveEvent(IAddonEventHandle eventHandle) - => this.eventManagerService.RemoveEvent(this.plugin.Manifest.WorkingPluginId, eventHandle); + => this.eventManagerService.RemoveEvent(this.plugin.EffectiveWorkingPluginId, eventHandle); /// public void SetCursor(AddonCursorType cursor) diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs index 40fa852cd..a4efb1f5e 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/PluginInstallerWindow.cs @@ -2438,7 +2438,7 @@ internal class PluginInstallerWindow : Window, IDisposable if (this.hasDevPlugins) { ImGuiHelpers.ScaledDummy(3); - ImGui.TextColored(ImGuiColors.DalamudGrey, $"WorkingPluginId: {manifest.WorkingPluginId}"); + ImGui.TextColored(ImGuiColors.DalamudGrey, $"WorkingPluginId: {plugin.EffectiveWorkingPluginId}"); ImGuiHelpers.ScaledDummy(3); } @@ -2621,10 +2621,10 @@ internal class PluginInstallerWindow : Window, IDisposable var applicableForProfiles = plugin.Manifest.SupportsProfiles /*&& !plugin.IsDev*/; var profilesThatWantThisPlugin = profileManager.Profiles - .Where(x => x.WantsPlugin(plugin.Manifest.WorkingPluginId) != null) + .Where(x => x.WantsPlugin(plugin.EffectiveWorkingPluginId) != null) .ToArray(); var isInSingleProfile = profilesThatWantThisPlugin.Length == 1; - var isDefaultPlugin = profileManager.IsInDefaultProfile(plugin.Manifest.WorkingPluginId); + var isDefaultPlugin = profileManager.IsInDefaultProfile(plugin.EffectiveWorkingPluginId); // Disable everything if the updater is running or another plugin is operating var disabled = this.updateStatus == OperationStatus.InProgress || this.installStatus == OperationStatus.InProgress; @@ -2659,17 +2659,17 @@ internal class PluginInstallerWindow : Window, IDisposable foreach (var profile in profileManager.Profiles.Where(x => !x.IsDefaultProfile)) { - var inProfile = profile.WantsPlugin(plugin.Manifest.WorkingPluginId) != null; + var inProfile = profile.WantsPlugin(plugin.EffectiveWorkingPluginId) != null; if (ImGui.Checkbox($"###profilePick{profile.Guid}{plugin.Manifest.InternalName}", ref inProfile)) { if (inProfile) { - Task.Run(() => profile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, true)) + Task.Run(() => profile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true)) .ContinueWith(this.DisplayErrorContinuation, Locs.Profiles_CouldNotAdd); } else { - Task.Run(() => profile.RemoveAsync(plugin.Manifest.WorkingPluginId)) + Task.Run(() => profile.RemoveAsync(plugin.EffectiveWorkingPluginId)) .ContinueWith(this.DisplayErrorContinuation, Locs.Profiles_CouldNotRemove); } } @@ -2689,11 +2689,11 @@ internal class PluginInstallerWindow : Window, IDisposable if (ImGuiComponents.IconButton(FontAwesomeIcon.Times)) { // TODO: Work this out - Task.Run(() => profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, plugin.IsLoaded, false)) + Task.Run(() => profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, plugin.IsLoaded, false)) .GetAwaiter().GetResult(); foreach (var profile in profileManager.Profiles.Where(x => !x.IsDefaultProfile && x.Plugins.Any(y => y.InternalName == plugin.Manifest.InternalName))) { - Task.Run(() => profile.RemoveAsync(plugin.Manifest.WorkingPluginId, false)) + Task.Run(() => profile.RemoveAsync(plugin.EffectiveWorkingPluginId, false)) .GetAwaiter().GetResult(); } @@ -2718,7 +2718,7 @@ internal class PluginInstallerWindow : Window, IDisposable if (ImGui.IsItemHovered()) ImGui.SetTooltip(Locs.PluginButtonToolTip_UnloadFailed); } - else if (this.enableDisableStatus == OperationStatus.InProgress && this.enableDisableWorkingPluginId == plugin.Manifest.WorkingPluginId) + else if (this.enableDisableStatus == OperationStatus.InProgress && this.enableDisableWorkingPluginId == plugin.EffectiveWorkingPluginId) { ImGuiComponents.DisabledToggleButton(toggleId, this.loadingIndicatorKind == LoadingIndicatorKind.EnablingSingle); } @@ -2743,9 +2743,9 @@ internal class PluginInstallerWindow : Window, IDisposable { // Reload the devPlugin manifest if it's a dev plugin // The plugin might rely on changed values in the manifest - if (plugin.IsDev) + if (plugin is LocalDevPlugin devPlugin) { - plugin.ReloadManifest(); + devPlugin.ReloadManifest(); } } catch (Exception ex) @@ -2761,13 +2761,13 @@ internal class PluginInstallerWindow : Window, IDisposable { this.enableDisableStatus = OperationStatus.InProgress; this.loadingIndicatorKind = LoadingIndicatorKind.DisablingSingle; - this.enableDisableWorkingPluginId = plugin.Manifest.WorkingPluginId; + this.enableDisableWorkingPluginId = plugin.EffectiveWorkingPluginId; Task.Run(async () => { await plugin.UnloadAsync(); await applicableProfile.AddOrUpdateAsync( - plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false); + plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false); notifications.AddNotification(Locs.Notifications_PluginDisabled(plugin.Manifest.Name), Locs.Notifications_PluginDisabledTitle, NotificationType.Success); }).ContinueWith(t => @@ -2782,9 +2782,9 @@ internal class PluginInstallerWindow : Window, IDisposable { this.enableDisableStatus = OperationStatus.InProgress; this.loadingIndicatorKind = LoadingIndicatorKind.EnablingSingle; - this.enableDisableWorkingPluginId = plugin.Manifest.WorkingPluginId; + this.enableDisableWorkingPluginId = plugin.EffectiveWorkingPluginId; - await applicableProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, true, false); + await applicableProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false); await plugin.LoadAsync(PluginLoadReason.Installer); notifications.AddNotification(Locs.Notifications_PluginEnabled(plugin.Manifest.Name), Locs.Notifications_PluginEnabledTitle, NotificationType.Success); @@ -2805,7 +2805,7 @@ internal class PluginInstallerWindow : Window, IDisposable if (shouldUpdate) { // We need to update the profile right here, because PM will not enable the plugin otherwise - await applicableProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, true, false); + await applicableProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false); await this.UpdateSinglePlugin(availableUpdate); } else @@ -3076,7 +3076,7 @@ internal class PluginInstallerWindow : Window, IDisposable if (localPlugin is LocalDevPlugin plugin) { var isInDefaultProfile = - Service.Get().IsInDefaultProfile(localPlugin.Manifest.WorkingPluginId); + Service.Get().IsInDefaultProfile(localPlugin.EffectiveWorkingPluginId); // https://colorswall.com/palette/2868/ var greenColor = new Vector4(0x5C, 0xB8, 0x5C, 0xFF) / 0xFF; @@ -3426,7 +3426,7 @@ internal class PluginInstallerWindow : Window, IDisposable this.pluginListAvailable.Sort((p1, p2) => p1.Name.CompareTo(p2.Name)); var profman = Service.Get(); - this.pluginListInstalled.Sort((p1, p2) => profman.IsInDefaultProfile(p1.Manifest.WorkingPluginId).CompareTo(profman.IsInDefaultProfile(p2.Manifest.WorkingPluginId))); + this.pluginListInstalled.Sort((p1, p2) => profman.IsInDefaultProfile(p1.EffectiveWorkingPluginId).CompareTo(profman.IsInDefaultProfile(p2.EffectiveWorkingPluginId))); break; default: throw new InvalidEnumArgumentException("Unknown plugin sort type."); diff --git a/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs b/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs index cac249abd..d0dc01ce5 100644 --- a/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs +++ b/Dalamud/Interface/Internal/Windows/PluginInstaller/ProfileManagerWidget.cs @@ -324,7 +324,7 @@ internal class ProfileManagerWidget if (ImGui.Selectable($"{plugin.Manifest.Name}{(plugin is LocalDevPlugin ? "(dev plugin)" : string.Empty)}###selector{plugin.Manifest.InternalName}")) { - Task.Run(() => profile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, true, false)) + Task.Run(() => profile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false)) .ContinueWith(this.installer.DisplayErrorContinuation, Locs.ErrorCouldNotChangeState); } } @@ -430,7 +430,7 @@ internal class ProfileManagerWidget foreach (var profileEntry in profile.Plugins.ToArray()) { didAny = true; - var pmPlugin = pm.InstalledPlugins.FirstOrDefault(x => x.Manifest.WorkingPluginId == profileEntry.WorkingPluginId); + var pmPlugin = pm.InstalledPlugins.FirstOrDefault(x => x.EffectiveWorkingPluginId == profileEntry.WorkingPluginId); var btnOffset = 2; if (pmPlugin != null) @@ -485,7 +485,7 @@ internal class ProfileManagerWidget FontAwesomeIcon.Check, "Yes, use this one")) { - profileEntry.WorkingPluginId = firstAvailableInstalled.Manifest.WorkingPluginId; + profileEntry.WorkingPluginId = firstAvailableInstalled.EffectiveWorkingPluginId; Task.Run(async () => { await profman.ApplyAllWantStatesAsync(); diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 7e224919a..d53c620f4 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -398,7 +398,7 @@ public sealed class DalamudPluginInterface : IDisposable if (currentConfig == null) return; - this.configs.Save(currentConfig, this.plugin.InternalName, this.plugin.Manifest.WorkingPluginId); + this.configs.Save(currentConfig, this.plugin.InternalName, this.plugin.EffectiveWorkingPluginId); } /// @@ -425,7 +425,7 @@ public sealed class DalamudPluginInterface : IDisposable } // this shouldn't be a thing, I think, but just in case - return this.configs.Load(this.plugin.InternalName, this.plugin.Manifest.WorkingPluginId); + return this.configs.Load(this.plugin.InternalName, this.plugin.EffectiveWorkingPluginId); } /// diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs index d64a3b9b0..7517ae413 100644 --- a/Dalamud/Plugin/Internal/PluginManager.cs +++ b/Dalamud/Plugin/Internal/PluginManager.cs @@ -1029,7 +1029,7 @@ internal class PluginManager : IInternalDisposableService { var plugin = metadata.InstalledPlugin; - var workingPluginId = metadata.InstalledPlugin.Manifest.WorkingPluginId; + var workingPluginId = metadata.InstalledPlugin.EffectiveWorkingPluginId; if (workingPluginId == Guid.Empty) throw new Exception("Existing plugin had no WorkingPluginId"); @@ -1331,16 +1331,16 @@ internal class PluginManager : IInternalDisposableService foreach (var installedPlugin in this.InstalledPlugins) { - if (installedPlugin.Manifest.WorkingPluginId == Guid.Empty) + if (installedPlugin.EffectiveWorkingPluginId == Guid.Empty) throw new Exception($"{(installedPlugin is LocalDevPlugin ? "DevPlugin" : "Plugin")} '{installedPlugin.Manifest.InternalName}' has an empty WorkingPluginId."); - if (seenIds.Contains(installedPlugin.Manifest.WorkingPluginId)) + if (seenIds.Contains(installedPlugin.EffectiveWorkingPluginId)) { throw new Exception( - $"{(installedPlugin is LocalDevPlugin ? "DevPlugin" : "Plugin")} '{installedPlugin.Manifest.InternalName}' has a duplicate WorkingPluginId '{installedPlugin.Manifest.WorkingPluginId}'"); + $"{(installedPlugin is LocalDevPlugin ? "DevPlugin" : "Plugin")} '{installedPlugin.Manifest.InternalName}' has a duplicate WorkingPluginId '{installedPlugin.EffectiveWorkingPluginId}'"); } - seenIds.Add(installedPlugin.Manifest.WorkingPluginId); + seenIds.Add(installedPlugin.EffectiveWorkingPluginId); } this.profileManager.ParanoiaValidateProfiles(); @@ -1388,7 +1388,7 @@ internal class PluginManager : IInternalDisposableService { // Only remove entries from the default profile that are NOT currently tied to an active LocalPlugin var guidsToRemove = this.profileManager.DefaultProfile.Plugins - .Where(x => this.InstalledPlugins.All(y => y.Manifest.WorkingPluginId != x.WorkingPluginId)) + .Where(x => this.InstalledPlugins.All(y => y.EffectiveWorkingPluginId != x.WorkingPluginId)) .Select(x => x.WorkingPluginId) .ToArray(); @@ -1560,9 +1560,9 @@ internal class PluginManager : IInternalDisposableService // This will also happen if you are installing a plugin with the installer, and that's intended! // It means that, if you have a profile which has unsatisfied plugins, installing a matching plugin will // enter it into the profiles it can match. - if (plugin.Manifest.WorkingPluginId == Guid.Empty) + if (plugin.EffectiveWorkingPluginId == Guid.Empty) throw new Exception("Plugin should have a WorkingPluginId at this point"); - this.profileManager.MigrateProfilesToGuidsForPlugin(plugin.Manifest.InternalName, plugin.Manifest.WorkingPluginId); + this.profileManager.MigrateProfilesToGuidsForPlugin(plugin.Manifest.InternalName, plugin.EffectiveWorkingPluginId); var wantedByAnyProfile = false; @@ -1573,7 +1573,7 @@ internal class PluginManager : IInternalDisposableService loadPlugin &= !isBoot; var wantsInDefaultProfile = - this.profileManager.DefaultProfile.WantsPlugin(plugin.Manifest.WorkingPluginId); + this.profileManager.DefaultProfile.WantsPlugin(plugin.EffectiveWorkingPluginId); if (wantsInDefaultProfile == null) { // We don't know about this plugin, so we don't want to do anything here. @@ -1582,7 +1582,7 @@ internal class PluginManager : IInternalDisposableService // Check if any profile wants this plugin. We need to do this here, since we want to allow loading a dev plugin if a non-default profile wants it active. // Note that this will not add the plugin to the default profile. That's done below in any other case. - wantedByAnyProfile = await this.profileManager.GetWantStateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false); + wantedByAnyProfile = await this.profileManager.GetWantStateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false); // If it is wanted by any other profile, we do want to load it. if (wantedByAnyProfile) @@ -1592,28 +1592,28 @@ internal class PluginManager : IInternalDisposableService { // We didn't want this plugin, and StartOnBoot is on. That means we don't want it and it should stay off until manually enabled. Log.Verbose("DevPlugin {Name} disabled and StartOnBoot => disable", plugin.Manifest.InternalName); - await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false); + await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false); loadPlugin = false; } else if (wantsInDefaultProfile == true && devPlugin.StartOnBoot) { // We wanted this plugin, and StartOnBoot is on. That means we actually do want it. Log.Verbose("DevPlugin {Name} enabled and StartOnBoot => enable", plugin.Manifest.InternalName); - await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, true, false); + await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, true, false); loadPlugin = !doNotLoad; } else if (wantsInDefaultProfile == true && !devPlugin.StartOnBoot) { // We wanted this plugin, but StartOnBoot is off. This means we don't want it anymore. Log.Verbose("DevPlugin {Name} enabled and !StartOnBoot => disable", plugin.Manifest.InternalName); - await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false); + await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false); loadPlugin = false; } else if (wantsInDefaultProfile == false && !devPlugin.StartOnBoot) { // We didn't want this plugin, and StartOnBoot is off. We don't want it. Log.Verbose("DevPlugin {Name} disabled and !StartOnBoot => disable", plugin.Manifest.InternalName); - await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, false, false); + await this.profileManager.DefaultProfile.AddOrUpdateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, false, false); loadPlugin = false; } @@ -1626,7 +1626,7 @@ internal class PluginManager : IInternalDisposableService // Plugins that aren't in any profile will be added to the default profile with this call. // We are skipping a double-lookup for dev plugins that are wanted by non-default profiles, as noted above. - wantedByAnyProfile = wantedByAnyProfile || await this.profileManager.GetWantStateAsync(plugin.Manifest.WorkingPluginId, plugin.Manifest.InternalName, defaultState); + wantedByAnyProfile = wantedByAnyProfile || await this.profileManager.GetWantStateAsync(plugin.EffectiveWorkingPluginId, plugin.Manifest.InternalName, defaultState); Log.Information("{Name} defaultState: {State} wantedByAnyProfile: {WantedByAny} loadPlugin: {LoadPlugin}", plugin.Manifest.InternalName, defaultState, wantedByAnyProfile, loadPlugin); if (loadPlugin) diff --git a/Dalamud/Plugin/Internal/Profiles/ProfileManager.cs b/Dalamud/Plugin/Internal/Profiles/ProfileManager.cs index d9c5ac787..e36e9908b 100644 --- a/Dalamud/Plugin/Internal/Profiles/ProfileManager.cs +++ b/Dalamud/Plugin/Internal/Profiles/ProfileManager.cs @@ -183,8 +183,8 @@ internal class ProfileManager : IServiceType var installedPlugin = pm.InstalledPlugins.FirstOrDefault(x => x.Manifest.InternalName == plugin.InternalName); if (installedPlugin != null) { - Log.Information("Satisfying plugin {InternalName} for profile {Name} with {Guid}", plugin.InternalName, newModel.Name, installedPlugin.Manifest.WorkingPluginId); - plugin.WorkingPluginId = installedPlugin.Manifest.WorkingPluginId; + Log.Information("Satisfying plugin {InternalName} for profile {Name} with {Guid}", plugin.InternalName, newModel.Name, installedPlugin.EffectiveWorkingPluginId); + plugin.WorkingPluginId = installedPlugin.EffectiveWorkingPluginId; } else { @@ -237,7 +237,7 @@ internal class ProfileManager : IServiceType var pm = Service.Get(); foreach (var installedPlugin in pm.InstalledPlugins) { - var wantThis = wantActive.Any(x => x.WorkingPluginId == installedPlugin.Manifest.WorkingPluginId); + var wantThis = wantActive.Any(x => x.WorkingPluginId == installedPlugin.EffectiveWorkingPluginId); switch (wantThis) { case true when !installedPlugin.IsLoaded: diff --git a/Dalamud/Plugin/Internal/Types/LocalDevPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalDevPlugin.cs index ab7b86021..f5fdbc663 100644 --- a/Dalamud/Plugin/Internal/Types/LocalDevPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalDevPlugin.cs @@ -50,14 +50,6 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable Log.Verbose("{InternalName} was assigned new devPlugin GUID {Guid}", this.InternalName, this.devSettings.WorkingPluginId); configuration.QueueSave(); } - - // If the ID in the manifest is wrong, force the good one - if (this.DevImposedWorkingPluginId != this.manifest.WorkingPluginId) - { - Debug.Assert(this.DevImposedWorkingPluginId != Guid.Empty, "Empty guid for devPlugin"); - this.manifest.WorkingPluginId = this.DevImposedWorkingPluginId; - this.SaveManifest("dev imposed working plugin id"); - } if (this.AutomaticReload) { @@ -99,7 +91,10 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable /// Gets an ID uniquely identifying this specific instance of a devPlugin. /// public Guid DevImposedWorkingPluginId => this.devSettings.WorkingPluginId; - + + /// + public override Guid EffectiveWorkingPluginId => this.DevImposedWorkingPluginId; + /// /// Gets a list of validation problems that have been dismissed by the user. /// @@ -148,6 +143,23 @@ internal class LocalDevPlugin : LocalPlugin, IDisposable } } + /// + /// Reload the manifest if it exists, to update possible changes. + /// + /// Thrown if the manifest could not be loaded. + public void ReloadManifest() + { + var manifestPath = LocalPluginManifest.GetManifestFile(this.DllFile); + if (manifestPath.Exists) + this.manifest = LocalPluginManifest.Load(manifestPath) ?? throw new Exception("Could not reload manifest."); + } + + /// + protected override void OnPreReload() + { + this.ReloadManifest(); + } + private void OnFileChanged(object sender, FileSystemEventArgs args) { var current = Interlocked.Increment(ref this.reloadCounter); diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index bca02a927..227a6c707 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -91,7 +91,7 @@ internal class LocalPlugin : IDisposable } // Create an installation instance ID for this plugin, if it doesn't have one yet - if (this.manifest.WorkingPluginId == Guid.Empty) + if (this.manifest.WorkingPluginId == Guid.Empty && !this.IsDev) { this.manifest.WorkingPluginId = Guid.NewGuid(); @@ -162,7 +162,7 @@ internal class LocalPlugin : IDisposable /// INCLUDES the default profile. /// public bool IsWantedByAnyProfile => - Service.Get().GetWantStateAsync(this.manifest.WorkingPluginId, this.Manifest.InternalName, false, false).GetAwaiter().GetResult(); + Service.Get().GetWantStateAsync(this.EffectiveWorkingPluginId, this.Manifest.InternalName, false, false).GetAwaiter().GetResult(); /// /// Gets a value indicating whether this plugin's API level is out of date. @@ -215,6 +215,11 @@ internal class LocalPlugin : IDisposable /// public Version EffectiveVersion => this.manifest.EffectiveVersion; + /// + /// Gets the effective working plugin ID for this plugin. + /// + public virtual Guid EffectiveWorkingPluginId => this.manifest.WorkingPluginId; + /// /// Gets the service scope for this plugin. /// @@ -271,11 +276,8 @@ internal class LocalPlugin : IDisposable await this.pluginLoadStateLock.WaitAsync(); try { - if (reloading && this.IsDev) - { - // Reload the manifest in-case there were changes here too. - this.ReloadManifest(); - } + if (reloading) + this.OnPreReload(); // If we reload a plugin we don't want to delete it. Makes sense, right? if (this.manifest.ScheduledForDeletion) @@ -578,24 +580,6 @@ internal class LocalPlugin : IDisposable this.SaveManifest("scheduling for deletion"); } - /// - /// Reload the manifest if it exists, preserve the internal Disabled state. - /// - public void ReloadManifest() - { - var manifestPath = LocalPluginManifest.GetManifestFile(this.DllFile); - if (manifestPath.Exists) - { - // Save some state that we do actually want to carry over - var guid = this.manifest.WorkingPluginId; - - this.manifest = LocalPluginManifest.Load(manifestPath) ?? throw new Exception("Could not reload manifest."); - this.manifest.WorkingPluginId = guid; - - this.SaveManifest("dev reload"); - } - } - /// /// Get the repository this plugin was installed from. /// @@ -620,6 +604,13 @@ internal class LocalPlugin : IDisposable /// /// Why it should be saved. protected void SaveManifest(string reason) => this.manifest.Save(this.manifestFile, reason); + + /// + /// Called before a plugin is reloaded. + /// + protected virtual void OnPreReload() + { + } private static void SetupLoaderConfig(LoaderConfig config) {