Files
Performance-Fish/Source/PerformanceFish/IdeoUtilityCaching.cs
T

72 lines
2.1 KiB
C#

// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using PerformanceFish.Prepatching;
using StyleDominanceCache
= PerformanceFish.Cache.ByInt<Verse.Thing, RimWorld.Ideo,
PerformanceFish.IdeoUtilityCaching.StyleDominanceCacheValue>;
namespace PerformanceFish;
public sealed class IdeoUtilityCaching : ClassWithFishPrepatches
{
public sealed class GetStyleDominance_Patch : FishPrepatch
{
public override string Description { get; }
= "Caches IdeoUtility.GetStyleDominance to only update about once every 900 ticks or so.";
public override MethodBase TargetMethodBase { get; } = methodof(IdeoUtility.GetStyleDominance);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Prefix(Thing? t, Ideo? ideo, ref float __result, out bool __state)
{
if (t is null || ideo is null || t.thingIDNumber < 0)
{
__state = false;
return true;
}
ref var cache = ref StyleDominanceCache.GetOrAddReference(new(t.thingIDNumber, ideo.id));
if (cache.Dirty)
return __state = true;
__result = cache.Value;
return __state = false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Postfix(Thing t, Ideo ideo, bool __state, float __result)
{
if (!__state)
return;
UpdateCache(t, ideo, __result);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void UpdateCache(Thing t, Ideo ideo, float __result)
=> StyleDominanceCache.GetExistingReference(t, ideo).Update(__result, t);
}
public record struct StyleDominanceCacheValue
{
public float Value;
private int _nextRefreshTick;
public void Update(float value, Thing thing)
{
Value = value;
_nextRefreshTick = TickHelper.Add(900 - 128, thing.thingIDNumber, 256);
// Pawn_StyleObserverTracker.StyleObservableTick runs every 900 ticks
}
public bool Dirty
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => TickHelper.Past(_nextRefreshTick);
}
}
}