using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Panik;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CloverPerformance")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CloverPerformance")]
[assembly: AssemblyTitle("CloverPerformance")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace AethaPerformancePatches
{
[BepInPlugin("Aetha.PerformancePatches", "AethaPerformancePatches", "1.0.0")]
public class AethaPerformancePatches : BaseUnityPlugin
{
public class PerformancePatchConfig
{
public bool SkipRerollSaves = true;
public bool CacheStrings = true;
public bool CacheBigIntegerMath = true;
public bool PatchStringsSanitize = true;
}
private const string ConfigFilename = "PerformanceConfig.json";
public static PerformancePatchConfig config = new PerformancePatchConfig();
private static string AssemblyDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private static string ConfigPath => AssemblyDirectory + "/PerformanceConfig.json";
private void Awake()
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
if (Directory.Exists(AssemblyDirectory))
{
if (File.Exists(ConfigPath))
{
config = JsonUtility.FromJson<PerformancePatchConfig>(File.ReadAllText(ConfigPath));
}
else
{
File.WriteAllText(ConfigPath, JsonUtility.ToJson((object)config));
}
}
new Harmony("Aetha.PerformancePatches").PatchAll();
}
}
[HarmonyPatch(typeof(Data))]
internal static class DataPatches
{
[CompilerGenerated]
private sealed class <AsyncTrue>d__2 : IAsyncStateMachine
{
public int <>1__state;
public AsyncUniTaskMethodBuilder<bool> <>t__builder;
private void MoveNext()
{
int num = <>1__state;
bool result;
try
{
result = true;
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
return;
}
<>1__state = -2;
<>t__builder.SetResult(result);
}
void IAsyncStateMachine.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
this.MoveNext();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
}
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
this.SetStateMachine(stateMachine);
}
}
[HarmonyPrepare]
private static bool Prepare()
{
return AethaPerformancePatches.config.SkipRerollSaves;
}
[HarmonyPrefix]
[HarmonyPatch("SaveGame")]
private static bool SaveGamePrefix(GameSavingReason reasonForSaving, ref UniTask<bool> __result)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (reasonForSaving - 13 <= 1)
{
__result = AsyncTrue();
return false;
}
return true;
}
[AsyncStateMachine(typeof(<AsyncTrue>d__2))]
[DebuggerStepThrough]
private static UniTask<bool> AsyncTrue()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
<AsyncTrue>d__2 <AsyncTrue>d__ = new <AsyncTrue>d__2();
<AsyncTrue>d__.<>t__builder = AsyncUniTaskMethodBuilder<bool>.Create();
<AsyncTrue>d__.<>1__state = -1;
<AsyncTrue>d__.<>t__builder.Start<<AsyncTrue>d__2>(ref <AsyncTrue>d__);
return <AsyncTrue>d__.<>t__builder.Task;
}
}
[HarmonyPatch(typeof(Strings))]
internal static class StringsCachePatches
{
private static readonly Dictionary<string, (string value, int frame)> Cache = new Dictionary<string, (string, int)>();
private static int _latestFrame = -1;
private static readonly HashSet<string> NeverCacheStrings = new HashSet<string>();
private static readonly string[] DoNotCache = new string[3] { "[START_PROMPT]", "[INPUTS_MOVE]", "[CHARGE_BAR]" };
[HarmonyPrepare]
private static bool Prepare()
{
return AethaPerformancePatches.config.CacheStrings;
}
public static void MarkDirty()
{
_latestFrame = Time.frameCount;
}
[HarmonyPrefix]
[HarmonyPatch("Sanitize")]
private static bool SanitizePrefix(SantizationKind santizationKind, string input, SanitizationSubKind subKind, ref string __result)
{
if (Cache.TryGetValue(input, out (string, int) value) && value.Item2 > _latestFrame)
{
__result = Cache[input].value;
return false;
}
return true;
}
[HarmonyPostfix]
[HarmonyPatch("Sanitize")]
private static void SanitizePostfix(SantizationKind santizationKind, string input, SanitizationSubKind subKind, ref string __result)
{
if (Cache.TryGetValue(input, out (string, int) value))
{
Cache[input] = (__result, Mathf.Max(value.Item2, Time.frameCount));
}
else if (!input.Contains("[") && !input.Contains("]"))
{
Cache[input] = (__result, int.MaxValue);
}
else
{
if (NeverCacheStrings.Contains(input))
{
return;
}
string[] doNotCache = DoNotCache;
foreach (string value2 in doNotCache)
{
if (input.Contains(value2))
{
NeverCacheStrings.Add(input);
return;
}
}
Cache[input] = (__result, Time.frameCount);
}
}
}
[HarmonyPatch(typeof(GameplayData))]
internal static class GameplayDataCachePatches
{
[HarmonyPrepare]
private static bool Prepare()
{
return AethaPerformancePatches.config.CacheStrings;
}
[HarmonyPostfix]
[HarmonyPatch]
private static void MarkDirtyPostfix()
{
StringsCachePatches.MarkDirty();
}
[HarmonyTargetMethods]
private static IEnumerable<MethodBase> CalculateMethods()
{
return from x in AccessTools.GetDeclaredMethods(typeof(GameplayData))
where x.Name.EndsWith("Set")
select x;
}
}
[HarmonyPatch(typeof(GameplayData))]
internal static class BigIntegerCachePatches
{
private static readonly Dictionary<string, int> CacheTimestamps = new Dictionary<string, int>();
private static readonly Dictionary<string, object> CachedValues = new Dictionary<string, object>();
[HarmonyPrepare]
private static bool Prepare()
{
return AethaPerformancePatches.config.CacheBigIntegerMath;
}
[HarmonyTargetMethods]
private static IEnumerable<MethodBase> CalculateMethods()
{
yield return AccessTools.Method(typeof(GameplayData), "InterestEarnedHypotetically", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "GetHypotehticalMaxSpinsBuyable", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "GetHypotehticalMidSpinsBuyable", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "DebtGetExt", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "SpinCostGet_Single", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "DebtGet", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "SpinCostMid_Get", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "SpinCostMax_Get", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "InterestRateGet", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "DebtIndexGet", (Type[])null, (Type[])null);
yield return AccessTools.Method(typeof(GameplayData), "DeadlineReward_CoinsGet", (Type[])null, (Type[])null);
}
[HarmonyPatch]
[HarmonyPrefix]
private static bool FrameCachedValue(MethodBase __originalMethod, ref object __result)
{
if (TryGetCachedValue(__originalMethod.Name, out object value))
{
__result = value;
return false;
}
return true;
}
[HarmonyPatch]
[HarmonyPostfix]
private static void CacheCurrentResult(MethodBase __originalMethod, ref object __result)
{
if (!CacheTimestamps.TryGetValue(__originalMethod.Name, out var value) || Time.frameCount != value)
{
CacheTimestamps[__originalMethod.Name] = Time.frameCount;
CachedValues[__originalMethod.Name] = __result;
}
}
private static bool TryGetCachedValue(string key, out object value)
{
if (CacheTimestamps.TryGetValue(key, out var value2))
{
if (Time.frameCount != value2)
{
value = BigInteger.Zero;
return false;
}
if (CachedValues.TryGetValue(key, out object value3))
{
value = value3;
return true;
}
}
value = BigInteger.Zero;
return false;
}
}
[HarmonyPatch(typeof(Strings))]
[HarmonyPatch("Sanitize")]
internal static class StringsPatches
{
private static readonly string[] KeyReplacements = new string[7] { "[DEBT]", "[DEBT_NEXT]", "[DEBT_30%]", "[INTEREST_REV]", "[2X_INTEREST_REV]", "[3X_INTEREST_REV]", "[REWARD_DEBT_AMMOUNT]" };
[HarmonyPrepare]
private static bool Prepare()
{
return AethaPerformancePatches.config.PatchStringsSanitize;
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator)
{
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Expected O, but got Unknown
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Expected O, but got Unknown
List<CodeInstruction> list = instructions.ToList();
Label label = default(Label);
int num = -1;
int num2 = -1;
for (int i = 0; i < list.Count; i++)
{
if (list[i].opcode == OpCodes.Ldstr && list[i].operand is string && KeyReplacements.Contains((string)list[i].operand))
{
num = i - 1;
num2 = -1;
}
if (list[i].opcode == OpCodes.Pop && num >= 0)
{
label = ilGenerator.DefineLabel();
list[i + 1].labels.Add(label);
num2 = i;
}
if (num >= 0 && num2 >= 0)
{
CodeInstruction item = list[num];
list.RemoveAt(num);
CodeInstruction item2 = list[num];
list.RemoveAt(num);
list.Insert(num++, new CodeInstruction(OpCodes.Ldarg_1, (object)null));
list.Insert(num++, item2);
list.Insert(num++, CodeInstruction.Call(typeof(string), "Contains", new Type[1] { typeof(string) }, (Type[])null));
list.Insert(num++, new CodeInstruction(OpCodes.Brfalse_S, (object)label));
list.Insert(num++, item);
list.Insert(num++, item2);
i = num2 + 4;
num = -1;
num2 = -1;
}
}
return list.AsEnumerable();
}
}
}