You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
3.6 KiB

  1. using IPA.Config;
  2. using IPA.Config.Stores;
  3. using IPA.Config.Stores.Attributes;
  4. using IPA.Config.Stores.Converters;
  5. using IPA.Logging;
  6. using IPA.Utilities;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. #if NET4
  13. using Task = System.Threading.Tasks.Task;
  14. using TaskEx = System.Threading.Tasks.Task;
  15. #endif
  16. #if NET3
  17. using Net3_Proxy;
  18. #endif
  19. namespace IPA.Loader
  20. {
  21. internal class DisabledConfig
  22. {
  23. public static Config.Config Disabled { get; set; }
  24. public static DisabledConfig Instance;
  25. public static void Load()
  26. {
  27. Disabled = Config.Config.GetConfigFor("Disabled Mods", "json");
  28. Instance = Disabled.Generated<DisabledConfig>();
  29. }
  30. public virtual bool Reset { get; set; } = true;
  31. [NonNullable]
  32. [UseConverter(typeof(CollectionConverter<string, HashSet<string>>))]
  33. public virtual HashSet<string> DisabledModIds { get; set; } = new HashSet<string>();
  34. protected internal virtual void Changed() { }
  35. protected internal virtual IDisposable ChangeTransaction() => null;
  36. private Task disableUpdateTask = null;
  37. private int updateState = 0;
  38. protected virtual void OnReload()
  39. {
  40. if (DisabledModIds == null || Reset)
  41. {
  42. DisabledModIds = new HashSet<string>();
  43. Reset = false;
  44. }
  45. if (!PluginLoader.IsFirstLoadComplete) return; // if the first load isn't complete, skip all of this
  46. var referToState = unchecked(++updateState);
  47. var copy = DisabledModIds.ToArray();
  48. if (disableUpdateTask == null || disableUpdateTask.IsCompleted)
  49. {
  50. disableUpdateTask = UpdateDisabledMods(copy);
  51. }
  52. else
  53. {
  54. disableUpdateTask = disableUpdateTask.ContinueWith(t =>
  55. {
  56. // skip if another got here before the last finished
  57. if (referToState != updateState) return TaskEx.WhenAll();
  58. else return UpdateDisabledMods(copy);
  59. });
  60. }
  61. }
  62. private Task UpdateDisabledMods(string[] updateWithDisabled)
  63. {
  64. do
  65. {
  66. using var transaction = PluginManager.PluginStateTransaction();
  67. var disabled = transaction.DisabledPlugins.ToArray();
  68. foreach (var plugin in disabled)
  69. transaction.Enable(plugin, autoDeps: true);
  70. var all = transaction.EnabledPlugins.ToArray();
  71. foreach (var plugin in all.Where(m => updateWithDisabled.Contains(m.Id)))
  72. transaction.Disable(plugin, autoDependents: true);
  73. try
  74. {
  75. if (transaction.WillNeedRestart)
  76. Logger.loader.Warn("Runtime disabled config reload will need game restart to apply");
  77. return transaction.Commit().ContinueWith(t =>
  78. {
  79. if (t.IsFaulted)
  80. {
  81. Logger.loader.Error("Error changing disabled plugins");
  82. Logger.loader.Error(t.Exception);
  83. }
  84. });
  85. }
  86. catch (InvalidOperationException)
  87. {
  88. continue;
  89. }
  90. }
  91. while (true);
  92. }
  93. }
  94. }