/// <summary> /// Whenever a plugin fails to load, suggests disabling it. /// </summary> private static void LoadPlugins_SuggestDisable([NotNull] FileInfo file, [NotNull] DisabledPlugins disabledplugins, [NotNull] string sError, [CanBeNull] IWin32Window owner) { if (file == null) { throw new ArgumentNullException("file"); } if (disabledplugins == null) { throw new ArgumentNullException("disabledplugins"); } if (sError.IsEmpty()) { throw new ArgumentNullException("sError"); } // Plugin name, error text, question var sb = new StringBuilder(); string displayname = AssemblyNameToPluginDisplayName(file); sb.AppendFormat(Stringtable.MessageBoxPluginCouldNotBeLoaded, displayname); sb.AppendLine(); sb.AppendLine(); sb.AppendLine(sError); sb.AppendLine(); sb.AppendFormat(Stringtable.MessageBoxDisableFailedPlugin, displayname); // Confirm if (MessageBox.Show(owner, sb.ToString(), Stringtable.MessageBoxFailedPluginTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) { disabledplugins.Add(Path.GetFileNameWithoutExtension(file.FullName)); // Disable } }
public void Apply() { foreach (var plugin in Core.Plugins) { plugin.Value.Enabled = !DisabledPlugins.Contains(plugin.Key); } PluginManager.Core.Docking.Refresh(); if (UIStyle != null && StyleManager.Style != UIStyle) { StyleManager.Style = UIStyle; } }
/// <summary> /// Looks up Omea Plugin assembly files, loads them, instantiates the plugin classes, calls their <see cref="IPlugin.Register"/>, all on the calling thread. /// </summary> public void LoadPlugins() { var disabledplugins = new DisabledPlugins(); // Collect to get the full count for the progress before we start loading the DLLs/types var plugins = new List <PossiblyPluginFileInfo>(); foreach (PossiblyPluginFileInfo file in GetAllPluginFiles()) { if (!file.IsPlugin) { continue; // Need plugins only } // Disabled plugin? Check by the DLL name if (!disabledplugins.Contains(Path.GetFileNameWithoutExtension(file.File.FullName))) { plugins.Add(file); } } // Load! var progressWindow = (SplashScreen)Core.ProgressWindow; for (int nFile = 0; nFile < plugins.Count; nFile++) { if (progressWindow != null) { progressWindow.UpdateProgress((nFile + 1) * 100 / plugins.Count, Stringtable.LoadingPluginsProgressMessage, null); // Progress after the current file before we process it (at the beginning, accomodate for collecting the files; at the and, let see the 100% fill for some time) } // Try loading string sError; if (!LoadPlugins_LoadFile(plugins[nFile], out sError)) { // Failed, report the error _mapPluginLoadRuntimeErrors[plugins[nFile].File.FullName] = sError; // Overwrite old Core.ReportBackgroundException(new ApplicationException(sError)); // Disable the failed plugin? LoadPlugins_SuggestDisable(plugins[nFile].File, disabledplugins, sError, progressWindow); } else { _mapPluginLoadRuntimeErrors.Remove(plugins[nFile].File.FullName); // Clean the error record } } // Apply declarative plugin settings LoadPlugins_XmlConfiguration(); // Types without supporting plugins LoadPlugins_MarkUnloadedResourceTypes(); }
internal static Task CommitTransaction(StateTransitionTransaction transaction) { if (!transaction.HasStateChanged) { return(Task.WhenAll()); } if (!UnityGame.OnMainThread) { var transactionCopy = transaction.Clone(); transaction.Dispose(); return(UnityMainThreadTaskScheduler.Factory.StartNew(() => CommitTransaction(transactionCopy)).Unwrap()); } lock (commitTransactionLockObject) { if (transaction.CurrentlyEnabled.Except(EnabledPlugins) .Concat(EnabledPlugins.Except(transaction.CurrentlyEnabled)).Any() || transaction.CurrentlyDisabled.Except(DisabledPlugins) .Concat(DisabledPlugins.Except(transaction.CurrentlyDisabled)).Any()) { // ensure that the transaction's base state reflects the current state, otherwise throw transaction.Dispose(); throw new InvalidOperationException("Transaction no longer resembles the current state of plugins"); } var toEnable = transaction.ToEnable; var toDisable = transaction.ToDisable; transaction.Dispose(); using var disabledChangeTransaction = DisabledConfig.Instance.ChangeTransaction(); { // first enable the mods that need to be void DeTree(List <PluginMetadata> into, IEnumerable <PluginMetadata> tree) { foreach (var st in tree) { if (toEnable.Contains(st) && !into.Contains(st)) { DeTree(into, st.Dependencies); into.Add(st); } } } var enableOrder = new List <PluginMetadata>(); DeTree(enableOrder, toEnable); foreach (var meta in enableOrder) { var executor = runtimeDisabledPlugins.FirstOrDefault(e => e.Metadata == meta); if (meta.RuntimeOptions == RuntimeOptions.DynamicInit) { if (executor != null) { runtimeDisabledPlugins.Remove(executor); } else { executor = PluginLoader.InitPlugin(meta, EnabledPlugins); } if (executor == null) { continue; // couldn't initialize, skip to next } } PluginLoader.DisabledPlugins.Remove(meta); DisabledConfig.Instance.DisabledModIds.Remove(meta.Id ?? meta.Name); PluginEnabled?.Invoke(meta, meta.RuntimeOptions != RuntimeOptions.DynamicInit); if (meta.RuntimeOptions == RuntimeOptions.DynamicInit) { _bsPlugins.Add(executor); try { executor.Enable(); } catch (Exception e) { Logger.loader.Error($"Error while enabling {meta.Id}:"); Logger.loader.Error(e); // this should still be considered enabled, hence its position } } } } var result = Task.WhenAll(); {
/// <summary> /// Gets a disabled plugin's metadata by its ID. /// </summary> /// <param name="name">the ID of the disabled plugin to get</param> /// <returns>the metadata for the corresponding plugin</returns> public static PluginMetadata GetDisabledPluginFromId(string name) => DisabledPlugins.FirstOrDefault(p => p.Id == name);
public bool ShouldSerializeDisabledPlugins() { return(DisabledPlugins.HasItems()); }
/// <summary> /// Checks if a given plugin is disabled. /// </summary> /// <param name="meta">the plugin to check</param> /// <returns><see langword="true"/> if the plugin is disabled, <see langword="false"/> otherwise.</returns> public static bool IsDisabled(PluginMetadata meta) => DisabledPlugins.Contains(meta);