diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-01-01 00:48:44 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2020-01-01 00:48:44 -0500 |
commit | 6766fcd0fd5f6982d1ffc91a46e0d4a5703315dc (patch) | |
tree | ec70f36767d3fa6f687882ec1a875d62cc2da41e /src/SMAPI/Framework/StateTracking | |
parent | c5cfcc6c9ff36a7fc05916de95889c21dc6849ea (diff) | |
download | SMAPI-6766fcd0fd5f6982d1ffc91a46e0d4a5703315dc.tar.gz SMAPI-6766fcd0fd5f6982d1ffc91a46e0d4a5703315dc.tar.bz2 SMAPI-6766fcd0fd5f6982d1ffc91a46e0d4a5703315dc.zip |
fix NetList watcher not handling array replacement and conflicting changes correctly
Diffstat (limited to 'src/SMAPI/Framework/StateTracking')
-rw-r--r-- | src/SMAPI/Framework/StateTracking/ChestTracker.cs | 4 | ||||
-rw-r--r-- | src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs | 61 |
2 files changed, 50 insertions, 15 deletions
diff --git a/src/SMAPI/Framework/StateTracking/ChestTracker.cs b/src/SMAPI/Framework/StateTracking/ChestTracker.cs index 66dc61eb..3ce70c17 100644 --- a/src/SMAPI/Framework/StateTracking/ChestTracker.cs +++ b/src/SMAPI/Framework/StateTracking/ChestTracker.cs @@ -57,9 +57,9 @@ namespace StardewModdingAPI.Framework.StateTracking { // update watcher this.InventoryWatcher.Update(); - foreach (Item item in this.InventoryWatcher.Added.Where(p => p != null)) + foreach (Item item in this.InventoryWatcher.Added) this.Added.Add(item); - foreach (Item item in this.InventoryWatcher.Removed.Where(p => p != null)) + foreach (Item item in this.InventoryWatcher.Removed) { if (!this.Added.Remove(item)) // item didn't change if it was both added and removed, so remove it from both lists this.Removed.Add(item); diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs index 8aa0eab5..0b4d3030 100644 --- a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs +++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Netcode; +using StardewModdingAPI.Framework.StateTracking.Comparers; namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers { @@ -15,10 +16,10 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers private readonly NetList<TValue, NetRef<TValue>> Field; /// <summary>The pairs added since the last reset.</summary> - private readonly IList<TValue> AddedImpl = new List<TValue>(); + private readonly ISet<TValue> AddedImpl = new HashSet<TValue>(new ObjectReferenceComparer<TValue>()); /// <summary>The pairs removed since the last reset.</summary> - private readonly IList<TValue> RemovedImpl = new List<TValue>(); + private readonly ISet<TValue> RemovedImpl = new HashSet<TValue>(new ObjectReferenceComparer<TValue>()); /********* @@ -81,14 +82,19 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers /// <param name="newValues">The new list of values.</param> private void OnArrayReplaced(NetList<TValue, NetRef<TValue>> list, IList<TValue> oldValues, IList<TValue> newValues) { - this.AddedImpl.Clear(); - this.RemovedImpl.Clear(); - - foreach (TValue value in newValues) - this.AddedImpl.Add(value); + ISet<TValue> oldSet = new HashSet<TValue>(oldValues, new ObjectReferenceComparer<TValue>()); + ISet<TValue> changed = new HashSet<TValue>(newValues, new ObjectReferenceComparer<TValue>()); - foreach (TValue value in oldValues) - this.RemovedImpl.Add(value); + foreach (TValue value in oldSet) + { + if (!changed.Contains(value)) + this.Remove(value); + } + foreach (TValue value in changed) + { + if (!oldSet.Contains(value)) + this.Add(value); + } } /// <summary>A callback invoked when an entry is replaced.</summary> @@ -98,11 +104,40 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers /// <param name="newValue">The new value.</param> private void OnElementChanged(NetList<TValue, NetRef<TValue>> list, int index, TValue oldValue, TValue newValue) { - if (newValue != null) - this.AddedImpl.Add(newValue); + this.Remove(oldValue); + this.Add(newValue); + } + + /// <summary>Track an added item.</summary> + /// <param name="value">The value that was added.</param> + private void Add(TValue value) + { + if (value == null) + return; + + if (this.RemovedImpl.Contains(value)) + { + this.AddedImpl.Remove(value); + this.RemovedImpl.Remove(value); + } + else + this.AddedImpl.Add(value); + } - if (oldValue != null) - this.RemovedImpl.Add(oldValue); + /// <summary>Track a removed item.</summary> + /// <param name="value">The value that was removed.</param> + private void Remove(TValue value) + { + if (value == null) + return; + + if (this.AddedImpl.Contains(value)) + { + this.AddedImpl.Remove(value); + this.RemovedImpl.Remove(value); + } + else + this.RemovedImpl.Add(value); } } } |