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.

79 lines
3.4 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace IPA.Loader
  7. {
  8. public sealed class StateTransitionTransaction : IDisposable
  9. {
  10. private readonly HashSet<PluginMetadata> currentlyEnabled;
  11. private readonly HashSet<PluginMetadata> currentlyDisabled;
  12. private readonly HashSet<PluginMetadata> toEnable = new HashSet<PluginMetadata>();
  13. private readonly HashSet<PluginMetadata> toDisable = new HashSet<PluginMetadata>();
  14. internal StateTransitionTransaction(IEnumerable<PluginMetadata> enabled, IEnumerable<PluginMetadata> disabled)
  15. {
  16. currentlyEnabled = new HashSet<PluginMetadata>(enabled.ToArray());
  17. currentlyDisabled = new HashSet<PluginMetadata>(disabled.ToArray());
  18. }
  19. public bool WillNeedRestart => toEnable.Concat(toDisable).Any(m => m.RuntimeOptions != RuntimeOptions.DynamicInit);
  20. internal IEnumerable<PluginMetadata> ToEnable => toEnable;
  21. internal IEnumerable<PluginMetadata> ToDisable => toDisable;
  22. public IEnumerable<PluginMetadata> EnabledPlugins => currentlyEnabled.Except(toDisable).Concat(toEnable);
  23. public IEnumerable<PluginMetadata> DisabledPlugins => currentlyDisabled.Except(toEnable).Concat(toDisable);
  24. public bool IsEnabled(PluginMetadata meta)
  25. => ThrowIfDisposed<bool>()
  26. || (currentlyEnabled.Contains(meta) && !toDisable.Contains(meta))
  27. || toEnable.Contains(meta);
  28. public bool IsDisabled(PluginMetadata meta)
  29. => ThrowIfDisposed<bool>()
  30. || (currentlyDisabled.Contains(meta) && !toEnable.Contains(meta))
  31. || toDisable.Contains(meta);
  32. public bool Enable(PluginMetadata meta)
  33. { // returns whether or not state was changed
  34. ThrowIfDisposed();
  35. if (!currentlyEnabled.Contains(meta) && !currentlyDisabled.Contains(meta))
  36. throw new ArgumentException(nameof(meta), "Plugin metadata does not represent a loadable plugin");
  37. if (toEnable.Contains(meta)) return false;
  38. if (currentlyEnabled.Contains(meta) && !toDisable.Contains(meta)) return false;
  39. toDisable.Remove(meta);
  40. toEnable.Add(meta);
  41. return true;
  42. }
  43. public bool Disable(PluginMetadata meta)
  44. { // returns whether or not state was changed
  45. ThrowIfDisposed();
  46. if (!currentlyEnabled.Contains(meta) && !currentlyDisabled.Contains(meta))
  47. throw new ArgumentException(nameof(meta), "Plugin metadata does not represent a ");
  48. if (toEnable.Contains(meta)) return false;
  49. if (currentlyEnabled.Contains(meta) && !toDisable.Contains(meta)) return false;
  50. toDisable.Remove(meta);
  51. toEnable.Add(meta);
  52. return true;
  53. }
  54. public Task Commit() => PluginManager.CommitTransaction(this);
  55. private void ThrowIfDisposed() => ThrowIfDisposed<byte>();
  56. private T ThrowIfDisposed<T>()
  57. {
  58. if (disposed)
  59. throw new ObjectDisposedException(nameof(StateTransitionTransaction));
  60. return default;
  61. }
  62. private bool disposed = false;
  63. public void Dispose()
  64. => disposed = true;
  65. }
  66. }