diff --git a/IPA.Loader/Loader/PluginManager.cs b/IPA.Loader/Loader/PluginManager.cs
index 72b9ee46..48d2ffc0 100644
--- a/IPA.Loader/Loader/PluginManager.cs
+++ b/IPA.Loader/Loader/PluginManager.cs
@@ -85,7 +85,11 @@ namespace IPA.Loader
if (!transaction.HasStateChanged) return TaskEx.WhenAll();
if (!UnityGame.OnMainThread)
- return UnityMainThreadTaskScheduler.Factory.StartNew(() => CommitTransaction(transaction)).Unwrap();
+ {
+ var transactionCopy = transaction.Clone();
+ transaction.Dispose();
+ return UnityMainThreadTaskScheduler.Factory.StartNew(() => CommitTransaction(transactionCopy)).Unwrap();
+ }
lock (commitTransactionLockObject)
{
@@ -94,6 +98,7 @@ namespace IPA.Loader
|| 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");
}
diff --git a/IPA.Loader/Loader/StateTransitionTransaction.cs b/IPA.Loader/Loader/StateTransitionTransaction.cs
index 41f6efef..e3209d00 100644
--- a/IPA.Loader/Loader/StateTransitionTransaction.cs
+++ b/IPA.Loader/Loader/StateTransitionTransaction.cs
@@ -237,6 +237,23 @@ namespace IPA.Loader
/// if the plugins' state no longer matches this transaction's original state
public Task Commit() => ThrowIfDisposed() ?? PluginManager.CommitTransaction(this);
+ ///
+ /// Clones this transaction to be identical, but with unrelated underlying sets.
+ ///
+ /// the new
+ /// if this object has been disposed
+ public StateTransitionTransaction Clone()
+ {
+ ThrowIfDisposed();
+ var copy = new StateTransitionTransaction(CurrentlyEnabled, CurrentlyDisabled);
+ foreach (var toEnable in ToEnable)
+ copy.toEnable.Add(toEnable);
+ foreach (var toDisable in ToDisable)
+ copy.toDisable.Add(toDisable);
+ copy.stateChanged = stateChanged;
+ return copy;
+ }
+
private void ThrowIfDisposed() => ThrowIfDisposed();
private T ThrowIfDisposed()
{