From b07d2340a9a6da22ee0fd95f2c6ccca3939cb7ab Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 22 Mar 2022 23:00:18 -0400 Subject: encapsulate & cache asset operation groups (#766) This is needed for the upcoming Stardew Valley 1.6 to avoid duplicate checks between DoesAssetExist and Load calls, and to make sure the answer doesn't change between them. --- .../Framework/Utilities/TickCacheDictionary.cs | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/SMAPI/Framework/Utilities/TickCacheDictionary.cs (limited to 'src/SMAPI/Framework/Utilities') diff --git a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs new file mode 100644 index 00000000..1613a480 --- /dev/null +++ b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using StardewValley; + +namespace StardewModdingAPI.Framework.Utilities +{ + /// An in-memory dictionary cache that stores data for the duration of a game update tick. + /// The dictionary key type. + /// The dictionary value type. + internal class TickCacheDictionary + { + /********* + ** Fields + *********/ + /// The last game tick for which data was cached. + private int LastGameTick = -1; + + /// The underlying cached data. + private readonly Dictionary Cache = new(); + + + /********* + ** Public methods + *********/ + /// Get a value from the cache, fetching it first if it's not cached yet. + /// The unique key for the cached value. + /// Get the latest data if it's not in the cache yet. + public TValue GetOrSet(TKey cacheKey, Func get) + { + // clear cache on new tick + if (Game1.ticks != this.LastGameTick) + { + this.Cache.Clear(); + this.LastGameTick = Game1.ticks; + } + + // fetch value + if (!this.Cache.TryGetValue(cacheKey, out TValue cached)) + this.Cache[cacheKey] = cached = get(); + return cached; + } + + /// Remove an entry from the cache. + /// The unique key for the cached value. + /// Returns whether the key was present in the dictionary. + public bool Remove(TKey cacheKey) + { + return this.Cache.Remove(cacheKey); + } + } +} -- cgit From 6292b21f220d1936f8d2a5e1c883c9664be4973d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Apr 2022 14:59:09 -0400 Subject: fix tick cache using game ticks instead of SMAPI ticks The game ticks aren't incremented consistently in some cases (e.g. while loading a save), which leads to the cache values being kept too long. --- src/SMAPI/Framework/Utilities/TickCacheDictionary.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework/Utilities') diff --git a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs index 1613a480..5921e089 100644 --- a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs +++ b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Framework.Utilities ** Fields *********/ /// The last game tick for which data was cached. - private int LastGameTick = -1; + private uint? LastGameTick; /// The underlying cached data. private readonly Dictionary Cache = new(); @@ -28,10 +28,10 @@ namespace StardewModdingAPI.Framework.Utilities public TValue GetOrSet(TKey cacheKey, Func get) { // clear cache on new tick - if (Game1.ticks != this.LastGameTick) + if (SCore.TicksElapsed != this.LastGameTick) { this.Cache.Clear(); - this.LastGameTick = Game1.ticks; + this.LastGameTick = SCore.TicksElapsed; } // fetch value -- cgit From 546b58778c9e1e983f1682f1b89cbc353939d9ea Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 2 Apr 2022 19:13:27 -0400 Subject: switch to 'processing tick' for tick caching This is incremented on each low-level tick (whether it's a game update, synchronized async operation, etc). That mainly avoids the cache persisting across the entire save loading process while it's being synchronized. --- src/SMAPI/Framework/Utilities/TickCacheDictionary.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework/Utilities') diff --git a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs index 5921e089..d0f276d2 100644 --- a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs +++ b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using StardewValley; namespace StardewModdingAPI.Framework.Utilities { @@ -28,10 +27,10 @@ namespace StardewModdingAPI.Framework.Utilities public TValue GetOrSet(TKey cacheKey, Func get) { // clear cache on new tick - if (SCore.TicksElapsed != this.LastGameTick) + if (SCore.ProcessTicksElapsed != this.LastGameTick) { this.Cache.Clear(); - this.LastGameTick = SCore.TicksElapsed; + this.LastGameTick = SCore.ProcessTicksElapsed; } // fetch value -- cgit From 2e7c233f6c9bf6430672b39f970a3324deba79dd Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 6 Apr 2022 21:48:55 -0400 Subject: enable nullable annotations by default (#837) This adds `#nullable disable` to all existing code (except where null is impossible like enum files), so it can be migrated incrementally. --- src/SMAPI/Framework/Utilities/ContextHash.cs | 2 ++ src/SMAPI/Framework/Utilities/Countdown.cs | 2 +- src/SMAPI/Framework/Utilities/TickCacheDictionary.cs | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/SMAPI/Framework/Utilities') diff --git a/src/SMAPI/Framework/Utilities/ContextHash.cs b/src/SMAPI/Framework/Utilities/ContextHash.cs index 6c0fdc90..46b9099e 100644 --- a/src/SMAPI/Framework/Utilities/ContextHash.cs +++ b/src/SMAPI/Framework/Utilities/ContextHash.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; diff --git a/src/SMAPI/Framework/Utilities/Countdown.cs b/src/SMAPI/Framework/Utilities/Countdown.cs index 342b4258..94c69e73 100644 --- a/src/SMAPI/Framework/Utilities/Countdown.cs +++ b/src/SMAPI/Framework/Utilities/Countdown.cs @@ -1,4 +1,4 @@ -namespace StardewModdingAPI.Framework.Utilities +namespace StardewModdingAPI.Framework.Utilities { /// Counts down from a baseline value. internal class Countdown diff --git a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs index d0f276d2..94ce0069 100644 --- a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs +++ b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using System.Collections.Generic; -- cgit From 6e9e8aef1ef97e1a4ef4410ce300cb1c47eca986 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 13 Apr 2022 19:00:24 -0400 Subject: enable nullable annotations in SMAPI where no changes are needed (#837) --- src/SMAPI/Framework/Utilities/ContextHash.cs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/SMAPI/Framework/Utilities') diff --git a/src/SMAPI/Framework/Utilities/ContextHash.cs b/src/SMAPI/Framework/Utilities/ContextHash.cs index 46b9099e..6c0fdc90 100644 --- a/src/SMAPI/Framework/Utilities/ContextHash.cs +++ b/src/SMAPI/Framework/Utilities/ContextHash.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; -- cgit From f39da383a17b368e92fd243cf155b27ba42671f3 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 13 Apr 2022 20:24:14 -0400 Subject: enable nullable annotations in SMAPI where no logic changes are needed (#837) --- src/SMAPI/Framework/Utilities/TickCacheDictionary.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/SMAPI/Framework/Utilities') diff --git a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs index 94ce0069..20d206e2 100644 --- a/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs +++ b/src/SMAPI/Framework/Utilities/TickCacheDictionary.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; @@ -9,6 +7,7 @@ namespace StardewModdingAPI.Framework.Utilities /// The dictionary key type. /// The dictionary value type. internal class TickCacheDictionary + where TKey : notnull { /********* ** Fields @@ -36,7 +35,7 @@ namespace StardewModdingAPI.Framework.Utilities } // fetch value - if (!this.Cache.TryGetValue(cacheKey, out TValue cached)) + if (!this.Cache.TryGetValue(cacheKey, out TValue? cached)) this.Cache[cacheKey] = cached = get(); return cached; } -- cgit