summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/StateTracking
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/StateTracking')
-rw-r--r--src/SMAPI/Framework/StateTracking/ChestTracker.cs5
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableListWatcher.cs17
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableWatcher.cs19
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/ImmutableCollectionWatcher.cs15
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/NetCollectionWatcher.cs19
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/NetDictionaryWatcher.cs19
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs25
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/NetValueWatcher.cs19
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs19
-rw-r--r--src/SMAPI/Framework/StateTracking/FieldWatchers/WatcherFactory.cs45
-rw-r--r--src/SMAPI/Framework/StateTracking/IWatcher.cs3
-rw-r--r--src/SMAPI/Framework/StateTracking/LocationTracker.cs28
-rw-r--r--src/SMAPI/Framework/StateTracking/PlayerTracker.cs14
-rw-r--r--src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs17
14 files changed, 161 insertions, 103 deletions
diff --git a/src/SMAPI/Framework/StateTracking/ChestTracker.cs b/src/SMAPI/Framework/StateTracking/ChestTracker.cs
index c33a7498..2796ad54 100644
--- a/src/SMAPI/Framework/StateTracking/ChestTracker.cs
+++ b/src/SMAPI/Framework/StateTracking/ChestTracker.cs
@@ -39,11 +39,12 @@ namespace StardewModdingAPI.Framework.StateTracking
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="chest">The chest being tracked.</param>
- public ChestTracker(Chest chest)
+ public ChestTracker(string name, Chest chest)
{
this.Chest = chest;
- this.InventoryWatcher = WatcherFactory.ForNetList(chest.items);
+ this.InventoryWatcher = WatcherFactory.ForNetList($"{name}.{nameof(chest.items)}", chest.items);
this.StackSizes = this.Chest.items
.Where(n => n != null)
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableListWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableListWatcher.cs
index 256370ce..0b13434a 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableListWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableListWatcher.cs
@@ -26,13 +26,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>Whether the value changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged => this.AddedImpl.Count > 0 || this.RemovedImpl.Count > 0;
- /// <summary>The values added since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Added => this.AddedImpl;
- /// <summary>The values removed since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Removed => this.RemovedImpl;
@@ -40,15 +43,17 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="values">The collection to watch.</param>
/// <param name="comparer">The equality comparer which indicates whether two values are the same.</param>
- public ComparableListWatcher(ICollection<TValue> values, IEqualityComparer<TValue> comparer)
+ public ComparableListWatcher(string name, ICollection<TValue> values, IEqualityComparer<TValue> comparer)
{
+ this.Name = name;
this.CurrentValues = values;
this.LastValues = new HashSet<TValue>(comparer);
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.AssertNotDisposed();
@@ -71,7 +76,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
this.LastValues = curValues;
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.AssertNotDisposed();
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableWatcher.cs
index 5f76fe0a..e2f6c7fd 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/ComparableWatcher.cs
@@ -20,13 +20,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>The field value at the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public TValue PreviousValue { get; private set; }
- /// <summary>The latest value.</summary>
+ /// <inheritdoc />
public TValue CurrentValue { get; private set; }
- /// <summary>Whether the value changed since the last reset.</summary>
+ /// <inheritdoc />
public bool IsChanged { get; private set; }
@@ -34,31 +37,33 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="getValue">Get the current value.</param>
/// <param name="comparer">The equality comparer which indicates whether two values are the same.</param>
- public ComparableWatcher(Func<TValue> getValue, IEqualityComparer<TValue> comparer)
+ public ComparableWatcher(string name, Func<TValue> getValue, IEqualityComparer<TValue> comparer)
{
+ this.Name = name;
this.GetValue = getValue;
this.Comparer = comparer;
this.CurrentValue = getValue();
this.PreviousValue = this.CurrentValue;
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.CurrentValue = this.GetValue();
this.IsChanged = !this.Comparer.Equals(this.PreviousValue, this.CurrentValue);
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.PreviousValue = this.CurrentValue;
this.IsChanged = false;
}
- /// <summary>Release any references if needed when the field is no longer needed.</summary>
+ /// <inheritdoc />
public void Dispose() { }
}
}
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/ImmutableCollectionWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/ImmutableCollectionWatcher.cs
index 84340fbf..9c2ba9bc 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/ImmutableCollectionWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/ImmutableCollectionWatcher.cs
@@ -13,26 +13,29 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/// <summary>A singleton collection watcher instance.</summary>
public static ImmutableCollectionWatcher<TValue> Instance { get; } = new();
- /// <summary>Whether the collection changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name => nameof(ImmutableCollectionWatcher<TValue>);
+
+ /// <inheritdoc />
public bool IsChanged { get; } = false;
- /// <summary>The values added since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Added { get; } = Array.Empty<TValue>();
- /// <summary>The values removed since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Removed { get; } = Array.Empty<TValue>();
/*********
** Public methods
*********/
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update() { }
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset() { }
- /// <summary>Stop watching the field and release all references.</summary>
+ /// <inheritdoc />
public override void Dispose() { }
}
}
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetCollectionWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetCollectionWatcher.cs
index 676c9fb4..1d5e4851 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetCollectionWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetCollectionWatcher.cs
@@ -24,13 +24,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>Whether the collection changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged => this.AddedImpl.Count > 0 || this.RemovedImpl.Count > 0;
- /// <summary>The values added since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Added => this.AddedImpl;
- /// <summary>The values removed since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Removed => this.RemovedImpl;
@@ -38,21 +41,23 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="field">The field to watch.</param>
- public NetCollectionWatcher(NetCollection<TValue> field)
+ public NetCollectionWatcher(string name, NetCollection<TValue> field)
{
+ this.Name = name;
this.Field = field;
field.OnValueAdded += this.OnValueAdded;
field.OnValueRemoved += this.OnValueRemoved;
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.AssertNotDisposed();
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.AssertNotDisposed();
@@ -61,7 +66,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
this.RemovedImpl.Clear();
}
- /// <summary>Stop watching the field and release all references.</summary>
+ /// <inheritdoc />
public override void Dispose()
{
if (!this.IsDisposed)
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetDictionaryWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetDictionaryWatcher.cs
index f55e4cea..3bd8e09d 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetDictionaryWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetDictionaryWatcher.cs
@@ -31,13 +31,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>Whether the collection changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged => this.PairsAdded.Count > 0 || this.PairsRemoved.Count > 0;
- /// <summary>The values added since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<KeyValuePair<TKey, TValue>> Added => this.PairsAdded;
- /// <summary>The values removed since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<KeyValuePair<TKey, TValue>> Removed => this.PairsRemoved;
@@ -45,22 +48,24 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="field">The field to watch.</param>
- public NetDictionaryWatcher(NetDictionary<TKey, TValue, TField, TSerialDict, TSelf> field)
+ public NetDictionaryWatcher(string name, NetDictionary<TKey, TValue, TField, TSerialDict, TSelf> field)
{
+ this.Name = name;
this.Field = field;
field.OnValueAdded += this.OnValueAdded;
field.OnValueRemoved += this.OnValueRemoved;
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.AssertNotDisposed();
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.AssertNotDisposed();
@@ -69,7 +74,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
this.PairsRemoved.Clear();
}
- /// <summary>Stop watching the field and release all references.</summary>
+ /// <inheritdoc />
public override void Dispose()
{
if (!this.IsDisposed)
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs
index 0b4d3030..5b6a3e1f 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetListWatcher.cs
@@ -25,13 +25,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>Whether the collection changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged => this.AddedImpl.Count > 0 || this.RemovedImpl.Count > 0;
- /// <summary>The values added since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Added => this.AddedImpl;
- /// <summary>The values removed since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Removed => this.RemovedImpl;
@@ -39,28 +42,30 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="field">The field to watch.</param>
- public NetListWatcher(NetList<TValue, NetRef<TValue>> field)
+ public NetListWatcher(string name, NetList<TValue, NetRef<TValue>> field)
{
+ this.Name = name;
this.Field = field;
field.OnElementChanged += this.OnElementChanged;
field.OnArrayReplaced += this.OnArrayReplaced;
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.AddedImpl.Clear();
this.RemovedImpl.Clear();
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.AssertNotDisposed();
}
- /// <summary>Stop watching the field and release all references.</summary>
+ /// <inheritdoc />
public override void Dispose()
{
if (!this.IsDisposed)
@@ -102,7 +107,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/// <param name="index">The list index which changed.</param>
/// <param name="oldValue">The previous value.</param>
/// <param name="newValue">The new value.</param>
- private void OnElementChanged(NetList<TValue, NetRef<TValue>> list, int index, TValue oldValue, TValue newValue)
+ private void OnElementChanged(NetList<TValue, NetRef<TValue>> list, int index, TValue? oldValue, TValue? newValue)
{
this.Remove(oldValue);
this.Add(newValue);
@@ -110,7 +115,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/// <summary>Track an added item.</summary>
/// <param name="value">The value that was added.</param>
- private void Add(TValue value)
+ private void Add(TValue? value)
{
if (value == null)
return;
@@ -126,7 +131,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/// <summary>Track a removed item.</summary>
/// <param name="value">The value that was removed.</param>
- private void Remove(TValue value)
+ private void Remove(TValue? value)
{
if (value == null)
return;
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetValueWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetValueWatcher.cs
index 48d5d681..e4219dda 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/NetValueWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/NetValueWatcher.cs
@@ -17,13 +17,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>Whether the value changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged { get; private set; }
- /// <summary>The field value at the last reset.</summary>
+ /// <inheritdoc />
public TValue PreviousValue { get; private set; }
- /// <summary>The latest value.</summary>
+ /// <inheritdoc />
public TValue CurrentValue { get; private set; }
@@ -31,9 +34,11 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="field">The field to watch.</param>
- public NetValueWatcher(NetFieldBase<TValue, TNetField> field)
+ public NetValueWatcher(string name, NetFieldBase<TValue, TNetField> field)
{
+ this.Name = name;
this.Field = field;
this.PreviousValue = field.Value;
this.CurrentValue = field.Value;
@@ -42,13 +47,13 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
field.fieldChangeEvent += this.OnValueChanged;
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.AssertNotDisposed();
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.AssertNotDisposed();
@@ -57,7 +62,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
this.IsChanged = false;
}
- /// <summary>Stop watching the field and release all references.</summary>
+ /// <inheritdoc />
public override void Dispose()
{
if (!this.IsDisposed)
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs
index 97aedca8..1f95ac89 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/ObservableCollectionWatcher.cs
@@ -28,13 +28,16 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/*********
** Accessors
*********/
- /// <summary>Whether the collection changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged => this.AddedImpl.Count > 0 || this.RemovedImpl.Count > 0;
- /// <summary>The values added since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Added => this.AddedImpl;
- /// <summary>The values removed since the last reset.</summary>
+ /// <inheritdoc />
public IEnumerable<TValue> Removed => this.RemovedImpl;
@@ -42,20 +45,22 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
** Public methods
*********/
/// <summary>Construct an instance.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="field">The field to watch.</param>
- public ObservableCollectionWatcher(ObservableCollection<TValue> field)
+ public ObservableCollectionWatcher(string name, ObservableCollection<TValue> field)
{
+ this.Name = name;
this.Field = field;
field.CollectionChanged += this.OnCollectionChanged;
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
this.AssertNotDisposed();
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.AssertNotDisposed();
@@ -64,7 +69,7 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
this.RemovedImpl.Clear();
}
- /// <summary>Stop watching the field and release all references.</summary>
+ /// <inheritdoc />
public override void Dispose()
{
if (!this.IsDisposed)
diff --git a/src/SMAPI/Framework/StateTracking/FieldWatchers/WatcherFactory.cs b/src/SMAPI/Framework/StateTracking/FieldWatchers/WatcherFactory.cs
index c4a4d0b9..c31be1fc 100644
--- a/src/SMAPI/Framework/StateTracking/FieldWatchers/WatcherFactory.cs
+++ b/src/SMAPI/Framework/StateTracking/FieldWatchers/WatcherFactory.cs
@@ -17,37 +17,41 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
****/
/// <summary>Get a watcher which compares values using their <see cref="object.Equals(object)"/> method. This method should only be used when <see cref="ForEquatable{T}"/> won't work, since this doesn't validate whether they're comparable.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="getValue">Get the current value.</param>
- public static IValueWatcher<T> ForGenericEquality<T>(Func<T> getValue)
+ public static IValueWatcher<T> ForGenericEquality<T>(string name, Func<T> getValue)
where T : struct
{
- return new ComparableWatcher<T>(getValue, new GenericEqualsComparer<T>());
+ return new ComparableWatcher<T>(name, getValue, new GenericEqualsComparer<T>());
}
/// <summary>Get a watcher for an <see cref="IEquatable{T}"/> value.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="getValue">Get the current value.</param>
- public static IValueWatcher<T> ForEquatable<T>(Func<T> getValue)
+ public static IValueWatcher<T> ForEquatable<T>(string name, Func<T> getValue)
where T : IEquatable<T>
{
- return new ComparableWatcher<T>(getValue, new EquatableComparer<T>());
+ return new ComparableWatcher<T>(name, getValue, new EquatableComparer<T>());
}
/// <summary>Get a watcher which detects when an object reference changes.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="getValue">Get the current value.</param>
- public static IValueWatcher<T> ForReference<T>(Func<T> getValue)
+ public static IValueWatcher<T> ForReference<T>(string name, Func<T> getValue)
{
- return new ComparableWatcher<T>(getValue, new ObjectReferenceComparer<T>());
+ return new ComparableWatcher<T>(name, getValue, new ObjectReferenceComparer<T>());
}
/// <summary>Get a watcher for a net collection.</summary>
/// <typeparam name="T">The value type.</typeparam>
/// <typeparam name="TSelf">The net field instance type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="field">The net collection.</param>
- public static IValueWatcher<T> ForNetValue<T, TSelf>(NetFieldBase<T, TSelf> field) where TSelf : NetFieldBase<T, TSelf>
+ public static IValueWatcher<T> ForNetValue<T, TSelf>(string name, NetFieldBase<T, TSelf> field) where TSelf : NetFieldBase<T, TSelf>
{
- return new NetValueWatcher<T, TSelf>(field);
+ return new NetValueWatcher<T, TSelf>(name, field);
}
/****
@@ -55,18 +59,20 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
****/
/// <summary>Get a watcher which detects when an object reference in a collection changes.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="collection">The observable collection.</param>
- public static ICollectionWatcher<T> ForReferenceList<T>(ICollection<T> collection)
+ public static ICollectionWatcher<T> ForReferenceList<T>(string name, ICollection<T> collection)
{
- return new ComparableListWatcher<T>(collection, new ObjectReferenceComparer<T>());
+ return new ComparableListWatcher<T>(name, collection, new ObjectReferenceComparer<T>());
}
/// <summary>Get a watcher for an observable collection.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="collection">The observable collection.</param>
- public static ICollectionWatcher<T> ForObservableCollection<T>(ObservableCollection<T> collection)
+ public static ICollectionWatcher<T> ForObservableCollection<T>(string name, ObservableCollection<T> collection)
{
- return new ObservableCollectionWatcher<T>(collection);
+ return new ObservableCollectionWatcher<T>(name, collection);
}
/// <summary>Get a watcher for a collection that never changes.</summary>
@@ -78,36 +84,39 @@ namespace StardewModdingAPI.Framework.StateTracking.FieldWatchers
/// <summary>Get a watcher for a net collection.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="collection">The net collection.</param>
- public static ICollectionWatcher<T> ForNetCollection<T>(NetCollection<T> collection)
+ public static ICollectionWatcher<T> ForNetCollection<T>(string name, NetCollection<T> collection)
where T : class, INetObject<INetSerializable>
{
- return new NetCollectionWatcher<T>(collection);
+ return new NetCollectionWatcher<T>(name, collection);
}
/// <summary>Get a watcher for a net list.</summary>
/// <typeparam name="T">The value type.</typeparam>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <param name="collection">The net list.</param>
- public static ICollectionWatcher<T> ForNetList<T>(NetList<T, NetRef<T>> collection)
+ public static ICollectionWatcher<T> ForNetList<T>(string name, NetList<T, NetRef<T>> collection)
where T : class, INetObject<INetSerializable>
{
- return new NetListWatcher<T>(collection);
+ return new NetListWatcher<T>(name, collection);
}
/// <summary>Get a watcher for a net dictionary.</summary>
+ /// <param name="name">A name which identifies what the watcher is watching, used for troubleshooting.</param>
/// <typeparam name="TKey">The dictionary key type.</typeparam>
/// <typeparam name="TValue">The dictionary value type.</typeparam>
/// <typeparam name="TField">The net type equivalent to <typeparamref name="TValue"/>.</typeparam>
/// <typeparam name="TSerialDict">The serializable dictionary type that can store the keys and values.</typeparam>
/// <typeparam name="TSelf">The net field instance type.</typeparam>
/// <param name="field">The net field.</param>
- public static NetDictionaryWatcher<TKey, TValue, TField, TSerialDict, TSelf> ForNetDictionary<TKey, TValue, TField, TSerialDict, TSelf>(NetDictionary<TKey, TValue, TField, TSerialDict, TSelf> field)
+ public static NetDictionaryWatcher<TKey, TValue, TField, TSerialDict, TSelf> ForNetDictionary<TKey, TValue, TField, TSerialDict, TSelf>(string name, NetDictionary<TKey, TValue, TField, TSerialDict, TSelf> field)
where TKey : notnull
where TField : class, INetObject<INetSerializable>, new()
where TSerialDict : IDictionary<TKey, TValue>, new()
where TSelf : NetDictionary<TKey, TValue, TField, TSerialDict, TSelf>
{
- return new NetDictionaryWatcher<TKey, TValue, TField, TSerialDict, TSelf>(field);
+ return new NetDictionaryWatcher<TKey, TValue, TField, TSerialDict, TSelf>(name, field);
}
}
}
diff --git a/src/SMAPI/Framework/StateTracking/IWatcher.cs b/src/SMAPI/Framework/StateTracking/IWatcher.cs
index 8c7fa51c..4a0e3998 100644
--- a/src/SMAPI/Framework/StateTracking/IWatcher.cs
+++ b/src/SMAPI/Framework/StateTracking/IWatcher.cs
@@ -8,6 +8,9 @@ namespace StardewModdingAPI.Framework.StateTracking
/*********
** Accessors
*********/
+ /// <summary>A name which identifies what the watcher is watching, used for troubleshooting.</summary>
+ string Name { get; }
+
/// <summary>Whether the value changed since the last reset.</summary>
bool IsChanged { get; }
diff --git a/src/SMAPI/Framework/StateTracking/LocationTracker.cs b/src/SMAPI/Framework/StateTracking/LocationTracker.cs
index ff72a19b..790c71dd 100644
--- a/src/SMAPI/Framework/StateTracking/LocationTracker.cs
+++ b/src/SMAPI/Framework/StateTracking/LocationTracker.cs
@@ -25,7 +25,10 @@ namespace StardewModdingAPI.Framework.StateTracking
/*********
** Accessors
*********/
- /// <summary>Whether the value changed since the last reset.</summary>
+ /// <inheritdoc />
+ public string Name { get; }
+
+ /// <inheritdoc />
public bool IsChanged => this.Watchers.Any(p => p.IsChanged);
/// <summary>The tracked location.</summary>
@@ -63,16 +66,17 @@ namespace StardewModdingAPI.Framework.StateTracking
/// <param name="location">The location to track.</param>
public LocationTracker(GameLocation location)
{
+ this.Name = $"Locations.{location.NameOrUniqueName}";
this.Location = location;
// init watchers
- this.BuildingsWatcher = location is BuildableGameLocation buildableLocation ? WatcherFactory.ForNetCollection(buildableLocation.buildings) : WatcherFactory.ForImmutableCollection<Building>();
- this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris);
- this.LargeTerrainFeaturesWatcher = WatcherFactory.ForNetCollection(location.largeTerrainFeatures);
- this.NpcsWatcher = WatcherFactory.ForNetCollection(location.characters);
- this.ObjectsWatcher = WatcherFactory.ForNetDictionary(location.netObjects);
- this.TerrainFeaturesWatcher = WatcherFactory.ForNetDictionary(location.terrainFeatures);
- this.FurnitureWatcher = WatcherFactory.ForNetCollection(location.furniture);
+ this.BuildingsWatcher = location is BuildableGameLocation buildableLocation ? WatcherFactory.ForNetCollection($"{this.Name}.{nameof(buildableLocation.buildings)}", buildableLocation.buildings) : WatcherFactory.ForImmutableCollection<Building>();
+ this.DebrisWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.debris)}", location.debris);
+ this.LargeTerrainFeaturesWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.largeTerrainFeatures)}", location.largeTerrainFeatures);
+ this.NpcsWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.characters)}", location.characters);
+ this.ObjectsWatcher = WatcherFactory.ForNetDictionary($"{this.Name}.{nameof(location.netObjects)}", location.netObjects);
+ this.TerrainFeaturesWatcher = WatcherFactory.ForNetDictionary($"{this.Name}.{nameof(location.terrainFeatures)}", location.terrainFeatures);
+ this.FurnitureWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.furniture)}", location.furniture);
this.Watchers.AddRange(new IWatcher[]
{
@@ -88,7 +92,7 @@ namespace StardewModdingAPI.Framework.StateTracking
this.UpdateChestWatcherList(added: location.Objects.Pairs, removed: Array.Empty<KeyValuePair<Vector2, SObject>>());
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
foreach (IWatcher watcher in this.Watchers)
@@ -100,7 +104,7 @@ namespace StardewModdingAPI.Framework.StateTracking
watcher.Value.Update();
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
foreach (IWatcher watcher in this.Watchers)
@@ -110,7 +114,7 @@ namespace StardewModdingAPI.Framework.StateTracking
watcher.Value.Reset();
}
- /// <summary>Stop watching the player fields and release all references.</summary>
+ /// <inheritdoc />
public void Dispose()
{
foreach (IWatcher watcher in this.Watchers)
@@ -143,7 +147,7 @@ namespace StardewModdingAPI.Framework.StateTracking
foreach ((Vector2 tile, SObject? obj) in added)
{
if (obj is Chest chest && !this.ChestWatchers.ContainsKey(tile))
- this.ChestWatchers.Add(tile, new ChestTracker(chest));
+ this.ChestWatchers.Add(tile, new ChestTracker($"{this.Name}.chest({tile})", chest));
}
}
}
diff --git a/src/SMAPI/Framework/StateTracking/PlayerTracker.cs b/src/SMAPI/Framework/StateTracking/PlayerTracker.cs
index 5433ac8e..fae90678 100644
--- a/src/SMAPI/Framework/StateTracking/PlayerTracker.cs
+++ b/src/SMAPI/Framework/StateTracking/PlayerTracker.cs
@@ -54,15 +54,15 @@ namespace StardewModdingAPI.Framework.StateTracking
this.PreviousInventory = new Dictionary<Item, int>(this.CurrentInventory);
// init trackers
- this.LocationWatcher = WatcherFactory.ForReference(this.GetCurrentLocation);
+ this.LocationWatcher = WatcherFactory.ForReference($"player.{nameof(player.currentLocation)}", this.GetCurrentLocation);
this.SkillWatchers = new Dictionary<SkillType, IValueWatcher<int>>
{
- [SkillType.Combat] = WatcherFactory.ForNetValue(player.combatLevel),
- [SkillType.Farming] = WatcherFactory.ForNetValue(player.farmingLevel),
- [SkillType.Fishing] = WatcherFactory.ForNetValue(player.fishingLevel),
- [SkillType.Foraging] = WatcherFactory.ForNetValue(player.foragingLevel),
- [SkillType.Luck] = WatcherFactory.ForNetValue(player.luckLevel),
- [SkillType.Mining] = WatcherFactory.ForNetValue(player.miningLevel)
+ [SkillType.Combat] = WatcherFactory.ForNetValue($"player.{nameof(player.combatLevel)}", player.combatLevel),
+ [SkillType.Farming] = WatcherFactory.ForNetValue($"player.{nameof(player.farmingLevel)}", player.farmingLevel),
+ [SkillType.Fishing] = WatcherFactory.ForNetValue($"player.{nameof(player.fishingLevel)}", player.fishingLevel),
+ [SkillType.Foraging] = WatcherFactory.ForNetValue($"player.{nameof(player.foragingLevel)}", player.foragingLevel),
+ [SkillType.Luck] = WatcherFactory.ForNetValue($"player.{nameof(player.luckLevel)}", player.luckLevel),
+ [SkillType.Mining] = WatcherFactory.ForNetValue($"player.{nameof(player.miningLevel)}", player.miningLevel)
};
// track watchers for convenience
diff --git a/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs b/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs
index 817a6011..ca6988ad 100644
--- a/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs
+++ b/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs
@@ -34,10 +34,13 @@ namespace StardewModdingAPI.Framework.StateTracking
/*********
** Accessors
*********/
+ /// <inheritdoc />
+ public string Name => nameof(WorldLocationsTracker);
+
/// <summary>Whether locations were added or removed since the last reset.</summary>
public bool IsLocationListChanged => this.Added.Any() || this.Removed.Any();
- /// <summary>Whether any tracked location data changed since the last reset.</summary>
+ /// <inheritdoc />
public bool IsChanged => this.IsLocationListChanged || this.Locations.Any(p => p.IsChanged);
/// <summary>The tracked locations.</summary>
@@ -59,12 +62,12 @@ namespace StardewModdingAPI.Framework.StateTracking
/// <param name="activeVolcanoLocations">The game's list of active volcano locations.</param>
public WorldLocationsTracker(ObservableCollection<GameLocation> locations, IList<MineShaft> activeMineLocations, IList<VolcanoDungeon> activeVolcanoLocations)
{
- this.LocationListWatcher = WatcherFactory.ForObservableCollection(locations);
- this.MineLocationListWatcher = WatcherFactory.ForReferenceList(activeMineLocations);
- this.VolcanoLocationListWatcher = WatcherFactory.ForReferenceList(activeVolcanoLocations);
+ this.LocationListWatcher = WatcherFactory.ForObservableCollection($"{this.Name}.{nameof(locations)}", locations);
+ this.MineLocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(activeMineLocations)}", activeMineLocations);
+ this.VolcanoLocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(activeVolcanoLocations)}", activeVolcanoLocations);
}
- /// <summary>Update the current value if needed.</summary>
+ /// <inheritdoc />
public void Update()
{
// update watchers
@@ -120,7 +123,7 @@ namespace StardewModdingAPI.Framework.StateTracking
this.VolcanoLocationListWatcher.Reset();
}
- /// <summary>Set the current value as the baseline.</summary>
+ /// <inheritdoc />
public void Reset()
{
this.ResetLocationList();
@@ -135,7 +138,7 @@ namespace StardewModdingAPI.Framework.StateTracking
return this.LocationDict.ContainsKey(location);
}
- /// <summary>Stop watching the player fields and release all references.</summary>
+ /// <inheritdoc />
public void Dispose()
{
foreach (IWatcher watcher in this.GetWatchers())