summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/StateTracking
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-01-01 00:48:44 -0500
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2020-01-01 00:48:44 -0500
commit6766fcd0fd5f6982d1ffc91a46e0d4a5703315dc (patch)
treeec70f36767d3fa6f687882ec1a875d62cc2da41e /src/SMAPI/Framework/StateTracking
parentc5cfcc6c9ff36a7fc05916de95889c21dc6849ea (diff)
downloadSMAPI-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.cs4
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs61
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);
}
}
}