Decompiled source of PerformanceEnhancedMenu v2.3.1

BepInEx/plugins/PerformanceEnhancedMenu.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.Math;
using Pigeon.Movement;
using Pigeon.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("PerformanceEnhancedMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.0.0")]
[assembly: AssemblyInformationalVersion("0.0.0-alpha.0.5+d6f427ecb324fcdcc95d444b8f51f209de322a5d")]
[assembly: AssemblyProduct("PerformanceEnhancedMenu")]
[assembly: AssemblyTitle("PerformanceEnhancedMenu")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public static class AsynchronousPrecalcPatches
{
	public static class GearSlotOnPointerEnterPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearSlot), "OnPointerEnter", new Type[1] { typeof(PointerEventData) }, (Type[])null);
		}

		public static void Postfix(GearSlot __instance)
		{
			try
			{
				if (__instance.Gear != null)
				{
					StartPrecalculation(__instance.Gear);
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearSlotOnPointerEnterPatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	public static class GearSlotOnPointerExitPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearSlot), "OnPointerExit", new Type[1] { typeof(PointerEventData) }, (Type[])null);
		}

		public static void Postfix()
		{
			try
			{
				currentlyPrecalculating = null;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearSlotOnPointerExitPatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	[CompilerGenerated]
	private sealed class <PrecalculateStats>d__4 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public IUpgradable gear;

		private GearData <gearData>5__2;

		private List<object>.Enumerator <>7__wrap2;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <PrecalculateStats>d__4(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			int num = <>1__state;
			if (num == -3 || num == 1)
			{
				try
				{
				}
				finally
				{
					<>m__Finally1();
				}
			}
			<gearData>5__2 = null;
			<>7__wrap2 = default(List<object>.Enumerator);
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			bool result;
			try
			{
				int num = <>1__state;
				if (num == 0)
				{
					<>1__state = -1;
					PerformanceEnhancedMenuPlugin.GetCachedEquippedUpgrade(gear, 0, 0);
					<gearData>5__2 = PlayerData.GetGearData(gear);
					if (StatCalcPatches.equippedUpgradesField.GetValue(<gearData>5__2) is IList list)
					{
						List<object> list2 = new List<object>();
						foreach (object item in list)
						{
							list2.Add(item);
						}
						<>7__wrap2 = list2.GetEnumerator();
						<>1__state = -3;
						goto IL_010e;
					}
					goto IL_0137;
				}
				if (num == 1)
				{
					<>1__state = -3;
					goto IL_010e;
				}
				result = false;
				goto end_IL_0000;
				IL_0137:
				if (gear is MiniCannon && !PerformanceEnhancedMenuPlugin.deferExpensiveCalculations)
				{
					StatCalcPatches.RecomputeTotals(<gearData>5__2);
				}
				currentlyPrecalculating = null;
				result = false;
				goto end_IL_0000;
				IL_010e:
				if (!<>7__wrap2.MoveNext())
				{
					<>m__Finally1();
					<>7__wrap2 = default(List<object>.Enumerator);
					goto IL_0137;
				}
				object current2 = <>7__wrap2.Current;
				if (currentlyPrecalculating != gear)
				{
					result = false;
					<>m__Finally1();
				}
				else
				{
					UpgradeInstance val = (UpgradeInstance)StatCalcPatches.getUpgradeMethod.Invoke(current2, null);
					if (val != null)
					{
						PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(gear, val);
					}
					<>2__current = null;
					<>1__state = 1;
					result = true;
				}
				end_IL_0000:;
			}
			catch
			{
				//try-fault
				((IDisposable)this).Dispose();
				throw;
			}
			return result;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		private void <>m__Finally1()
		{
			<>1__state = -1;
			((IDisposable)<>7__wrap2).Dispose();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static IUpgradable currentlyPrecalculating;

	private static void StartPrecalculation(IUpgradable gear)
	{
		if (currentlyPrecalculating != gear)
		{
			currentlyPrecalculating = gear;
			IEnumerator enumerator = PrecalculateStats(gear);
			if ((Object)(object)Menu.Instance != (Object)null)
			{
				((MonoBehaviour)Menu.Instance).StartCoroutine(enumerator);
			}
		}
	}

	[IteratorStateMachine(typeof(<PrecalculateStats>d__4))]
	private static IEnumerator PrecalculateStats(IUpgradable gear)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <PrecalculateStats>d__4(0)
		{
			gear = gear
		};
	}
}
public static class CellTouchingPatches
{
	public static class GetConnectedPrismCountRecursivePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("UpgradeProperty_MiniCannon_Prism"), "GetConnectedPrismCountRecursive", new Type[2]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance)
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable prefab, UpgradeInstance upgrade, ref int __result)
		{
			try
			{
				if (StatCalcPatches.prismConnectedCounts.TryGetValue(upgrade.InstanceID, out var value))
				{
					__result = value;
					return false;
				}
				if (PerformanceEnhancedMenuPlugin.deferExpensiveCalculations)
				{
					__result = 1;
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetConnectedPrismCountRecursivePatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class GetNumCellsTouchingThisPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(UpgradeProperty), "GetNumCellsTouchingThis", new Type[3]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance),
				StatCalcPatches.rarityFlagsType
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable prefab, UpgradeInstance upgrade, object rarities, ref int __result)
		{
			try
			{
				PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
				if (PerformanceEnhancedMenuPlugin.cellTouchingCache.TryGetValue(upgrade.InstanceID, out (int, int, int, int) value))
				{
					if (!rarities.Equals(StatCalcPatches.rarityFlagsStandard))
					{
						if (rarities.Equals(StatCalcPatches.rarityFlagsRare))
						{
							return true;
						}
						if (rarities.Equals(StatCalcPatches.rarityFlagsEpic))
						{
							return true;
						}
						if (rarities.Equals(StatCalcPatches.rarityFlagsExotic))
						{
							return true;
						}
						(__result, _, _, _) = value;
						return false;
					}
					(__result, _, _, _) = value;
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetNumCellsTouchingThisPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class GetNumRaritiesTouchingThisPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("UpgradeProperty"), "GetNumRaritiesTouchingThis", new Type[2]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance)
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable prefab, UpgradeInstance upgrade, ref int __result)
		{
			try
			{
				PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
				if (PerformanceEnhancedMenuPlugin.cellTouchingCache.TryGetValue(upgrade.InstanceID, out (int, int, int, int) value))
				{
					__result = value.Item4;
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetNumRaritiesTouchingThisPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class GetNumCellsTouchingThisNonRarityPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("UpgradeProperty"), "GetNumCellsTouchingThis", new Type[2]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance)
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable prefab, UpgradeInstance upgrade, ref int __result)
		{
			try
			{
				if (PerformanceEnhancedMenuPlugin.deferExpensiveCalculations)
				{
					PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
					__result = 0;
					return false;
				}
				PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
				if (!PerformanceEnhancedMenuPlugin.cellTouchingCache.TryGetValue(upgrade.InstanceID, out (int, int, int, int) value))
				{
					return true;
				}
				(__result, _, _, _) = value;
				return false;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetNumCellsTouchingThisNonRarityPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class GetNumEmptyCellsTouchingThisPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("UpgradeProperty"), "GetNumEmptyCellsTouchingThis", new Type[2]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance)
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable prefab, UpgradeInstance upgrade, ref int __result)
		{
			try
			{
				if (PerformanceEnhancedMenuPlugin.deferExpensiveCalculations)
				{
					PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
					__result = 0;
					return false;
				}
				PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
				if (PerformanceEnhancedMenuPlugin.cellTouchingCache.TryGetValue(upgrade.InstanceID, out (int, int, int, int) value))
				{
					__result = value.Item2;
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetNumEmptyCellsTouchingThisPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class GetNumUniqueUpgradesTouchingThisPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(AccessTools.TypeByName("UpgradeProperty"), "GetNumUniqueUpgradesTouchingThis", new Type[2]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance)
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable prefab, UpgradeInstance upgrade, ref int __result)
		{
			try
			{
				PerformanceEnhancedMenuPlugin.ComputeCellTouchingStats(prefab, upgrade);
				if (PerformanceEnhancedMenuPlugin.cellTouchingCache.TryGetValue(upgrade.InstanceID, out (int, int, int, int) value))
				{
					__result = value.Item3;
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetNumUniqueUpgradesTouchingThisPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}
}
public static class DebouncePatches
{
	public static class GearDataEquipUpgradePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearData), "EquipUpgrade", new Type[5]
			{
				typeof(UpgradeInstance),
				typeof(sbyte),
				typeof(sbyte),
				typeof(byte),
				typeof(bool)
			}, (Type[])null);
		}

		public static void Postfix(GearData __instance, UpgradeInstance upgrade, sbyte x, sbyte y, byte rotation, bool sort)
		{
			try
			{
				PerformanceEnhancedMenuPlugin.StartDebounce();
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDataEquipUpgradePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	public static class GearDataUnequipUpgradePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearData), "UnequipUpgrade", new Type[1] { typeof(UpgradeInstance) }, (Type[])null);
		}

		public static void Postfix()
		{
			try
			{
				PerformanceEnhancedMenuPlugin.StartDebounce();
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDataUnequipUpgradePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}
}
public static class GeneralPatches
{
	public static class EquipUpgradePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearData), "EquipUpgrade", new Type[5]
			{
				typeof(UpgradeInstance),
				typeof(sbyte),
				typeof(sbyte),
				typeof(byte),
				typeof(bool)
			}, (Type[])null);
		}

		public static void Postfix(GearData __instance, UpgradeInstance upgrade, sbyte x, sbyte y, byte rotation, bool sort)
		{
			try
			{
				if (!StatCalcPatches.skipRecompute)
				{
					StatCalcPatches.ClearCaches();
					PerformanceEnhancedMenuPlugin.ClearAllCaches();
					StatCalcPatches.RecomputeTotals(__instance);
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in EquipUpgradePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	public static class UnequipUpgradePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearData), "UnequipUpgrade", new Type[1] { typeof(UpgradeInstance) }, (Type[])null);
		}

		public static void Postfix(GearData __instance, UpgradeInstance upgrade)
		{
			try
			{
				StatCalcPatches.prismConnectedCounts.Remove(upgrade.InstanceID);
				StatCalcPatches.rarityTouchingCounts.Remove(upgrade.InstanceID);
				if (!StatCalcPatches.skipRecompute)
				{
					StatCalcPatches.ClearCaches();
					PerformanceEnhancedMenuPlugin.ClearAllCaches();
					StatCalcPatches.RecomputeTotals(__instance);
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in UnequipUpgradePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	public static class GetEquippedUpgradePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PlayerData), "GetEquippedUpgrade", new Type[3]
			{
				typeof(IUpgradable),
				typeof(int),
				typeof(int)
			}, (Type[])null);
		}

		public static bool Prefix(IUpgradable gear, int x, int y, ref UpgradeInstance __result)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int iD = gear.Info.ID;
				if (!StatCalcPatches.upgradeGridCache.TryGetValue(iD, out var value))
				{
					int num = default(int);
					int num2 = default(int);
					gear.Info.GetUpgradeGridSize(ref num, ref num2, false);
					value = new UpgradeInstance[num, num2];
					GearData gearData = PlayerData.GetGearData(gear);
					foreach (object item in (IList)StatCalcPatches.equippedUpgradesField.GetValue(gearData))
					{
						UpgradeInstance val = (UpgradeInstance)StatCalcPatches.getUpgradeMethod.Invoke(item, null);
						if (val == null)
						{
							continue;
						}
						EquippedCellsEnumerator equippedCells = val.GetEquippedCells(gear);
						try
						{
							while (((EquippedCellsEnumerator)(ref equippedCells)).MoveNext())
							{
								value[((EquippedCellsEnumerator)(ref equippedCells)).X, ((EquippedCellsEnumerator)(ref equippedCells)).Y] = val;
							}
						}
						finally
						{
							((IDisposable)(EquippedCellsEnumerator)(ref equippedCells)).Dispose();
						}
					}
					StatCalcPatches.upgradeGridCache[iD] = value;
				}
				__result = value[x, y];
				return false;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GetEquippedUpgradePatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}
}
public static class PerformanceEnhancedMenuPlugin
{
	[CompilerGenerated]
	private sealed class <DebounceCoroutine>d__15 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DebounceCoroutine>d__15(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				deferExpensiveCalculations = false;
				debounceCoroutine = null;
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	internal static Dictionary<(int gearId, int x, int y), UpgradeInstance> upgradeGridCache = new Dictionary<(int, int, int), UpgradeInstance>();

	internal static Dictionary<int, (int cellsTouching, int emptyCellsTouching, int uniqueUpgradesTouching, int numRaritiesTouching)> cellTouchingCache = new Dictionary<int, (int, int, int, int)>();

	internal static Dictionary<int, HashSet<(int x, int y)>> surroundingCellsCache = new Dictionary<int, HashSet<(int, int)>>();

	internal static Dictionary<GearUpgradeUI, (Vector2 position, bool borderActive)> upgradeUICache = new Dictionary<GearUpgradeUI, (Vector2, bool)>();

	internal static Dictionary<UpgradeEquipCell, Color> cellColorCache = new Dictionary<UpgradeEquipCell, Color>();

	private static float lastUpgradeListUpdate = 0f;

	private static float lastBorderUpdate = 0f;

	private static readonly float UPDATE_THROTTLE = 0.1f;

	internal static bool deferExpensiveCalculations = false;

	private static Coroutine debounceCoroutine;

	internal static float lastUpgradeCollectionTime = 0f;

	internal static readonly float UPGRADE_COLLECTION_THROTTLE = 0.2f;

	public static void ClearUICaches()
	{
		upgradeUICache.Clear();
		cellColorCache.Clear();
	}

	public static void ClearAllCaches()
	{
		upgradeGridCache.Clear();
		cellTouchingCache.Clear();
		surroundingCellsCache.Clear();
		ClearUICaches();
	}

	public static void StartDebounce()
	{
		deferExpensiveCalculations = true;
		if (debounceCoroutine != null)
		{
			((MonoBehaviour)Menu.Instance).StopCoroutine(debounceCoroutine);
		}
		debounceCoroutine = ((MonoBehaviour)Menu.Instance).StartCoroutine(DebounceCoroutine());
	}

	[IteratorStateMachine(typeof(<DebounceCoroutine>d__15))]
	private static IEnumerator DebounceCoroutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DebounceCoroutine>d__15(0);
	}

