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);
}
}
}
}