using System; using System.Collections.Generic; 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 where TKey : notnull { /********* ** Fields *********/ /// The last game tick for which data was cached. private uint? LastGameTick; /// 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 (SCore.ProcessTicksElapsed != this.LastGameTick) { this.Cache.Clear(); this.LastGameTick = SCore.ProcessTicksElapsed; } // 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); } } /// An in-memory dictionary cache that stores data for the duration of a game update tick. /// The dictionary key type. internal class TickCacheDictionary : TickCacheDictionary where TKey : notnull { /********* ** 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) { object? value = base.GetOrSet(cacheKey, () => get()!); try { return (TValue)value; } catch (Exception ex) { throw new InvalidCastException($"Can't cast value of the '{cacheKey}' cache entry from {value?.GetType().FullName ?? "null"} to {typeof(TValue).FullName}.", ex); } } } }