	public static UpgradeInstance GetCachedEquippedUpgrade(IUpgradable gear, int x, int y)
	{
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		int num = default(int);
		int num2 = default(int);
		gear.Info.GetUpgradeGridSize(ref num, ref num2, false);
		if (x < 0 || x >= num || y < 0 || y >= num2)
		{
			return null;
		}
		int iD = gear.Info.ID;
		(int, int, int) key = (iD, x, y);
		if (!upgradeGridCache.TryGetValue(key, out var value))
		{
			UpgradeInstance[,] array = new UpgradeInstance[num, num2];
			GearData gearData = PlayerData.GetGearData(gear);
			if (StatCalcPatches.equippedUpgradesField.GetValue(gearData) is IList list)
			{
				foreach (object item in list)
				{
					UpgradeInstance val = (UpgradeInstance)StatCalcPatches.getUpgradeMethod.Invoke(item, null);
					if (val == null)
					{
						continue;
					}
					EquippedCellsEnumerator equippedCells = val.GetEquippedCells(gear);
					try
					{
						while (((EquippedCellsEnumerator)(ref equippedCells)).MoveNext())
						{
							int x2 = ((EquippedCellsEnumerator)(ref equippedCells)).X;
							int y2 = ((EquippedCellsEnumerator)(ref equippedCells)).Y;
							if (x2 >= 0 && x2 < num && y2 >= 0 && y2 < num2)
							{
								array[x2, y2] = val;
							}
						}
					}
					finally
					{
						((IDisposable)(EquippedCellsEnumerator)(ref equippedCells)).Dispose();
					}
				}
			}
			for (int i = 0; i < num; i++)
			{
				for (int j = 0; j < num2; j++)
				{
					upgradeGridCache[(iD, i, j)] = array[i, j];
				}
			}
			return array[x, y];
		}
		return value;
	}

