summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/common.targets2
-rw-r--r--docs/release-notes.md7
-rw-r--r--docs/technical/mod-package.md8
-rw-r--r--src/SMAPI.Mods.ConsoleCommands/manifest.json4
-rw-r--r--src/SMAPI.Mods.ErrorHandler/manifest.json4
-rw-r--r--src/SMAPI.Mods.SaveBackup/manifest.json4
-rw-r--r--src/SMAPI/Constants.cs2
-rw-r--r--src/SMAPI/Framework/ContentCoordinator.cs24
-rw-r--r--src/SMAPI/Framework/ContentManagers/BaseContentManager.cs12
-rw-r--r--src/SMAPI/Framework/ContentManagers/ModContentManager.cs2
-rw-r--r--src/SMAPI/Framework/Deprecations/DeprecationManager.cs3
-rw-r--r--src/SMAPI/Framework/SCore.cs1
-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
-rw-r--r--src/SMAPI/Framework/WatcherCore.cs14
27 files changed, 218 insertions, 133 deletions
diff --git a/build/common.targets b/build/common.targets
index 7b59e4ae..2e37e729 100644
--- a/build/common.targets
+++ b/build/common.targets
@@ -1,7 +1,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!--set general build properties -->
- <Version>3.14.5</Version>
+ <Version>3.14.6</Version>
<Product>SMAPI</Product>
<LangVersion>latest</LangVersion>
<AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths>
diff --git a/docs/release-notes.md b/docs/release-notes.md
index cd177f61..4770bd4f 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,6 +1,13 @@
← [README](README.md)
# Release notes
+## 3.14.6
+Released 27 May 2022 for Stardew Valley 1.5.6 or later.
+
+* For players:
+ * Fixed error in split-screen mode when a mod provides a localized asset in one screen but not another.
+ * Minor optimizations.
+
## 3.14.5
Released 22 May 2022 for Stardew Valley 1.5.6 or later.
diff --git a/docs/technical/mod-package.md b/docs/technical/mod-package.md
index c632af84..dd65a992 100644
--- a/docs/technical/mod-package.md
+++ b/docs/technical/mod-package.md
@@ -412,14 +412,14 @@ The NuGet package is generated automatically in `StardewModdingAPI.ModBuildConfi
when you compile it.
## Release notes
-## 4.0.1
+### 4.0.1
Released 14 April 2022.
* Added detection for Xbox app game folders.
* Fixed "_conflicts between different versions of Microsoft.Win32.Registry_" warnings in recent SMAPI versions.
* Internal refactoring.
-## 4.0.0
+### 4.0.0
Released 30 November 2021.
* Updated for Stardew Valley 1.5.5 and SMAPI 3.13.0. (Older versions are no longer supported.)
@@ -441,7 +441,7 @@ Released 30 November 2021.
* If you need to bundle extra DLLs besides your mod DLL, see the [`BundleExtraAssemblies`
documentation](#configure).
-## 3.3.0
+### 3.3.0
Released 30 March 2021.
* Added a build warning when the mod isn't compiled for `Any CPU`.
@@ -450,7 +450,7 @@ Released 30 March 2021.
* Added support for building mods against the 64-bit Linux version of the game on Windows.
* The package now suppresses the misleading 'processor architecture mismatch' warnings.
-## 3.2.2
+### 3.2.2
Released 23 September 2020.
* Reworked and streamlined how the package is compiled.
diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json
index 7b403a75..9d9a8061 100644
--- a/src/SMAPI.Mods.ConsoleCommands/manifest.json
+++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Console Commands",
"Author": "SMAPI",
- "Version": "3.14.5",
+ "Version": "3.14.6",
"Description": "Adds SMAPI console commands that let you manipulate the game.",
"UniqueID": "SMAPI.ConsoleCommands",
"EntryDll": "ConsoleCommands.dll",
- "MinimumApiVersion": "3.14.5"
+ "MinimumApiVersion": "3.14.6"
}
diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json
index 2ac959bb..07c2512b 100644
--- a/src/SMAPI.Mods.ErrorHandler/manifest.json
+++ b/src/SMAPI.Mods.ErrorHandler/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Error Handler",
"Author": "SMAPI",
- "Version": "3.14.5",
+ "Version": "3.14.6",
"Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.",
"UniqueID": "SMAPI.ErrorHandler",
"EntryDll": "ErrorHandler.dll",
- "MinimumApiVersion": "3.14.5"
+ "MinimumApiVersion": "3.14.6"
}
diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json
index 707b6d8a..ec048dea 100644
--- a/src/SMAPI.Mods.SaveBackup/manifest.json
+++ b/src/SMAPI.Mods.SaveBackup/manifest.json
@@ -1,9 +1,9 @@
{
"Name": "Save Backup",
"Author": "SMAPI",
- "Version": "3.14.5",
+ "Version": "3.14.6",
"Description": "Automatically backs up all your saves once per day into its folder.",
"UniqueID": "SMAPI.SaveBackup",
"EntryDll": "SaveBackup.dll",
- "MinimumApiVersion": "3.14.5"
+ "MinimumApiVersion": "3.14.6"
}
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index b2916a8d..9212fc90 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -50,7 +50,7 @@ namespace StardewModdingAPI
internal static int? LogScreenId { get; set; }
/// <summary>SMAPI's current raw semantic version.</summary>
- internal static string RawApiVersion = "3.14.5";
+ internal static string RawApiVersion = "3.14.6";
}
/// <summary>Contains SMAPI's constants and assumptions.</summary>
diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs
index fc61b44b..cfeb35c8 100644
--- a/src/SMAPI/Framework/ContentCoordinator.cs
+++ b/src/SMAPI/Framework/ContentCoordinator.cs
@@ -15,8 +15,8 @@ using StardewModdingAPI.Framework.Utilities;
using StardewModdingAPI.Internal;
using StardewModdingAPI.Metadata;
using StardewModdingAPI.Toolkit.Serialization;
-using StardewModdingAPI.Toolkit.Utilities;
using StardewModdingAPI.Toolkit.Utilities.PathLookups;
+using StardewModdingAPI.Utilities;
using StardewValley;
using StardewValley.GameData;
using xTile;
@@ -110,6 +110,10 @@ namespace StardewModdingAPI.Framework
/// <summary>The absolute path to the <see cref="ContentManager.RootDirectory"/>.</summary>
public string FullRootDirectory { get; }
+ /// <summary>A lookup which tracks whether each given asset name has a localized form.</summary>
+ /// <remarks>This is a per-screen equivalent to the base game's <see cref="LocalizedContentManager.localizedAssetNames"/> field, since mods may provide different assets per-screen.</remarks>
+ public PerScreen<Dictionary<string, string>> LocalizedAssetNames { get; } = new(() => new());
+
/*********
** Public methods
@@ -245,6 +249,9 @@ namespace StardewModdingAPI.Framework
{
this.VanillaContentManager.Unload();
});
+
+ // forget localized flags (to match the logic in Game1.TranslateFields, which is called on language change)
+ this.LocalizedAssetNames.Value.Clear();
}
/// <summary>Clean up when the player is returning to the title screen.</summary>
@@ -275,6 +282,10 @@ namespace StardewModdingAPI.Framework
// their changes, the assets won't be found in the cache so no changes will be propagated.
if (LocalizedContentManager.CurrentLanguageCode != LocalizedContentManager.LanguageCode.en)
this.InvalidateCache((contentManager, _, _) => contentManager is GameContentManager);
+
+ // clear the localized assets lookup (to match the logic in Game1.CleanupReturningToTitle)
+ foreach ((_, Dictionary<string, string> localizedAssets) in this.LocalizedAssetNames.GetActiveValues())
+ localizedAssets.Clear();
}
/// <summary>Parse a raw asset name.</summary>
@@ -411,12 +422,15 @@ namespace StardewModdingAPI.Framework
// A mod might provide a localized variant of a normally non-localized asset (like
// `Maps/MovieTheater.fr-FR`). When the asset is invalidated, we need to recheck
// whether the asset is localized in case it stops providing it.
- foreach (IAssetName assetName in invalidatedAssets.Keys)
{
- LocalizedContentManager.localizedAssetNames.Remove(assetName.Name);
+ Dictionary<string, string> localizedAssetNames = this.LocalizedAssetNames.Value;
+ foreach (IAssetName assetName in invalidatedAssets.Keys)
+ {
+ localizedAssetNames.Remove(assetName.Name);
- if (LocalizedContentManager.localizedAssetNames.TryGetValue(assetName.BaseName, out string? targetForBaseKey) && targetForBaseKey == assetName.Name)
- LocalizedContentManager.localizedAssetNames.Remove(assetName.BaseName);
+ if (localizedAssetNames.TryGetValue(assetName.BaseName, out string? targetForBaseKey) && targetForBaseKey == assetName.Name)
+ localizedAssetNames.Remove(assetName.BaseName);
+ }
}
// special case: maps may be loaded through a temporary content manager that's removed while the map is still in use.
diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
index ddc02a8c..d7be0c37 100644
--- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs
@@ -153,7 +153,9 @@ namespace StardewModdingAPI.Framework.ContentManagers
return this.LoadExact<T>(assetName, useCache: useCache);
// check for localized asset
- if (!LocalizedContentManager.localizedAssetNames.TryGetValue(assetName.Name, out _))
+ // ReSharper disable once LocalVariableHidesMember -- this is deliberate
+ Dictionary<string, string> localizedAssetNames = this.Coordinator.LocalizedAssetNames.Value;
+ if (!localizedAssetNames.TryGetValue(assetName.Name, out _))
{
string localeCode = this.LanguageCodeString(language);
IAssetName localizedName = new AssetName(baseName: assetName.BaseName, localeCode: localeCode, languageCode: language);
@@ -161,7 +163,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
try
{
T data = this.LoadExact<T>(localizedName, useCache: useCache);
- LocalizedContentManager.localizedAssetNames[assetName.Name] = localizedName.Name;
+ localizedAssetNames[assetName.Name] = localizedName.Name;
return data;
}
catch (ContentLoadException)
@@ -170,18 +172,18 @@ namespace StardewModdingAPI.Framework.ContentManagers
try
{
T data = this.LoadExact<T>(localizedName, useCache: useCache);
- LocalizedContentManager.localizedAssetNames[assetName.Name] = localizedName.Name;
+ localizedAssetNames[assetName.Name] = localizedName.Name;
return data;
}
catch (ContentLoadException)
{
- LocalizedContentManager.localizedAssetNames[assetName.Name] = assetName.Name;
+ localizedAssetNames[assetName.Name] = assetName.Name;
}
}
}
// use cached key
- string rawName = LocalizedContentManager.localizedAssetNames[assetName.Name];
+ string rawName = localizedAssetNames[assetName.Name];
if (assetName.Name != rawName)
assetName = this.Coordinator.ParseAssetName(rawName, allowLocales: this.TryLocalizeKeys);
return this.LoadExact<T>(assetName, useCache: useCache);
diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
index 38a21383..1b94b8c6 100644
--- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
@@ -176,7 +176,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
return asset;
}
- /// <summary>Load an unpacked image file (<c>.json</c>).</summary>
+ /// <summary>Load an unpacked image file (<c>.png</c>).</summary>
/// <typeparam name="T">The type of asset to load.</typeparam>
/// <param name="assetName">The asset name relative to the loader root directory.</param>
/// <param name="file">The file to load.</param>
diff --git a/src/SMAPI/Framework/Deprecations/DeprecationManager.cs b/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
index 3bbbd7b8..4597a764 100644
--- a/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
+++ b/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
@@ -95,6 +95,9 @@ namespace StardewModdingAPI.Framework.Deprecations
/// <summary>Print any queued messages.</summary>
public void PrintQueued()
{
+ if (!this.QueuedWarnings.Any())
+ return;
+
foreach (DeprecationWarning warning in this.QueuedWarnings.OrderBy(p => p.ModName).ThenBy(p => p.NounPhrase))
{
// build message
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index 7042e83a..67f78400 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -596,6 +596,7 @@ namespace StardewModdingAPI.Framework
/*********
** Execute commands
*********/
+ if (this.ScreenCommandQueue.Value.Any())
{
var commandQueue = this.ScreenCommandQueue.Value;
foreach ((Command? command, string? name, string[]? args) in commandQueue)
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, TV