	public static void ComputeCellTouchingStats(IUpgradable gear, UpgradeInstance upgrade)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		if (cellTouchingCache.ContainsKey(upgrade.InstanceID))
		{
			return;
		}
		if (!surroundingCellsCache.TryGetValue(upgrade.InstanceID, out HashSet<(int, int)> value))
		{
			value = new HashSet<(int, int)>();
			EquippedCellsEnumerator equippedCells = upgrade.GetEquippedCells(gear);
			try
			{
				while (((EquippedCellsEnumerator)(ref equippedCells)).MoveNext())
				{
					int x = ((EquippedCellsEnumerator)(ref equippedCells)).X;
					int y = ((EquippedCellsEnumerator)(ref equippedCells)).Y;
					int num = ((x % 2 == 0) ? (-1) : 0);
					value.Add((x, y + 1));
					value.Add((x, y - 1));
					value.Add((x - 1, y + num));
					value.Add((x - 1, y + 1 + num));
					value.Add((x + 1, y + num));
					value.Add((x + 1, y + 1 + num));
				}
			}
			finally
			{
				((IDisposable)(EquippedCellsEnumerator)(ref equippedCells)).Dispose();
			}
			surroundingCellsCache[upgrade.InstanceID] = value;
		}
		int num2 = 0;
		int num3 = 0;
		HashSet<UpgradeInstance> hashSet = new HashSet<UpgradeInstance>();
		HashSet<Rarity> hashSet2 = new HashSet<Rarity>();
		int num4 = default(int);
		int num5 = default(int);
		foreach (var item in value)
		{
			gear.Info.GetUpgradeGridSize(ref num4, ref num5, false);
			if (item.Item1 >= 0 && item.Item1 < num4 && item.Item2 >= 0 && item.Item2 < num5)
			{
				UpgradeInstance cachedEquippedUpgrade = GetCachedEquippedUpgrade(gear, item.Item1, item.Item2);
				if (cachedEquippedUpgrade != null)
				{
					num2++;
					hashSet.Add(cachedEquippedUpgrade);
					hashSet2.Add(cachedEquippedUpgrade.Upgrade.Rarity);
				}
				else
				{
					num3++;
				}
			}
		}
		cellTouchingCache[upgrade.InstanceID] = (num2, num3, hashSet.Count, hashSet2.Count);
	}
}
public static class PlayerDataPatches
{
	public static class UnequipFromAllPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PlayerData), "UnequipFromAll", new Type[1] { typeof(UpgradeInstance) }, (Type[])null);
		}

		public static bool Prefix(UpgradeInstance upgrade)
		{
			try
			{
				if (upgrade != null && !upgrade.RemoveAfterMission)
				{
					PerformanceEnhancedMenuPlugin.ClearAllCaches();
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in UnequipFromAllPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class CollectInstancePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PlayerData), "CollectInstance", new Type[2]
			{
				typeof(UpgradeInstance),
				typeof(UnlockFlags)
			}, (Type[])null);
		}

		public static bool Prefix(UpgradeInstance instance, UnlockFlags flags = 0)
		{
			try
			{
				if (instance == null || (Object)(object)instance.Upgrade == (Object)null || instance.Favorite)
				{
					return true;
				}
				IUpgradable gear = instance.Gear;
				if (gear == null)
				{
					return true;
				}
				bool skins = instance.Upgrade.IsSkin();
				if (GetTotalCount(gear, skins) >= 256)
				{
					PlayerData.Instance.rentedUpgrades.Add(instance);
					if ((Object)(object)PlayerLook.Instance != (Object)null)
					{
						PlayerLook.Instance.AddTextChatMessage("Upgrade limit reached, stored in lost loot.", (Player)null);
					}
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in CollectInstancePatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class OnAwakePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(PlayerData), "OnAwake", (Type[])null, (Type[])null);
		}

		public static void Postfix()
		{
			try
			{
				EnforceUpgradeLimit();
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in OnAwakePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	private const int UPGRADE_LIMIT = 256;

	private static void EnforceUpgradeLimit()
	{
		try
		{
			foreach (KeyValuePair<int, GearData> item in PlayerData.Instance.collectedGear)
			{
				IUpgradable gear = item.Value.Gear;
				if (gear != null)
				{
					EnforceLimitForGear(gear, skins: false);
					EnforceLimitForGear(gear, skins: true);
				}
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogError((object)("Error in EnforceUpgradeLimit: " + ex.Message + "\n" + ex.StackTrace));
		}
	}

	private static void EnforceLimitForGear(IUpgradable gear, bool skins)
	{
		try
		{
			List<UpgradeInfo> obj = (skins ? PlayerData.GetAllSkins(gear, true) : PlayerData.GetAllUpgrades(gear, true));
			List<UpgradeInstance> list = new List<UpgradeInstance>();
			foreach (UpgradeInfo item in obj)
			{
				if (item.Instances != null)
				{
					list.AddRange(item.Instances.Where((UpgradeInstance inst) => !inst.Favorite && !inst.RemoveAfterMission));
				}
			}
			if (list.Count <= 256)
			{
				return;
			}
			list.Sort((UpgradeInstance a, UpgradeInstance b) => b.InstanceID.CompareTo(a.InstanceID));
			int num = list.Count - 256;
			for (int i = 0; i < num; i++)
			{
				UpgradeInstance val = list[i];
				UpgradeInfo upgradeInfo = PlayerData.GetUpgradeInfo(gear, val.Upgrade);
				if (upgradeInfo.Instances != null)
				{
					upgradeInfo.Instances.Remove(val);
				}
				PlayerData.Instance.rentedUpgrades.Add(val);
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogError((object)("Error in EnforceLimitForGear: " + ex.Message + "\n" + ex.StackTrace));
		}
	}

	private static int GetTotalCount(IUpgradable gear, bool skins)
	{
		List<UpgradeInfo> obj = (skins ? PlayerData.GetAllSkins(gear, true) : PlayerData.GetAllUpgrades(gear, true));
		int num = 0;
		foreach (UpgradeInfo item in obj)
		{
			if (item.Instances != null)
			{
				num += item.Instances.Count((UpgradeInstance inst) => !inst.RemoveAfterMission);
			}
		}
		return num;
	}
}
[BepInPlugin("sparroh.enhancedmenuperformance", "EnhancedMenuPerformance", "2.2.0")]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class SparrohPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.enhancedmenuperformance";

	public const string PluginName = "EnhancedMenuPerformance";

	public const string PluginVersion = "2.2.0";

	internal static ManualLogSource Logger;

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Expected O, but got Unknown
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Expected O, but got Unknown
		//IL_00e9: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Expected O, but got Unknown
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Expected O, but got Unknown
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Expected O, but got Unknown
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Expected O, but got Unknown
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Expected O, but got Unknown
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Expected O, but got Unknown
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		Harmony val = new Harmony("sparroh.enhancedmenuperformance");
		MethodBase methodBase = GeneralPatches.EquipUpgradePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(GeneralPatches.EquipUpgradePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = GeneralPatches.UnequipUpgradePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(GeneralPatches.UnequipUpgradePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = GeneralPatches.GetEquippedUpgradePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, new HarmonyMethod(typeof(GeneralPatches.GetEquippedUpgradePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = TransitionOptimizationPatches.GearDetailsWindowSetupPatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, new HarmonyMethod(typeof(TransitionOptimizationPatches.GearDetailsWindowSetupPatch), "Prefix", (Type[])null), new HarmonyMethod(typeof(TransitionOptimizationPatches.GearDetailsWindowSetupPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = UIOptimizationPatches.GearUpgradeUISetUpgradePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(UIOptimizationPatches.GearUpgradeUISetUpgradePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = UIOptimizationPatches.GearDetailsWindowOnUpgradeCollectedOrDestroyedPatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, new HarmonyMethod(typeof(UIOptimizationPatches.GearDetailsWindowOnUpgradeCollectedOrDestroyedPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = UIOptimizationPatches.OuroGearWindowOnUpgradeCollectedOrDestroyedPatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, new HarmonyMethod(typeof(UIOptimizationPatches.OuroGearWindowOnUpgradeCollectedOrDestroyedPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = DebouncePatches.GearDataEquipUpgradePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(DebouncePatches.GearDataEquipUpgradePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = DebouncePatches.GearDataUnequipUpgradePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(DebouncePatches.GearDataUnequipUpgradePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = PlayerDataPatches.UnequipFromAllPatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, new HarmonyMethod(typeof(PlayerDataPatches.UnequipFromAllPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = PlayerDataPatches.CollectInstancePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, new HarmonyMethod(typeof(PlayerDataPatches.CollectInstancePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		methodBase = PlayerDataPatches.OnAwakePatch.TargetMethod();
		if (methodBase != null)
		{
			val.Patch(methodBase, (HarmonyMethod)null, new HarmonyMethod(typeof(PlayerDataPatches.OnAwakePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		Logger.LogInfo((object)"EnhancedMenuPerformance loaded");
	}
}
public static class SkinOptimizationPatches
{
	public static class GearDetailsWindowSetupUpgradesSkinModePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearDetailsWindow), "SetupUpgrades", new Type[3]
			{
				typeof(IUpgradable),
				typeof(bool),
				typeof(bool)
			}, (Type[])null);
		}

		public static bool Prefix(GearDetailsWindow __instance, IUpgradable upgradable, bool skins, bool resetScroll, ref bool __state)
		{
			try
			{
				if (!skins)
				{
					return true;
				}
				currentWindow = __instance;
				skinsDeferredLoaded = false;
				if (PlayerData.GetGearData(upgradable) != null)
				{
					upgradable.Info.SkinCount();
					__state = true;
					StartDeferredSkinLoading(__instance, upgradable, resetScroll);
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDetailsWindowSetupUpgradesSkinModePatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}

		public static void Postfix(GearDetailsWindow __instance, IUpgradable upgradable, bool skins, bool resetScroll, bool __state)
		{
			try
			{
				if (__state && skins)
				{
					SetupMinimalSkinUI(__instance, upgradable);
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDetailsWindowSetupUpgradesSkinModePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	public static class GearDetailsWindowOnSkinAreaInteractionPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearDetailsWindow), "Update", (Type[])null, (Type[])null);
		}

		public static void Postfix(GearDetailsWindow __instance)
		{
			try
			{
				if (!((Object)(object)currentWindow == (Object)(object)__instance) || skinsDeferredLoaded)
				{
					return;
				}
				object? value = AccessTools.Field(typeof(GearDetailsWindow), "upgradeListScrollbar").GetValue(__instance);
				ScrollBar val = (ScrollBar)((value is ScrollBar) ? value : null);
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf && (bool)AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").GetValue(__instance) && !skinsDeferredLoaded)
				{
					IUpgradable upgradablePrefab = __instance.UpgradablePrefab;
					if (upgradablePrefab != null)
					{
						LoadSkinsDeferred(__instance, upgradablePrefab, resetScroll: true);
						skinsDeferredLoaded = true;
						HideSkinLoadingIndicator(__instance);
					}
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDetailsWindowOnSkinAreaInteractionPatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	[CompilerGenerated]
	private sealed class <DeferredSkinLoadingCoroutine>d__4 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public GearDetailsWindow window;

		public IUpgradable upgradable;

		public bool resetScroll;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DeferredSkinLoadingCoroutine>d__4(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				ShowSkinLoadingIndicator(window);
				<>2__current = null;
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				LoadSkinsDeferred(window, upgradable, resetScroll);
				skinsDeferredLoaded = true;
				HideSkinLoadingIndicator(window);
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static bool skinsDeferredLoaded;

	private static GearDetailsWindow currentWindow;

	private static void StartDeferredSkinLoading(GearDetailsWindow window, IUpgradable upgradable, bool resetScroll)
	{
		if ((Object)(object)Menu.Instance != (Object)null)
		{
			((MonoBehaviour)Menu.Instance).StartCoroutine(DeferredSkinLoadingCoroutine(window, upgradable, resetScroll));
		}
	}

	[IteratorStateMachine(typeof(<DeferredSkinLoadingCoroutine>d__4))]
	private static IEnumerator DeferredSkinLoadingCoroutine(GearDetailsWindow window, IUpgradable upgradable, bool resetScroll)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DeferredSkinLoadingCoroutine>d__4(0)
		{
			window = window,
			upgradable = upgradable,
			resetScroll = resetScroll
		};
	}

	private static void ShowSkinLoadingIndicator(GearDetailsWindow window)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		object? value = AccessTools.Field(typeof(GearDetailsWindow), "upgradeListParent").GetValue(window);
		RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
		if ((Object)(object)val != (Object)null)
		{
			TextMeshProUGUI obj = new GameObject("Skin Loading Indicator").AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).transform.SetParent((Transform)(object)val, false);
			((TMP_Text)obj).transform.localPosition = Vector3.zero;
			((TMP_Text)obj).text = "Loading skins...";
			((TMP_Text)obj).fontSize = 24f;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((Graphic)obj).color = Color.white;
			((Component)obj).gameObject.SetActive(true);
		}
	}

	private static void HideSkinLoadingIndicator(GearDetailsWindow window)
	{
		object? value = AccessTools.Field(typeof(GearDetailsWindow), "upgradeListParent").GetValue(window);
		RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
		if (!((Object)(object)val != (Object)null))
		{
			return;
		}
		for (int num = ((Transform)val).childCount - 1; num >= 0; num--)
		{
			Transform child = ((Transform)val).GetChild(num);
			if (((Object)child).name == "Skin Loading Indicator")
			{
				Object.Destroy((Object)(object)((Component)child).gameObject);
			}
		}
	}

	private static void SetupMinimalSkinUI(GearDetailsWindow window, IUpgradable upgradable)
	{
		PlayerData.GetGearData(upgradable);
		AccessTools.Field(typeof(GearDetailsWindow), "inSkinMode").SetValue(window, true);
		object? value = AccessTools.Field(typeof(GearDetailsWindow), "skinsButton").GetValue(window);
		Button val = (Button)((value is Button) ? value : null);
		if ((Object)(object)val != (Object)null)
		{
			TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = "upgrades";
			}
			Triangle componentInChildren2 = ((Component)val).GetComponentInChildren<Triangle>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.SetFlip(true);
			}
		}
		AccessTools.Method(typeof(GearDetailsWindow), "EnableGridLock", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null)?.Invoke(window, new object[2] { false, false });
		UpdateSkinsExclamation(window, upgradable);
	}

	private static void LoadSkinsDeferred(GearDetailsWindow window, IUpgradable upgradable, bool resetScroll)
	{
		AccessTools.Method(typeof(GearDetailsWindow), "SetupUpgrades", new Type[3]
		{
			typeof(IUpgradable),
			typeof(bool),
			typeof(bool)
		}, (Type[])null)?.Invoke(window, new object[3] { upgradable, true, resetScroll });
	}

	private static void UpdateSkinsExclamation(GearDetailsWindow window, IUpgradable upgradable)
	{
		object? value = AccessTools.Field(typeof(GearDetailsWindow), "skinsExclamation").GetValue(window);
		Graphic val = (Graphic)((value is Graphic) ? value : null);
		if ((Object)(object)val != (Object)null)
		{
			bool active = PlayerData.HasAnyUnseenSkins(upgradable);
			((Component)val).gameObject.SetActive(active);
		}
	}
}
public static class StatCalcPatches
{
	internal static Dictionary<long, string> statListCache;

	internal static Dictionary<long, string> displayPropertiesCache;

	internal static string tempOldProperties;

	internal static Dictionary<int, int> prismConnectedCounts;

	internal static Dictionary<int, (int std, int rare, int epic, int exo)> rarityTouchingCounts;

	internal static Dictionary<int, UpgradeInstance[,]> upgradeGridCache;

	internal static Type rarityFlagsType;

	internal static object rarityFlagsStandard;

	internal static object rarityFlagsRare;

	internal static object rarityFlagsEpic;

	internal static object rarityFlagsExotic;

	internal static MethodInfo getNumTouchingMethod;

	internal static Type iGlobblometerPropertyType;

	internal static MethodInfo modifyGlobblometerMethod;

	internal static Type upgradeEquipDataType;

	internal static MethodInfo getUpgradeMethod;

	internal static FieldInfo equippedUpgradesField;

	internal static bool skipRecompute;

	static StatCalcPatches()
	{
		statListCache = new Dictionary<long, string>();
		displayPropertiesCache = new Dictionary<long, string>();
		prismConnectedCounts = new Dictionary<int, int>();
		rarityTouchingCounts = new Dictionary<int, (int, int, int, int)>();
		upgradeGridCache = new Dictionary<int, UpgradeInstance[,]>();
		equippedUpgradesField = null;
		skipRecompute = false;
		try
		{
			rarityFlagsType = AccessTools.TypeByName("RarityFlags");
			rarityFlagsStandard = Enum.Parse(rarityFlagsType, "Standard");
			rarityFlagsRare = Enum.Parse(rarityFlagsType, "Rare");
			rarityFlagsEpic = Enum.Parse(rarityFlagsType, "Epic");
			rarityFlagsExotic = Enum.Parse(rarityFlagsType, "Exotic");
			getNumTouchingMethod = AccessTools.Method(typeof(UpgradeProperty), "GetNumCellsTouchingThis", new Type[3]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance),
				rarityFlagsType
			}, (Type[])null);
			iGlobblometerPropertyType = AccessTools.TypeByName("IGlobblometerProperty");
			modifyGlobblometerMethod = AccessTools.Method(iGlobblometerPropertyType, "ModifyGlobblometer", new Type[4]
			{
				typeof(int).MakeByRefType(),
				typeof(Random),
				typeof(IUpgradable),
				typeof(UpgradeInstance)
			}, (Type[])null);
			upgradeEquipDataType = AccessTools.Inner(typeof(PlayerData), "UpgradeEquipData");
			getUpgradeMethod = AccessTools.Method(upgradeEquipDataType, "GetUpgrade", (Type[])null, (Type[])null);
			equippedUpgradesField = AccessTools.Field(typeof(GearData), "equippedUpgrades");
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogError((object)("Error initializing StatCalcPatches: " + ex.Message + "\n" + ex.StackTrace));
		}
	}

	internal static void RecomputeTotals(GearData gearData)
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Expected O, but got Unknown
		//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Expected O, but got Unknown
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d8: Expected O, but got Unknown
		try
		{
			if (PerformanceEnhancedMenuPlugin.deferExpensiveCalculations)
			{
				return;
			}
			rarityTouchingCounts.Clear();
			UpgradePropertyList properties;
			if (gearData.Gear is Globbler)
			{
				int num = 0;
				List<UpgradeInstance> list = new List<UpgradeInstance>();
				IList obj = (IList)equippedUpgradesField.GetValue(gearData);
				List<object> list2 = new List<object>();
				foreach (object item5 in obj)
				{
					list2.Add(item5);
				}
				Random val2 = default(Random);
				foreach (object item6 in list2)
				{
					UpgradeInstance val = (UpgradeInstance)getUpgradeMethod.Invoke(item6, null);
					((Random)(ref val2))..ctor(val.Seed);
					bool flag = false;
					Upgrade upgrade = val.Upgrade;
					GenericGunUpgrade val3 = (GenericGunUpgrade)(object)((upgrade is GenericGunUpgrade) ? upgrade : null);
					if (val3 != null)
					{
						properties = ((Upgrade)val3).Properties;
						if (((UpgradePropertyList)(ref properties)).HasProperties)
						{
							UpgradePropertyList properties2 = ((Upgrade)val3).Properties;
							for (int i = 0; i < ((UpgradePropertyList)(ref properties2)).Count; i++)
							{
								UpgradeProperty val4 = ((UpgradePropertyList)(ref properties2))[i];
								if (((object)val4).GetType().FullName == "UpgradeProperty_Globbler_RarityStats")
								{
									flag = true;
								}
								if (iGlobblometerPropertyType.IsAssignableFrom(((object)val4).GetType()))
								{
									object[] array = new object[4] { num, val2, gearData.Gear, val };
									modifyGlobblometerMethod.Invoke(val4, array);
									num = (int)array[0];
								}
							}
						}
					}
					if (flag)
					{
						list.Add(val);
					}
					if (iGlobblometerPropertyType.IsAssignableFrom(((object)val.Upgrade).GetType()))
					{
						object[] array2 = new object[4] { num, val2, gearData.Gear, val };
						modifyGlobblometerMethod.Invoke(val.Upgrade, array2);
						num = (int)array2[0];
					}
				}
				if (list.Count > 0)
				{
					foreach (UpgradeInstance item7 in list)
					{
						int item = (int)getNumTouchingMethod.Invoke(null, new object[3] { gearData.Gear, item7, rarityFlagsStandard });
						int item2 = (int)getNumTouchingMethod.Invoke(null, new object[3] { gearData.Gear, item7, rarityFlagsRare });
						int item3 = (int)getNumTouchingMethod.Invoke(null, new object[3] { gearData.Gear, item7, rarityFlagsEpic });
						int item4 = (int)getNumTouchingMethod.Invoke(null, new object[3] { gearData.Gear, item7, rarityFlagsExotic });
						rarityTouchingCounts[item7.InstanceID] = (item, item2, item3, item4);
					}
				}
			}
			if (!(gearData.Gear is MiniCannon))
			{
				return;
			}
			prismConnectedCounts.Clear();
			Dictionary<UpgradeInstance, List<UpgradeInstance>> dictionary = new Dictionary<UpgradeInstance, List<UpgradeInstance>>();
			List<UpgradeInstance> list3 = new List<UpgradeInstance>();
			Dictionary<int, HashSet<(int, int)>> dictionary2 = new Dictionary<int, HashSet<(int, int)>>();
			IList obj2 = (IList)equippedUpgradesField.GetValue(gearData);
			List<object> list4 = new List<object>();
			foreach (object item8 in obj2)
			{
				list4.Add(item8);
			}
			foreach (object item9 in list4)
			{
				UpgradeInstance val5 = (UpgradeInstance)getUpgradeMethod.Invoke(item9, null);
				bool flag2 = false;
				Upgrade upgrade2 = val5.Upgrade;
				GenericGunUpgrade val6 = (GenericGunUpgrade)(object)((upgrade2 is GenericGunUpgrade) ? upgrade2 : null);
				if (val6 != null)
				{
					properties = ((Upgrade)val6).Properties;
					if (((UpgradePropertyList)(ref properties)).HasProperties)
					{
						UpgradePropertyList properties3 = ((Upgrade)val6).Properties;
						for (int j = 0; j < ((UpgradePropertyList)(ref properties3)).Count; j++)
						{
							if (((object)((UpgradePropertyList)(ref properties3))[j]).GetType().FullName == "UpgradeProperty_MiniCannon_Prism")
							{
								flag2 = true;
								break;
							}
						}
					}
				}
				if (flag2)
				{
					list3.Add(val5);
					dictionary[val5] = new List<UpgradeInstance>();
				}
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerData), "GetSurroundingCells", new Type[3]
			{
				typeof(IUpgradable),
				typeof(UpgradeInstance),
				typeof(HashSet<(int, int)>).MakeByRefType()
			}, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerData), "GetEquippedUpgrade", new Type[3]
			{
				typeof(IUpgradable),
				typeof(int),
				typeof(int)
			}, (Type[])null);
			foreach (UpgradeInstance item10 in list3)
			{
				HashSet<(int, int)> hashSet = new HashSet<(int, int)>();
				object[] array3 = new object[3] { gearData.Gear, item10, hashSet };
				methodInfo.Invoke(null, array3);
				hashSet = (HashSet<(int, int)>)array3[2];
				dictionary2[item10.InstanceID] = hashSet;
			}
			foreach (UpgradeInstance item11 in list3)
			{
				foreach (var item12 in dictionary2[item11.InstanceID])
				{
					UpgradeInstance val7 = (UpgradeInstance)methodInfo2.Invoke(null, new object[3] { gearData.Gear, item12.Item1, item12.Item2 });
					if (val7 != null && dictionary.ContainsKey(val7))
					{
						dictionary[item11].Add(val7);
					}
				}
			}
			HashSet<UpgradeInstance> hashSet2 = new HashSet<UpgradeInstance>();
			foreach (UpgradeInstance item13 in list3)
			{
				if (hashSet2.Contains(item13))
				{
					continue;
				}
				List<UpgradeInstance> list5 = DFS(dictionary, item13, hashSet2);
				int count = list5.Count;
				foreach (UpgradeInstance item14 in list5)
				{
					prismConnectedCounts[item14.InstanceID] = count;
				}
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogError((object)("Error in RecomputeTotals: " + ex.Message + "\n" + ex.StackTrace));
		}
	}

	internal static List<UpgradeInstance> DFS(Dictionary<UpgradeInstance, List<UpgradeInstance>> graph, UpgradeInstance node, HashSet<UpgradeInstance> visited)
	{
		List<UpgradeInstance> list = new List<UpgradeInstance>();
		Stack<UpgradeInstance> stack = new Stack<UpgradeInstance>();
		stack.Push(node);
		while (stack.Count > 0)
		{
			UpgradeInstance val = stack.Pop();
			if (!visited.Add(val))
			{
				continue;
			}
			list.Add(val);
			foreach (UpgradeInstance item in graph[val])
			{
				if (!visited.Contains(item))
				{
					stack.Push(item);
				}
			}
		}
		return list;
	}

	internal static void ClearCaches()
	{
		statListCache.Clear();
		displayPropertiesCache.Clear();
		upgradeGridCache.Clear();
	}
}
public static class TransitionOptimizationPatches
{
	public static class GearDetailsWindowSetupPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearDetailsWindow), "Setup", new Type[1] { typeof(IUpgradable) }, (Type[])null);
		}

		public static bool Prefix(GearDetailsWindow __instance, IUpgradable upgradable)
		{
			try
			{
				PerformanceEnhancedMenuPlugin.deferExpensiveCalculations = true;
				OptimizeGearPreviewSetup(__instance, upgradable);
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDetailsWindowSetupPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}

		public static void Postfix(GearDetailsWindow __instance, IUpgradable upgradable)
		{
			try
			{
				PerformanceEnhancedMenuPlugin.deferExpensiveCalculations = false;
				PostSetupOptimizations(__instance, upgradable);
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDetailsWindowSetupPatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	[CompilerGenerated]
	private sealed class <DelayedSetupOperations>d__5 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public GearDetailsWindow instance;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DelayedSetupOperations>d__5(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				AccessTools.Method(typeof(GearDetailsWindow), "SetupSkinMaterials", (Type[])null, (Type[])null)?.Invoke(instance, null);
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static Dictionary<IUpgradable, GameObject> gearPreviewCache = new Dictionary<IUpgradable, GameObject>();

	private static Dictionary<Character, GameObject> characterPreviewCache = new Dictionary<Character, GameObject>();

	private static void OptimizeGearPreviewSetup(GearDetailsWindow instance, IUpgradable upgradable)
	{
		object? value = AccessTools.Field(typeof(GearDetailsWindow), "characterPreview").GetValue(instance);
		Transform val = (Transform)((value is Transform) ? value : null);
		if (!((Object)(object)val != (Object)null))
		{
			return;
		}
		if (val.childCount > 0)
		{
			for (int num = val.childCount - 1; num >= 0; num--)
			{
				Transform child = val.GetChild(num);
				if (!(upgradable is Character) || Global.Instance.Characters[num] != upgradable)
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
		}
		Character val2 = (Character)(object)((upgradable is Character) ? upgradable : null);
		if (val2 == null)
		{
			return;
		}
		bool flag = false;
		for (int i = 0; i < val.childCount; i++)
		{
			if (((Component)val.GetChild(i)).gameObject.activeSelf && Global.Instance.Characters[i] == upgradable)
			{
				flag = true;
				break;
			}
		}
		if (!flag && val2.Index < val.childCount)
		{
			((Component)val.GetChild(val2.Index)).gameObject.SetActive(true);
		}
	}

	private static void PostSetupOptimizations(GearDetailsWindow instance, IUpgradable upgradable)
	{
		((MonoBehaviour)instance).StartCoroutine(DelayedSetupOperations(instance, upgradable));
	}

	[IteratorStateMachine(typeof(<DelayedSetupOperations>d__5))]
	private static IEnumerator DelayedSetupOperations(GearDetailsWindow instance, IUpgradable upgradable)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DelayedSetupOperations>d__5(0)
		{
			instance = instance
		};
	}
}
public static class UIOptimizationPatches
{
	public static class GearUpgradeUISetUpgradePatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearUpgradeUI), "SetUpgrade", new Type[2]
			{
				typeof(UpgradeInstance),
				typeof(bool)
			}, (Type[])null);
		}

		public static void Postfix(GearUpgradeUI __instance, UpgradeInstance upgrade, bool isPreview)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!(upgrade == null || isPreview))
				{
					RarityData rarity = Global.GetRarity(upgrade.Upgrade.Rarity);
					object? value = AccessTools.Field(typeof(GearUpgradeUI), "button").GetValue(__instance);
					DefaultButton val = (DefaultButton)((value is DefaultButton) ? value : null);
					if ((Object)(object)val != (Object)null && (Object)(object)val.MainGraphic != (Object)null)
					{
						val.MainGraphic.material = rarity.uiMat;
					}
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearUpgradeUISetUpgradePatch.Postfix: " + ex.Message + "\n" + ex.StackTrace));
			}
		}
	}

	public static class GearDetailsWindowOnUpgradeCollectedOrDestroyedPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(GearDetailsWindow), "OnUpgradeCollectedOrDestroyed", new Type[2]
			{
				typeof(UpgradeInstance),
				typeof(bool)
			}, (Type[])null);
		}

		public static bool Prefix(GearDetailsWindow __instance, UpgradeInstance upgrade, bool collected)
		{
			try
			{
				if (!collected)
				{
					currentlyScrappingUpgrade = upgrade;
					if (AccessTools.Field(typeof(GearDetailsWindow), "upgradeUIs").GetValue(null) is List<GearUpgradeUI> list)
					{
						for (int i = 0; i < list.Count; i++)
						{
							GearUpgradeUI val = list[i];
							if ((Object)(object)val != (Object)null && ((HoverInfoUpgrade)val).Upgrade == upgrade && ((Component)val).gameObject.activeSelf)
							{
								((Component)val).gameObject.SetActive(false);
								break;
							}
						}
					}
					PerformanceEnhancedMenuPlugin.ClearAllCaches();
					return false;
				}
				currentlyScrappingUpgrade = null;
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in GearDetailsWindowOnUpgradeCollectedOrDestroyedPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	public static class OuroGearWindowOnUpgradeCollectedOrDestroyedPatch
	{
		public static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(OuroGearWindow), "OnUpgradeCollectedOrDestroyed", new Type[2]
			{
				typeof(UpgradeInstance),
				typeof(bool)
			}, (Type[])null);
		}

		public static bool Prefix(OuroGearWindow __instance, UpgradeInstance upgrade, bool collected)
		{
			try
			{
				if (!collected)
				{
					currentlyScrappingUpgrade = upgrade;
					if (AccessTools.Field(typeof(OuroGearWindow), "upgradeUIs").GetValue(null) is List<GearUpgradeUI> list)
					{
						for (int i = 0; i < list.Count; i++)
						{
							GearUpgradeUI val = list[i];
							if ((Object)(object)val != (Object)null && ((HoverInfoUpgrade)val).Upgrade == upgrade && ((Component)val).gameObject.activeSelf)
							{
								((Component)val).gameObject.SetActive(false);
								break;
							}
						}
					}
					PerformanceEnhancedMenuPlugin.ClearAllCaches();
					return false;
				}
				currentlyScrappingUpgrade = null;
				return true;
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogError((object)("Error in OuroGearWindowOnUpgradeCollectedOrDestroyedPatch.Prefix: " + ex.Message + "\n" + ex.StackTrace));
				return true;
			}
		}
	}

	private static Dictionary<string, (UpgradeEquipCell cell, float lastUpdate)> raycastCache = new Dictionary<string, (UpgradeEquipCell, float)>();

	private static Dictionary<string, (GearUpgradeUI ui, float lastUpdate)> uiRaycastCache = new Dictionary<string, (GearUpgradeUI, float)>();

	private static readonly float RAYCAST_CACHE_TIME = 0.05f;

	private static float lastExpensiveUpdate = 0f;

	private static readonly float EXPENSIVE_UPDATE_THROTTLE = 0.1f;

	private static UpgradeInstance currentlyScrappingUpgrade = null;
}
public static class VirtualizedUpgradeList
{
	private const int VISIBLE_BUFFER = 10;

	private const float ITEM_HEIGHT = 60f;

	private static List<UpgradeInstance> allUpgrades = new List<UpgradeInstance>();

	private static Dictionary<int, GearUpgradeUI> activeUIElements = new Dictionary<int, GearUpgradeUI>();

	private static List<GearUpgradeUI> uiPool = new List<GearUpgradeUI>();

	private static RectTransform upgradeListParent;

	private static ScrollRect scrollRect;

	private static GearDetailsWindow currentWindow;

	private static bool isVirtualized = false;

	private static GearUpgradeUI uiPrefab;

	private static float viewportHeight = 0f;

	private static float currentScrollPosition = 0f;

	public static bool IsVirtualized => isVirtualized;

	public static void Initialize(GearDetailsWindow window, RectTransform parent, ScrollRect scroll)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		currentWindow = window;
		upgradeListParent = parent;
		scrollRect = scroll;
		Rect rect = parent.rect;
		viewportHeight = ((Rect)(ref rect)).height;
		((UnityEvent<Vector2>)(object)scrollRect.onValueChanged).AddListener((UnityAction<Vector2>)OnScrollChanged);
		isVirtualized = true;
	}

	public static void SetUpgradeData(List<UpgradeInstance> upgrades, GearUpgradeUI prefab)
	{
		if (isVirtualized)
		{
			allUpgrades = new List<UpgradeInstance>(upgrades);
			uiPrefab = prefab;
			ClearActiveUI();
			UpdateVisibleItems();
		}
	}

	private static GearUpgradeUI GetPooledUI()
	{
		GearUpgradeUI val;
		if (uiPool.Count > 0)
		{
			val = uiPool[uiPool.Count - 1];
			uiPool.RemoveAt(uiPool.Count - 1);
			((Component)val).gameObject.SetActive(true);
		}
		else
		{
			val = Object.Instantiate<GearUpgradeUI>(uiPrefab, (Transform)(object)upgradeListParent);
		}
		return val;
	}

	private static void ReturnToPool(GearUpgradeUI ui)
	{
		((Component)ui).gameObject.SetActive(false);
		uiPool.Add(ui);
	}

	public static void UpdateVisibleItems()
	{
		if (!isVirtualized || allUpgrades.Count == 0)
		{
			return;
		}
		int num = CalculateVisibleStartIndex();
		int num2 = CalculateVisibleEndIndex();
		num = Math.Max(0, num - 10);
		num2 = Math.Min(allUpgrades.Count - 1, num2 + 10);
		List<int> list = new List<int>();
		foreach (KeyValuePair<int, GearUpgradeUI> activeUIElement in activeUIElements)
		{
			if (activeUIElement.Key < num || activeUIElement.Key > num2)
			{
				ReturnToPool(activeUIElement.Value);
				list.Add(activeUIElement.Key);
			}
		}
		foreach (int item in list)
		{
			activeUIElements.Remove(item);
		}
		for (int i = num; i <= num2; i++)
		{
			if (!activeUIElements.ContainsKey(i))
			{
				GearUpgradeUI pooledUI = GetPooledUI();
				pooledUI.SetUpgrade(allUpgrades[i], false);
				bool flag = (bool)AccessTools.Field(typeof(GearDetailsWindow), "isGridView").GetValue(null);
				pooledUI.EnableGridView(flag);
				SetUpgradePosition(pooledUI, i);
				activeUIElements[i] = pooledUI;
			}
		}
	}

	private static void SetUpgradePosition(GearUpgradeUI ui, int index)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = (RectTransform)((Component)ui).transform;
		Rect rect;
		if ((bool)AccessTools.Field(typeof(GearDetailsWindow), "isGridView").GetValue(null))
		{
			rect = upgradeListParent.rect;
			double num = (double)((Rect)(ref rect)).width - 6.0;
			Rect rect2 = val.rect;
			double num2 = (double)((Rect)(ref rect2)).width + 10.0;
			int num3 = Mathf.Max(Mathf.FloorToInt((float)(num / num2)), 1);
			double num4 = index % num3;
			rect2 = val.rect;
			double num5 = (double)((Rect)(ref rect2)).width + 10.0;
			float num6 = (float)(3.0 + num4 * num5);
			double num7 = index / num3;
			rect2 = val.rect;
			double num8 = (double)((Rect)(ref rect2)).height + 10.0;
			float num9 = (float)(-3.0 - num7 * num8);
			val.anchoredPosition = new Vector2(num6, num9);
		}
		else
		{
			val.offsetMin = new Vector2(0f, val.offsetMin.y);
			val.offsetMax = new Vector2(0f, val.offsetMax.y);
			rect = val.rect;
			val.anchoredPosition = new Vector2(0f, (float)(-3.0 - ((double)((Rect)(ref rect)).height + 4.0) * (double)index));
		}
	}

	private static int CalculateVisibleStartIndex()
	{
		if ((bool)AccessTools.Field(typeof(GearDetailsWindow), "isGridView").GetValue(null))
		{
			return 0;
		}
		float num = 1f - currentScrollPosition;
		float num2 = (float)allUpgrades.Count * 64f;
		float num3 = num * (num2 - viewportHeight);
		return Math.Max(0, (int)(num3 / 64f));
	}

	private static int CalculateVisibleEndIndex()
	{
		if ((bool)AccessTools.Field(typeof(GearDetailsWindow), "isGridView").GetValue(null))
		{
			return Math.Min(allUpgrades.Count - 1, CalculateVisibleStartIndex() + 50);
		}
		int num = CalculateVisibleStartIndex();
		int num2 = (int)(viewportHeight / 64f) + 1;
		return Math.Min(allUpgrades.Count - 1, num + num2);
	}

	private static void OnScrollChanged(Vector2 scrollPos)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		currentScrollPosition = scrollPos.y;
		UpdateVisibleItems();
	}

	public static void ClearActiveUI()
	{
		foreach (GearUpgradeUI value in activeUIElements.Values)
		{
			ReturnToPool(value);
		}
		activeUIElements.Clear();
	}

	public static void Shutdown()
	{
		if ((Object)(object)scrollRect != (Object)null)
		{
			((UnityEvent<Vector2>)(object)scrollRect.onValueChanged).RemoveListener((UnityAction<Vector2>)OnScrollChanged);
		}
		ClearActiveUI();
		allUpgrades.Clear();
		isVirtualized = false;
		currentWindow = null;
	}

	public static GearUpgradeUI GetUIForUpgrade(UpgradeInstance upgrade)
	{
		foreach (KeyValuePair<int, GearUpgradeUI> activeUIElement in activeUIElements)
		{
			if (((HoverInfoUpgrade)activeUIElement.Value).Upgrade == upgrade)
			{
				return activeUIElement.Value;
			}
		}
		return null;
	}
}
[CompilerGenerated]
[ExcludeFromCodeCoverage]
internal static class GitVersionInformation
{
	public const string AssemblySemFileVer = "0.0.1.0";

	public const string AssemblySemVer = "0.0.1.0";

	public const string BranchName = "master";

	public const string BuildMetaData = "";

	public const string CommitDate = "2025-12-26";

	public const string CommitsSinceVersionSource = "6";

	public const string EscapedBranchName = "master";

	public const string FullBuildMetaData = "Branch.master.Sha.d6f427ecb324fcdcc95d444b8f51f209de322a5d";

	public const string FullSemVer = "0.0.1-6";

	public const string InformationalVersion = "0.0.1-6+Branch.master.Sha.d6f427ecb324fcdcc95d444b8f51f209de322a5d";

	public const string Major = "0";

	public const string MajorMinorPatch = "0.0.1";

	public const string Minor = "0";

	public const string Patch = "1";

	public const string PreReleaseLabel = "";

	public const string PreReleaseLabelWithDash = "";

	public const string PreReleaseNumber = "6";

	public const string PreReleaseTag = "6";

	public const string PreReleaseTagWithDash = "-6";

	public const string SemVer = "0.0.1-6";

	public const string Sha = "d6f427ecb324fcdcc95d444b8f51f209de322a5d";

	public const string ShortSha = "d6f427e";

	public const string UncommittedChanges = "13";

	public const string VersionSourceSha = "";

	public const string WeightedPreReleaseNumber = "55006";
}
namespace PerformanceEnhancedMenu
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "PerformanceEnhancedMenu";

		public const string PLUGIN_NAME = "PerformanceEnhancedMenu";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}