Decompiled source of ROR O v1.0.4

plugins/ror-o/ROR-O.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates.Assassin.Weapon;
using EntityStates.BeetleQueenMonster;
using EntityStates.Chef;
using EntityStates.ClaymanMonster;
using EntityStates.Drone.DroneWeapon;
using EntityStates.FalseSon;
using EntityStates.FalseSonBoss;
using EntityStates.FriendUnit;
using EntityStates.GolemMonster;
using EntityStates.GrandParentBoss;
using EntityStates.Huntress;
using EntityStates.LemurianBruiserMonster;
using EntityStates.Loader;
using EntityStates.LunarWisp;
using EntityStates.Mage.Weapon;
using EntityStates.Merc;
using EntityStates.NewtMonster;
using EntityStates.Paladin;
using EntityStates.Seeker;
using EntityStates.SolusAmalgamator;
using EntityStates.SolusWing;
using EntityStates.Tanker;
using EntityStates.Toolbot;
using EntityStates.VagrantMonster.Weapon;
using HarmonyLib;
using KinematicCharacterController;
using LookingGlass.ItemStatsNameSpace;
using Microsoft.CodeAnalysis;
using ROR_O.Utilities;
using RoR2;
using RoR2.PostProcessing;
using RoR2.Projectile;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("LookingGlass")]
[assembly: IgnoresAccessChecksTo("RoR2")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ROR-O")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c61dbc246dd63e9ec06aadddf51acfd32e966ec8")]
[assembly: AssemblyProduct("ROR-O")]
[assembly: AssemblyTitle("ROR-O")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
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 ROR_O
{
	internal static class ROROConfig
	{
		private static ConfigEntry<bool>? enableDamageNumberLoadShedding;

		private static ConfigEntry<int>? softParticleCap;

		private static ConfigEntry<int>? hardParticleCap;

		private static ConfigEntry<int>? absoluteParticleCap;

		private static ConfigEntry<int>? softSpawnsPerFrame;

		private static ConfigEntry<int>? hardSpawnsPerFrame;

		private static ConfigEntry<int>? absoluteSpawnsPerFrame;

		private static ConfigEntry<float>? softPeakDamageFraction;

		private static ConfigEntry<float>? hardPeakDamageFraction;

		private static ConfigEntry<float>? absolutePeakDamageFraction;

		private static ConfigEntry<float>? softMinimumDamage;

		private static ConfigEntry<float>? hardMinimumDamage;

		private static ConfigEntry<float>? absoluteMinimumDamage;

		private static ConfigEntry<float>? peakDamageHalfLifeSeconds;

		private static ConfigEntry<bool>? preserveCriticalHits;

		private static ConfigEntry<bool>? preserveImportantColors;

		private static ConfigEntry<bool>? enableDynamicBoneInvisibleThrottling;

		private static ConfigEntry<int>? dynamicBoneInvisibleUpdateInterval;

		private static ConfigEntry<int>? dynamicBoneRecentlyVisibleGraceFrames;

		private static ConfigEntry<float>? dynamicBoneVisibleMidDistance;

		private static ConfigEntry<float>? dynamicBoneVisibleFarDistance;

		private static ConfigEntry<int>? dynamicBoneVisibleMidUpdateInterval;

		private static ConfigEntry<int>? dynamicBoneVisibleFarUpdateInterval;

		private static ConfigEntry<bool>? enableGenericIkInvisibleThrottling;

		private static ConfigEntry<int>? genericIkInvisibleUpdateInterval;

		private static ConfigEntry<int>? genericIkRecentlyVisibleGraceFrames;

		public static bool EnableDamageNumberLoadShedding => enableDamageNumberLoadShedding?.Value ?? true;

		public static int SoftParticleCap => softParticleCap?.Value ?? 128;

		public static int HardParticleCap => hardParticleCap?.Value ?? 192;

		public static int AbsoluteParticleCap => absoluteParticleCap?.Value ?? 256;

		public static int SoftSpawnsPerFrame => softSpawnsPerFrame?.Value ?? 24;

		public static int HardSpawnsPerFrame => hardSpawnsPerFrame?.Value ?? 40;

		public static int AbsoluteSpawnsPerFrame => absoluteSpawnsPerFrame?.Value ?? 56;

		public static float SoftPeakDamageFraction => softPeakDamageFraction?.Value ?? 0.03f;

		public static float HardPeakDamageFraction => hardPeakDamageFraction?.Value ?? 0.08f;

		public static float AbsolutePeakDamageFraction => absolutePeakDamageFraction?.Value ?? 0.16f;

		public static float SoftMinimumDamage => softMinimumDamage?.Value ?? 1f;

		public static float HardMinimumDamage => hardMinimumDamage?.Value ?? 2f;

		public static float AbsoluteMinimumDamage => absoluteMinimumDamage?.Value ?? 4f;

		public static float PeakDamageHalfLifeSeconds => peakDamageHalfLifeSeconds?.Value ?? 1.5f;

		public static bool PreserveCriticalHits => preserveCriticalHits?.Value ?? true;

		public static bool PreserveImportantColors => preserveImportantColors?.Value ?? true;

		public static bool EnableDynamicBoneInvisibleThrottling => enableDynamicBoneInvisibleThrottling?.Value ?? true;

		public static int DynamicBoneInvisibleUpdateInterval => dynamicBoneInvisibleUpdateInterval?.Value ?? 3;

		public static int DynamicBoneRecentlyVisibleGraceFrames => dynamicBoneRecentlyVisibleGraceFrames?.Value ?? 12;

		public static float DynamicBoneVisibleMidDistance => dynamicBoneVisibleMidDistance?.Value ?? 30f;

		public static float DynamicBoneVisibleFarDistance => dynamicBoneVisibleFarDistance?.Value ?? 55f;

		public static int DynamicBoneVisibleMidUpdateInterval => dynamicBoneVisibleMidUpdateInterval?.Value ?? 2;

		public static int DynamicBoneVisibleFarUpdateInterval => dynamicBoneVisibleFarUpdateInterval?.Value ?? 3;

		public static bool EnableGenericIkInvisibleThrottling => enableGenericIkInvisibleThrottling?.Value ?? true;

		public static int GenericIkInvisibleUpdateInterval => genericIkInvisibleUpdateInterval?.Value ?? 2;

		public static int GenericIkRecentlyVisibleGraceFrames => genericIkRecentlyVisibleGraceFrames?.Value ?? 8;

		public static void Bind(ConfigFile config)
		{
			enableDamageNumberLoadShedding = config.Bind<bool>("Damage Numbers", "Enable Load Shedding", true, "Reduces the number of spawned damage number particles during heavy combat.");
			softParticleCap = config.Bind<int>("Damage Numbers", "Soft Particle Cap", 128, "Starts lightly sampling regular damage numbers when active particles reach this amount.");
			hardParticleCap = config.Bind<int>("Damage Numbers", "Hard Particle Cap", 192, "Uses stronger sampling when active particles reach this amount.");
			absoluteParticleCap = config.Bind<int>("Damage Numbers", "Absolute Particle Cap", 256, "Uses the strongest sampling when active particles reach this amount.");
			softSpawnsPerFrame = config.Bind<int>("Damage Numbers", "Soft Spawns Per Frame", 24, "Starts lightly sampling regular damage numbers when this many spawns happen in one frame.");
			hardSpawnsPerFrame = config.Bind<int>("Damage Numbers", "Hard Spawns Per Frame", 40, "Uses stronger sampling when this many spawns happen in one frame.");
			absoluteSpawnsPerFrame = config.Bind<int>("Damage Numbers", "Absolute Spawns Per Frame", 56, "Uses the strongest sampling when this many spawns happen in one frame.");
			softPeakDamageFraction = config.Bind<float>("Damage Numbers", "Soft Peak Damage Fraction", 0.03f, "During soft load shedding, regular hits at or above this fraction of the recent peak damage are preserved.");
			hardPeakDamageFraction = config.Bind<float>("Damage Numbers", "Hard Peak Damage Fraction", 0.08f, "During hard load shedding, regular hits at or above this fraction of the recent peak damage are preserved.");
			absolutePeakDamageFraction = config.Bind<float>("Damage Numbers", "Absolute Peak Damage Fraction", 0.16f, "During the strongest load shedding, regular hits at or above this fraction of the recent peak damage are preserved.");
			softMinimumDamage = config.Bind<float>("Damage Numbers", "Soft Minimum Damage", 1f, "During soft load shedding, regular hits at or above this raw damage value are preserved even if recent peak damage is low.");
			hardMinimumDamage = config.Bind<float>("Damage Numbers", "Hard Minimum Damage", 2f, "During hard load shedding, regular hits at or above this raw damage value are preserved even if recent peak damage is low.");
			absoluteMinimumDamage = config.Bind<float>("Damage Numbers", "Absolute Minimum Damage", 4f, "During the strongest load shedding, regular hits at or above this raw damage value are preserved even if recent peak damage is low.");
			peakDamageHalfLifeSeconds = config.Bind<float>("Damage Numbers", "Peak Damage Half Life Seconds", 1.5f, "How quickly the recent peak damage estimate decays back down after large hits stop happening.");
			preserveCriticalHits = config.Bind<bool>("Damage Numbers", "Preserve Critical Hits", true, "Always allow critical hit damage numbers through the load shedding filter.");
			preserveImportantColors = config.Bind<bool>("Damage Numbers", "Preserve Important Colors", true, "Always allow important color categories like heal and weak point through the load shedding filter.");
			enableDynamicBoneInvisibleThrottling = config.Bind<bool>("Dynamic Bones", "Enable Invisible Update Throttling", true, "Throttles DynamicBone LateUpdate calls when the affected renderers are offscreen.");
			dynamicBoneInvisibleUpdateInterval = config.Bind<int>("Dynamic Bones", "Invisible Update Interval", 3, "When a DynamicBone is offscreen for a while, only let it fully update once every N frames.");
			dynamicBoneRecentlyVisibleGraceFrames = config.Bind<int>("Dynamic Bones", "Recently Visible Grace Frames", 12, "Keeps DynamicBone updating normally for a short time after it leaves the screen to reduce visible popping.");
			dynamicBoneVisibleMidDistance = config.Bind<float>("Dynamic Bones", "Visible Mid Distance", 30f, "When a visible DynamicBone rig is at least this far from the camera, it can be updated less often.");
			dynamicBoneVisibleFarDistance = config.Bind<float>("Dynamic Bones", "Visible Far Distance", 55f, "When a visible DynamicBone rig is at least this far from the camera, it can be updated even less often.");
			dynamicBoneVisibleMidUpdateInterval = config.Bind<int>("Dynamic Bones", "Visible Mid Update Interval", 2, "When a visible DynamicBone rig is beyond the mid distance, only run a full LateUpdate once every N frames.");
			dynamicBoneVisibleFarUpdateInterval = config.Bind<int>("Dynamic Bones", "Visible Far Update Interval", 3, "When a visible DynamicBone rig is beyond the far distance, only run a full LateUpdate once every N frames.");
			enableGenericIkInvisibleThrottling = config.Bind<bool>("Generic IK", "Enable Invisible Update Throttling", true, "Throttles GenericIK LateUpdate calls when the animated character has been offscreen for a short time.");
			genericIkInvisibleUpdateInterval = config.Bind<int>("Generic IK", "Invisible Update Interval", 2, "When a GenericIK rig is offscreen, only let it run a full LateUpdate once every N frames.");
			genericIkRecentlyVisibleGraceFrames = config.Bind<int>("Generic IK", "Recently Visible Grace Frames", 8, "Keeps GenericIK updating normally for a short time after it leaves the screen to reduce visible snapping.");
		}
	}
	[BepInPlugin("net.sixik.plugin.roro", "ROR-O", "1.0.4")]
	public sealed class RORO : BaseUnityPlugin
	{
		private const string Modguid = "net.sixik.plugin.roro";

		private const string ModName = "ROR-O";

		private const string ModVersion = "1.0.4";

		public static ManualLogSource? GlobalLogger { get; private set; }

		private void Awake()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			GlobalLogger = ((BaseUnityPlugin)this).Logger;
			GlobalLogger.LogInfo((object)"Initialize ROR-O mod: ROR-O v1.0.4");
			ROROConfig.Bind(((BaseUnityPlugin)this).Config);
			new Harmony("net.sixik.plugin.roro").PatchAll();
			GlobalLogger.LogInfo((object)"Harmony patches applied successfully!");
		}
	}
}
namespace ROR_O.Utilities
{
	internal sealed class FixedConditionalWeakTable<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, FixedConditionalWeakTableManager.IShrinkable where TKey : class where TValue : class
	{
		private readonly struct WeakReferenceWrapper<T> where T : class
		{
			public readonly int TargetHashCode;

			public readonly WeakReference<T>? WeakReference;

			public readonly T? Target;

			public WeakReferenceWrapper(T target, bool strongReference)
			{
				TargetHashCode = target.GetHashCode();
				if (strongReference)
				{
					Target = target;
					WeakReference = null;
				}
				else
				{
					Target = null;
					WeakReference = new WeakReference<T>(target);
				}
			}

			public WeakReferenceWrapper(int targetHashCode)
			{
				TargetHashCode = targetHashCode;
				Target = null;
				WeakReference = null;
			}
		}

		[StructLayout(LayoutKind.Sequential, Size = 1)]
		private readonly struct WeakReferenceWrapperComparer<T> : IEqualityComparer<WeakReferenceWrapper<T>> where T : class
		{
			public bool Equals(WeakReferenceWrapper<T> first, WeakReferenceWrapper<T> second)
			{
				T target = first.Target;
				T target2 = second.Target;
				T target3;
				if (target == null && first.WeakReference == null)
				{
					if (second.WeakReference != null)
					{
						return !second.WeakReference.TryGetTarget(out target3);
					}
					return false;
				}
				if (target2 == null && second.WeakReference == null)
				{
					if (first.WeakReference != null)
					{
						return !first.WeakReference.TryGetTarget(out target3);
					}
					return false;
				}
				if (target == null && (first.WeakReference == null || !first.WeakReference.TryGetTarget(out target)))
				{
					return false;
				}
				if (target2 == null && (second.WeakReference == null || !second.WeakReference.TryGetTarget(out target2)))
				{
					return false;
				}
				return target == target2;
			}

			public int GetHashCode(WeakReferenceWrapper<T> obj)
			{
				return obj.TargetHashCode;
			}
		}

		private ConstructorInfo? cachedConstructor;

		private readonly ConcurrentDictionary<WeakReferenceWrapper<TKey>, TValue> valueByKey = new ConcurrentDictionary<WeakReferenceWrapper<TKey>, TValue>(default(WeakReferenceWrapperComparer<TKey>));

		public TValue this[TKey key]
		{
			get
			{
				return valueByKey[new WeakReferenceWrapper<TKey>(key, strongReference: true)];
			}
			set
			{
				valueByKey[new WeakReferenceWrapper<TKey>(key, strongReference: false)] = value;
			}
		}

		public ICollection<TKey> Keys
		{
			get
			{
				List<TKey> list = new List<TKey>(valueByKey.Count);
				foreach (WeakReferenceWrapper<TKey> key in valueByKey.Keys)
				{
					if (key.WeakReference != null && key.WeakReference.TryGetTarget(out var target))
					{
						list.Add(target);
					}
				}
				return list.AsReadOnly();
			}
		}

		public ICollection<TValue> Values
		{
			get
			{
				List<TValue> list = new List<TValue>(valueByKey.Count);
				foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey)
				{
					if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var _))
					{
						list.Add(item.Value);
					}
				}
				return list.AsReadOnly();
			}
		}

		public int Count
		{
			get
			{
				int num = 0;
				foreach (WeakReferenceWrapper<TKey> key in valueByKey.Keys)
				{
					if (key.WeakReference != null && key.WeakReference.TryGetTarget(out var _))
					{
						num++;
					}
				}
				return num;
			}
		}

		public int SpeculativeCount => valueByKey.Count;

		bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;

		IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;

		IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;

		public FixedConditionalWeakTable()
		{
			FixedConditionalWeakTableManager.Add(this);
		}

		public void Add(TKey key, TValue value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (!valueByKey.TryAdd(new WeakReferenceWrapper<TKey>(key, strongReference: false), value))
			{
				throw new ArgumentException("The key already exists", "key");
			}
		}

		public bool Remove(TKey key)
		{
			TValue value;
			return valueByKey.TryRemove(new WeakReferenceWrapper<TKey>(key, strongReference: true), out value);
		}

		public bool TryGetValue(TKey key, out TValue value)
		{
			return valueByKey.TryGetValue(new WeakReferenceWrapper<TKey>(key, strongReference: true), out value);
		}

		public TValue GetValue(TKey key, Func<TKey, TValue> defaultFunc)
		{
			if (TryGetValue(key, out var value))
			{
				return value;
			}
			value = defaultFunc(key);
			Add(key, value);
			return value;
		}

		public TValue GetOrCreateValue(TKey key)
		{
			if (TryGetValue(key, out var value))
			{
				return value;
			}
			if (cachedConstructor == null)
			{
				Type typeFromHandle = typeof(TValue);
				cachedConstructor = typeFromHandle.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (cachedConstructor == null)
				{
					throw new MissingMethodException(typeFromHandle.FullName + " doesn't have a parameterless constructor");
				}
			}
			value = (TValue)cachedConstructor.Invoke(Array.Empty<object>());
			Add(key, value);
			return value;
		}

		void FixedConditionalWeakTableManager.IShrinkable.Shrink()
		{
			foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey)
			{
				if (item.Key.WeakReference != null && !item.Key.WeakReference.TryGetTarget(out var _))
				{
					valueByKey.TryRemove(new WeakReferenceWrapper<TKey>(item.Key.TargetHashCode), out var _);
				}
			}
		}

		public bool ContainsKey(TKey key)
		{
			return valueByKey.ContainsKey(new WeakReferenceWrapper<TKey>(key, strongReference: true));
		}

		public void Clear()
		{
			valueByKey.Clear();
		}

		void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
		{
			Add(item.Key, item.Value);
		}

		bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
		{
			if (TryGetValue(item.Key, out var value))
			{
				return EqualityComparer<TValue>.Default.Equals(value, item.Value);
			}
			return false;
		}

		void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (arrayIndex < 0 || arrayIndex >= array.Length)
			{
				throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is not a valid index in array");
			}
			int count = Count;
			if (arrayIndex + count > array.Length)
			{
				throw new ArgumentOutOfRangeException("array", "Destination array is not long enough to copy all the items in the collection.");
			}
			foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey)
			{
				if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var target))
				{
					array[arrayIndex++] = new KeyValuePair<TKey, TValue>(target, item.Value);
				}
			}
		}

		bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
		{
			if (TryGetValue(item.Key, out var value) && EqualityComparer<TValue>.Default.Equals(value, item.Value))
			{
				return Remove(item.Key);
			}
			return false;
		}

		public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
		{
			foreach (KeyValuePair<WeakReferenceWrapper<TKey>, TValue> item in valueByKey)
			{
				if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var target))
				{
					yield return new KeyValuePair<TKey, TValue>(target, item.Value);
				}
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	internal static class FixedConditionalWeakTableManager
	{
		internal interface IShrinkable
		{
			void Shrink();
		}

		private const int ShrinkAttemptDelayMilliseconds = 2000;

		private static readonly object LockObject = new object();

		private static readonly List<WeakReference<IShrinkable>> Instances = new List<WeakReference<IShrinkable>>();

		private static int lastCollectionCount;

		public static void Add(IShrinkable weakTable)
		{
			lock (LockObject)
			{
				if (Instances.Count == 0)
				{
					Thread thread = new Thread(ShrinkThreadLoop);
					thread.IsBackground = true;
					thread.Name = "ROR-O FixedConditionalWeakTable Shrinker";
					thread.Start();
				}
				Instances.Add(new WeakReference<IShrinkable>(weakTable));
			}
		}

		private static void ShrinkThreadLoop()
		{
			while (true)
			{
				Thread.Sleep(2000);
				int num = GC.CollectionCount(2);
				if (lastCollectionCount == num)
				{
					continue;
				}
				lastCollectionCount = num;
				lock (LockObject)
				{
					for (int num2 = Instances.Count - 1; num2 >= 0; num2--)
					{
						if (!Instances[num2].TryGetTarget(out IShrinkable target))
						{
							Instances.RemoveAt(num2);
						}
						else
						{
							target.Shrink();
						}
					}
					if (Instances.Count == 0)
					{
						break;
					}
				}
			}
		}
	}
}
namespace ROR_O.patches
{
	[HarmonyPatch(typeof(Glaze), "FixedUpdate")]
	public class OptimizeChefGlazePatch
	{
		private static readonly MethodInfo GetFastMuzzleMethod = AccessTools.Method(typeof(OptimizeChefGlazePatch), "GetFastMuzzle", (Type[])null, (Type[])null);

		private static readonly string[] CachedMuzzles = new string[6] { "MuzzleGlaze0", "MuzzleGlaze1", "MuzzleGlaze2", "MuzzleGlaze3", "MuzzleGlaze4", "MuzzleGlaze5" };

		public static string GetFastMuzzle(Glaze instance)
		{
			int muzzleStringEndNum = instance.muzzleStringEndNum;
			if (muzzleStringEndNum >= 0 && muzzleStringEndNum < CachedMuzzles.Length)
			{
				return CachedMuzzles[muzzleStringEndNum];
			}
			return "MuzzleGlaze" + muzzleStringEndNum;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo objB = AccessTools.Method(typeof(string), "Concat", new Type[2]
			{
				typeof(string),
				typeof(string)
			}, (Type[])null);
			int num = -1;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldstr && object.Equals(list[i].operand, "MuzzleGlaze"))
				{
					num = i;
					break;
				}
			}
			if (num >= 0)
			{
				int num2 = -1;
				for (int j = num; j < list.Count; j++)
				{
					if (list[j].opcode == OpCodes.Call && object.Equals(list[j].operand, objB))
					{
						num2 = j;
						break;
					}
				}
				if (num2 >= num)
				{
					list.RemoveRange(num, num2 - num + 1);
					list.Insert(num, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)GetFastMuzzleMethod));
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(TitanRockController), "FixedUpdate")]
	public static class OptimizeTitanRockControllerPatch
	{
		private static readonly MethodInfo ComponentGetParticleSystemsInChildrenMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentsInChildrenMethod(typeof(ParticleSystem));

		private static readonly MethodInfo ComponentGetLightsInChildrenMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentsInChildrenMethod(typeof(Light));

		private static readonly MethodInfo ComponentGetParticleSystemMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ParticleSystem));

		private static readonly MethodInfo TransformFindMethod = AccessTools.Method(typeof(Transform), "Find", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo CachedParticleSystemsInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetParticleSystemsInChildren", new Type[1] { typeof(Component) }, (Type[])null);

		private static readonly MethodInfo CachedLightsInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetLightsInChildren", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedParticleSystemMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetParticleSystem", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedTransformFindMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindTransform", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetParticleSystemsInChildrenMethod, CachedParticleSystemsInChildrenMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetLightsInChildrenMethod, CachedLightsInChildrenMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetParticleSystemMethod, CachedParticleSystemMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, TransformFindMethod, CachedTransformFindMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"TitanRockController.FixedUpdate optimized: cached hierarchy calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(TalismanAnimator), "FixedUpdate")]
	public static class OptimizeTalismanAnimatorPatch
	{
		private static readonly MethodInfo GameObjectGetParticleSystemsInChildrenMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentsInChildrenMethod(typeof(ParticleSystem));

		private static readonly MethodInfo CachedParticleSystemsInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetParticleSystemsInChildren", new Type[1] { typeof(GameObject) }, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetParticleSystemsInChildrenMethod, CachedParticleSystemsInChildrenMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"TalismanAnimator.FixedUpdate optimized: cached hierarchy calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(GravCubeController), "Update")]
	public static class OptimizeGravCubeControllerPatch
	{
		private static readonly MethodInfo GameObjectGetAnimatorInChildrenMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentInChildrenMethod(typeof(Animator));

		private static readonly MethodInfo CachedAnimatorInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetAnimatorInChildren", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetAnimatorInChildrenMethod, CachedAnimatorInChildrenMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"GravCubeController.Update optimized: cached hierarchy calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(JellyBarrage), "FixedUpdate")]
	public static class OptimizeJellyBarragePatch
	{
		private static readonly MethodInfo ChildLocatorFindChildMethod = AccessTools.Method(typeof(ChildLocator), "FindChild", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo CachedChildLocatorFindMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindChild", new Type[2]
		{
			typeof(ChildLocator),
			typeof(string)
		}, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ChildLocatorFindChildMethod, CachedChildLocatorFindMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"JellyBarrage.FixedUpdate optimized: cached hierarchy calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(JellyStorm), "FixedUpdate")]
	public static class OptimizeJellyStormPatch
	{
		private static readonly MethodInfo ChildLocatorFindChildMethod = AccessTools.Method(typeof(ChildLocator), "FindChild", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo CachedChildLocatorFindMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindChild", new Type[2]
		{
			typeof(ChildLocator),
			typeof(string)
		}, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ChildLocatorFindChildMethod, CachedChildLocatorFindMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"JellyStorm.FixedUpdate optimized: cached hierarchy calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(SwipeForward), "FixedUpdate")]
	public static class OptimizeSwipeForwardPatch
	{
		private static readonly MethodInfo ComponentGetCharacterDirectionMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterDirection));

		private static readonly MethodInfo CachedCharacterDirectionMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterDirectionFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterDirectionMethod, CachedCharacterDirectionMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"SwipeForward.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(GroundLight), "FixedUpdate")]
	public static class OptimizeGroundLightPatch
	{
		private static readonly MethodInfo ComponentGetCharacterDirectionMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterDirection));

		private static readonly MethodInfo CachedCharacterDirectionMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterDirectionFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterDirectionMethod, CachedCharacterDirectionMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"GroundLight.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(SlashCombo), "FixedUpdate")]
	public static class OptimizeSlashComboPatch
	{
		private static readonly MethodInfo ComponentGetCharacterDirectionMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterDirection));

		private static readonly MethodInfo CachedCharacterDirectionMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterDirectionFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterDirectionMethod, CachedCharacterDirectionMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"SlashCombo.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(Assaulter), "FixedUpdate")]
	public static class OptimizeAssaulterPatch
	{
		private static readonly MethodInfo ComponentGetCharacterModelMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterModel));

		private static readonly MethodInfo CachedCharacterModelMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterModelFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterModelMethod, CachedCharacterModelMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"Assaulter.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(Evis), "FixedUpdate")]
	public static class OptimizeEvisPatch
	{
		private static readonly MethodInfo ComponentGetCharacterModelMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterModel));

		private static readonly MethodInfo CachedCharacterModelMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterModelFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterModelMethod, CachedCharacterModelMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"Evis.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(EvisDash), "FixedUpdate")]
	public static class OptimizeEvisDashPatch
	{
		private static readonly MethodInfo ComponentGetCharacterModelMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterModel));

		private static readonly MethodInfo ComponentGetHurtBoxMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HurtBox));

		private static readonly MethodInfo CachedCharacterModelMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterModelFromComponent", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedHurtBoxMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHurtBoxFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterModelMethod, CachedCharacterModelMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHurtBoxMethod, CachedHurtBoxMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"EvisDash.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(KickFromShop), "FixedUpdate")]
	public static class OptimizeKickFromShopPatch
	{
		private static readonly MethodInfo ComponentGetHurtBoxGroupMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HurtBoxGroup));

		private static readonly MethodInfo CachedHurtBoxGroupMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHurtBoxGroupFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHurtBoxGroupMethod, CachedHurtBoxGroupMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"KickFromShop.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(DashSlam), "FixedUpdate")]
	public static class OptimizeDashSlamPatch
	{
		private static readonly MethodInfo ComponentGetHurtBoxMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HurtBox));

		private static readonly MethodInfo CachedHurtBoxMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHurtBoxFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHurtBoxMethod, CachedHurtBoxMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"DashSlam.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(ClapState), "FixedUpdate")]
	public static class OptimizeClapStatePatch
	{
		private static readonly MethodInfo ComponentGetChildLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ChildLocator));

		private static readonly MethodInfo CachedChildLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChildLocatorFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetChildLocatorMethod, CachedChildLocatorMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"ClapState.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(LaserFather), "FixedUpdate")]
	public static class OptimizeLaserFatherPatch
	{
		private static readonly MethodInfo ComponentGetChildLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ChildLocator));

		private static readonly MethodInfo CachedChildLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChildLocatorFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetChildLocatorMethod, CachedChildLocatorMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"LaserFather.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	internal enum DamageNumberLoadLevel
	{
		None,
		Soft,
		Hard,
		Absolute
	}
	internal static class DamageNumberLoadShedState
	{
		private static readonly FieldRef<DamageNumberManager, ParticleSystem> ParticleSystemField = AccessTools.FieldRefAccess<DamageNumberManager, ParticleSystem>("ps");

		private static int lastFrame = -1;

		private static int spawnsThisFrame;

		private static uint noisySpawnSequence;

		private static float recentPeakDamage = 1f;

		private static float lastPeakUpdateTime;

		public static bool ShouldAllowSpawn(DamageNumberManager? manager, float damage, bool crit, DamageColorIndex damageColorIndex)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!ROROConfig.EnableDamageNumberLoadShedding)
			{
				return true;
			}
			int frameCount = Time.frameCount;
			if (frameCount != lastFrame)
			{
				lastFrame = frameCount;
				spawnsThisFrame = 0;
			}
			int activeDamageNumberCount = GetActiveDamageNumberCount(manager);
			bool flag = IsCriticalColor(damageColorIndex);
			UpdateRecentPeakDamage(damage);
			int orderedThreshold = GetOrderedThreshold(ROROConfig.SoftParticleCap, 1);
			int orderedThreshold2 = GetOrderedThreshold(ROROConfig.HardParticleCap, orderedThreshold);
			int orderedThreshold3 = GetOrderedThreshold(ROROConfig.AbsoluteParticleCap, orderedThreshold2);
			int orderedThreshold4 = GetOrderedThreshold(ROROConfig.SoftSpawnsPerFrame, 1);
			int orderedThreshold5 = GetOrderedThreshold(ROROConfig.HardSpawnsPerFrame, orderedThreshold4);
			DamageNumberLoadLevel damageNumberLoadLevel = GetLoadLevel(absoluteSpawnsPerFrame: GetOrderedThreshold(ROROConfig.AbsoluteSpawnsPerFrame, orderedThreshold5), activeDamageNumbers: activeDamageNumberCount, currentSpawnsPerFrame: spawnsThisFrame, softParticleCap: orderedThreshold, hardParticleCap: orderedThreshold2, absoluteParticleCap: orderedThreshold3, softSpawnsPerFrame: orderedThreshold4, hardSpawnsPerFrame: orderedThreshold5);
			if (damageNumberLoadLevel == DamageNumberLoadLevel.None)
			{
				spawnsThisFrame++;
				return true;
			}
			if (flag || crit || IsHighPriorityDamage(damage, damageNumberLoadLevel))
			{
				spawnsThisFrame++;
				return true;
			}
			switch (damageNumberLoadLevel)
			{
			case DamageNumberLoadLevel.Absolute:
				if (!ShouldSample(crit, flag, 3, 8))
				{
					return false;
				}
				break;
			case DamageNumberLoadLevel.Hard:
				if (!ShouldSample(crit, flag, 2, 4))
				{
					return false;
				}
				break;
			default:
				if (!ShouldSample(crit, flag, 1, 2))
				{
					return false;
				}
				break;
			}
			spawnsThisFrame++;
			return true;
		}

		private static int GetActiveDamageNumberCount(DamageNumberManager? manager)
		{
			if ((Object)(object)manager == (Object)null)
			{
				return 0;
			}
			ParticleSystem val = ParticleSystemField.Invoke(manager);
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			return val.particleCount;
		}

		private static void UpdateRecentPeakDamage(float damage)
		{
			float unscaledTime = Time.unscaledTime;
			float num = recentPeakDamage;
			float num2 = unscaledTime - lastPeakUpdateTime;
			lastPeakUpdateTime = unscaledTime;
			float num3 = Mathf.Max(0.05f, ROROConfig.PeakDamageHalfLifeSeconds);
			if (num2 > 0f)
			{
				float num4 = Mathf.Pow(0.5f, num2 / num3);
				num = Mathf.Max(1f, num * num4);
			}
			if (damage > num)
			{
				num = damage;
			}
			recentPeakDamage = Mathf.Max(1f, num);
		}

		private static DamageNumberLoadLevel GetLoadLevel(int activeDamageNumbers, int currentSpawnsPerFrame, int softParticleCap, int hardParticleCap, int absoluteParticleCap, int softSpawnsPerFrame, int hardSpawnsPerFrame, int absoluteSpawnsPerFrame)
		{
			if (activeDamageNumbers >= absoluteParticleCap || currentSpawnsPerFrame >= absoluteSpawnsPerFrame)
			{
				return DamageNumberLoadLevel.Absolute;
			}
			if (activeDamageNumbers >= hardParticleCap || currentSpawnsPerFrame >= hardSpawnsPerFrame)
			{
				return DamageNumberLoadLevel.Hard;
			}
			if (activeDamageNumbers >= softParticleCap || currentSpawnsPerFrame >= softSpawnsPerFrame)
			{
				return DamageNumberLoadLevel.Soft;
			}
			return DamageNumberLoadLevel.None;
		}

		private static int GetOrderedThreshold(int configuredValue, int minimumValue)
		{
			if (configuredValue >= minimumValue)
			{
				return configuredValue;
			}
			return minimumValue;
		}

		private static bool IsHighPriorityDamage(float damage, DamageNumberLoadLevel loadLevel)
		{
			float orderedFraction;
			float orderedFloat;
			switch (loadLevel)
			{
			case DamageNumberLoadLevel.Absolute:
				orderedFraction = GetOrderedFraction(ROROConfig.AbsolutePeakDamageFraction, ROROConfig.HardPeakDamageFraction);
				orderedFloat = GetOrderedFloat(ROROConfig.AbsoluteMinimumDamage, ROROConfig.HardMinimumDamage);
				break;
			case DamageNumberLoadLevel.Hard:
				orderedFraction = GetOrderedFraction(ROROConfig.HardPeakDamageFraction, ROROConfig.SoftPeakDamageFraction);
				orderedFloat = GetOrderedFloat(ROROConfig.HardMinimumDamage, ROROConfig.SoftMinimumDamage);
				break;
			default:
				orderedFraction = GetOrderedFraction(ROROConfig.SoftPeakDamageFraction, 0f);
				orderedFloat = GetOrderedFloat(ROROConfig.SoftMinimumDamage, 0f);
				break;
			}
			float num = recentPeakDamage * orderedFraction;
			float num2 = Mathf.Max(orderedFloat, num);
			return damage >= num2;
		}

		private static float GetOrderedFraction(float configuredValue, float minimumValue)
		{
			return Mathf.Clamp((configuredValue < minimumValue) ? minimumValue : configuredValue, 0f, 1f);
		}

		private static float GetOrderedFloat(float configuredValue, float minimumValue)
		{
			if (!(configuredValue < minimumValue))
			{
				return configuredValue;
			}
			return minimumValue;
		}

		private static bool ShouldSample(bool crit, bool criticalColor, int critDivisor, int noisyDivisor)
		{
			if (criticalColor)
			{
				return true;
			}
			int num = (crit ? critDivisor : noisyDivisor);
			if (num <= 1)
			{
				return true;
			}
			noisySpawnSequence++;
			return noisySpawnSequence % (uint)num == 0;
		}

		private static bool IsCriticalColor(DamageColorIndex damageColorIndex)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			if (!ROROConfig.PreserveImportantColors)
			{
				return false;
			}
			if ((int)damageColorIndex == 1 || damageColorIndex - 5 <= 1 || damageColorIndex - 12 <= 2)
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(DamageNumberManager), "SpawnDamageNumber")]
	public static class OptimizeDamageNumberManagerSpawnPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(DamageNumberManager __instance, float amount, bool crit, DamageColorIndex damageColorIndex)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			bool crit2 = ROROConfig.PreserveCriticalHits && crit;
			return DamageNumberLoadShedState.ShouldAllowSpawn(__instance, amount, crit2, damageColorIndex);
		}
	}
	internal static class OptimizedComponentCache
	{
		private sealed class CacheBox<T> where T : class
		{
			public T? Value;
		}

		private sealed class NamedTransformCache
		{
			public readonly Dictionary<string, Transform?> Values = new Dictionary<string, Transform>();
		}

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterBody>> CharacterBodies = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterBody>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterMaster>> CharacterMasters = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterMaster>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<EquipmentSlot>> EquipmentSlots = new FixedConditionalWeakTable<GameObject, CacheBox<EquipmentSlot>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HealthComponent>> HealthComponents = new FixedConditionalWeakTable<GameObject, CacheBox<HealthComponent>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HuntressTracker>> HuntressTrackers = new FixedConditionalWeakTable<GameObject, CacheBox<HuntressTracker>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<DamageTrail>> DamageTrails = new FixedConditionalWeakTable<GameObject, CacheBox<DamageTrail>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody>> Rigidbodies = new FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody2D>> Rigidbodies2D = new FixedConditionalWeakTable<GameObject, CacheBox<Rigidbody2D>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<IInspectable>> Inspectables = new FixedConditionalWeakTable<GameObject, CacheBox<IInspectable>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<IInteractable>> Interactables = new FixedConditionalWeakTable<GameObject, CacheBox<IInteractable>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<InteractionDriver>> InteractionDrivers = new FixedConditionalWeakTable<GameObject, CacheBox<InteractionDriver>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<InputBankTest>> InputBankTests = new FixedConditionalWeakTable<GameObject, CacheBox<InputBankTest>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CameraTargetParams>> CameraTargetParamsCache = new FixedConditionalWeakTable<GameObject, CacheBox<CameraTargetParams>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ChefController>> ChefControllers = new FixedConditionalWeakTable<GameObject, CacheBox<ChefController>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterMotor>> CharacterMotors = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterMotor>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<RigidbodyMotor>> RigidbodyMotors = new FixedConditionalWeakTable<GameObject, CacheBox<RigidbodyMotor>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<KinematicCharacterMotor>> KinematicCharacterMotors = new FixedConditionalWeakTable<GameObject, CacheBox<KinematicCharacterMotor>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<NetworkIdentity>> NetworkIdentities = new FixedConditionalWeakTable<GameObject, CacheBox<NetworkIdentity>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<NetworkUser>> NetworkUsers = new FixedConditionalWeakTable<GameObject, CacheBox<NetworkUser>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<FalseSonBossController>> FalseSonBossControllers = new FixedConditionalWeakTable<GameObject, CacheBox<FalseSonBossController>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<OilGhostController>> OilGhostControllers = new FixedConditionalWeakTable<GameObject, CacheBox<OilGhostController>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<PlayerCharacterMasterController>> PlayerCharacterMasterControllers = new FixedConditionalWeakTable<GameObject, CacheBox<PlayerCharacterMasterController>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<SkillLocator>> SkillLocators = new FixedConditionalWeakTable<GameObject, CacheBox<SkillLocator>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<TeamFilter>> TeamFilters = new FixedConditionalWeakTable<GameObject, CacheBox<TeamFilter>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ProjectileController>> ProjectileControllers = new FixedConditionalWeakTable<GameObject, CacheBox<ProjectileController>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ProjectileDamage>> ProjectileDamages = new FixedConditionalWeakTable<GameObject, CacheBox<ProjectileDamage>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ChildLocator>> ChildLocators = new FixedConditionalWeakTable<GameObject, CacheBox<ChildLocator>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ScaleParticleSystemDuration>> ScaleParticleSystemDurations = new FixedConditionalWeakTable<GameObject, CacheBox<ScaleParticleSystemDuration>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ObjectScaleCurve>> ObjectScaleCurves = new FixedConditionalWeakTable<GameObject, CacheBox<ObjectScaleCurve>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterDirection>> CharacterDirections = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterDirection>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<CharacterModel>> CharacterModels = new FixedConditionalWeakTable<GameObject, CacheBox<CharacterModel>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HurtBoxGroup>> HurtBoxGroups = new FixedConditionalWeakTable<GameObject, CacheBox<HurtBoxGroup>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<HurtBox>> HurtBoxes = new FixedConditionalWeakTable<GameObject, CacheBox<HurtBox>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Animator>> AnimatorsInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<Animator>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem>> ParticleSystems = new FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem[]>> ParticleSystemsInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<ParticleSystem[]>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Light[]>> LightsInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<Light[]>>();

		private static readonly FixedConditionalWeakTable<GameObject, CacheBox<Renderer[]>> RenderersInChildren = new FixedConditionalWeakTable<GameObject, CacheBox<Renderer[]>>();

		private static readonly FixedConditionalWeakTable<Transform, NamedTransformCache> TransformFindCache = new FixedConditionalWeakTable<Transform, NamedTransformCache>();

		private static readonly FixedConditionalWeakTable<ChildLocator, NamedTransformCache> ChildLocatorFindCache = new FixedConditionalWeakTable<ChildLocator, NamedTransformCache>();

		public static CharacterBody? GetCharacterBody(GameObject gameObject)
		{
			return GetOrAdd(gameObject, CharacterBodies, (GameObject target) => target.GetComponent<CharacterBody>());
		}

		public static CharacterBody? GetCharacterBodyFromComponent(Component component)
		{
			return GetOrAdd(component, CharacterBodies, (GameObject target) => target.GetComponent<CharacterBody>());
		}

		public static CharacterMaster? GetCharacterMaster(GameObject gameObject)
		{
			return GetOrAdd(gameObject, CharacterMasters, (GameObject target) => target.GetComponent<CharacterMaster>());
		}

		public static EquipmentSlot? GetEquipmentSlot(GameObject gameObject)
		{
			return GetOrAdd(gameObject, EquipmentSlots, (GameObject target) => target.GetComponent<EquipmentSlot>());
		}

		public static HealthComponent? GetHealthComponent(GameObject gameObject)
		{
			return GetOrAdd(gameObject, HealthComponents, (GameObject target) => target.GetComponent<HealthComponent>());
		}

		public static HealthComponent? GetHealthComponentFromComponent(Component component)
		{
			return GetOrAdd(component, HealthComponents, (GameObject target) => target.GetComponent<HealthComponent>());
		}

		public static HuntressTracker? GetHuntressTracker(GameObject gameObject)
		{
			return GetOrAdd(gameObject, HuntressTrackers, (GameObject target) => target.GetComponent<HuntressTracker>());
		}

		public static DamageTrail? GetDamageTrail(GameObject gameObject)
		{
			return GetOrAdd(gameObject, DamageTrails, (GameObject target) => target.GetComponent<DamageTrail>());
		}

		public static Rigidbody? GetRigidbody(GameObject gameObject)
		{
			return GetOrAdd(gameObject, Rigidbodies, (GameObject target) => target.GetComponent<Rigidbody>());
		}

		public static Rigidbody? GetRigidbodyFromComponent(Component component)
		{
			return GetOrAdd(component, Rigidbodies, (GameObject target) => target.GetComponent<Rigidbody>());
		}

		public static Rigidbody2D? GetRigidbody2D(GameObject gameObject)
		{
			return GetOrAdd(gameObject, Rigidbodies2D, (GameObject target) => target.GetComponent<Rigidbody2D>());
		}

		public static IInspectable? GetInspectable(GameObject gameObject)
		{
			return GetOrAdd(gameObject, Inspectables, (GameObject target) => target.GetComponent<IInspectable>());
		}

		public static IInteractable? GetInteractable(GameObject gameObject)
		{
			return GetOrAdd(gameObject, Interactables, (GameObject target) => target.GetComponent<IInteractable>());
		}

		public static InteractionDriver? GetInteractionDriver(GameObject gameObject)
		{
			return GetOrAdd(gameObject, InteractionDrivers, (GameObject target) => target.GetComponent<InteractionDriver>());
		}

		public static InteractionDriver? GetInteractionDriverFromComponent(Component component)
		{
			return GetOrAdd(component, InteractionDrivers, (GameObject target) => target.GetComponent<InteractionDriver>());
		}

		public static InputBankTest? GetInputBankTest(GameObject gameObject)
		{
			return GetOrAdd(gameObject, InputBankTests, (GameObject target) => target.GetComponent<InputBankTest>());
		}

		public static CameraTargetParams? GetCameraTargetParamsFromComponent(Component component)
		{
			return GetOrAdd(component, CameraTargetParamsCache, (GameObject target) => target.GetComponent<CameraTargetParams>());
		}

		public static ChefController? GetChefController(GameObject gameObject)
		{
			return GetOrAdd(gameObject, ChefControllers, (GameObject target) => target.GetComponent<ChefController>());
		}

		public static CharacterMotor? GetCharacterMotor(GameObject gameObject)
		{
			return GetOrAdd(gameObject, CharacterMotors, (GameObject target) => target.GetComponent<CharacterMotor>());
		}

		public static CharacterMotor? GetCharacterMotor(Component component)
		{
			return GetOrAdd(component, CharacterMotors, (GameObject target) => target.GetComponent<CharacterMotor>());
		}

		public static RigidbodyMotor? GetRigidbodyMotor(Component component)
		{
			return GetOrAdd(component, RigidbodyMotors, (GameObject target) => target.GetComponent<RigidbodyMotor>());
		}

		public static KinematicCharacterMotor? GetKinematicCharacterMotor(Component component)
		{
			return GetOrAdd(component, KinematicCharacterMotors, (GameObject target) => target.GetComponent<KinematicCharacterMotor>());
		}

		public static NetworkIdentity? GetNetworkIdentity(Component component)
		{
			return GetOrAdd(component, NetworkIdentities, (GameObject target) => target.GetComponent<NetworkIdentity>());
		}

		public static NetworkUser? GetNetworkUser(GameObject gameObject)
		{
			return GetOrAdd(gameObject, NetworkUsers, (GameObject target) => target.GetComponent<NetworkUser>());
		}

		public static FalseSonBossController? GetFalseSonBossControllerFromComponent(Component component)
		{
			return GetOrAdd(component, FalseSonBossControllers, (GameObject target) => target.GetComponent<FalseSonBossController>());
		}

		public static OilGhostController? GetOilGhostController(GameObject gameObject)
		{
			return GetOrAdd(gameObject, OilGhostControllers, (GameObject target) => target.GetComponent<OilGhostController>());
		}

		public static PlayerCharacterMasterController? GetPlayerCharacterMasterController(Component component)
		{
			return GetOrAdd(component, PlayerCharacterMasterControllers, (GameObject target) => target.GetComponent<PlayerCharacterMasterController>());
		}

		public static SkillLocator? GetSkillLocator(GameObject gameObject)
		{
			return GetOrAdd(gameObject, SkillLocators, (GameObject target) => target.GetComponent<SkillLocator>());
		}

		public static SkillLocator? GetSkillLocatorFromComponent(Component component)
		{
			return GetOrAdd(component, SkillLocators, (GameObject target) => target.GetComponent<SkillLocator>());
		}

		public static TeamFilter? GetTeamFilter(GameObject gameObject)
		{
			return GetOrAdd(gameObject, TeamFilters, (GameObject target) => target.GetComponent<TeamFilter>());
		}

		public static ProjectileController? GetProjectileController(GameObject gameObject)
		{
			return GetOrAdd(gameObject, ProjectileControllers, (GameObject target) => target.GetComponent<ProjectileController>());
		}

		public static ProjectileDamage? GetProjectileDamage(GameObject gameObject)
		{
			return GetOrAdd(gameObject, ProjectileDamages, (GameObject target) => target.GetComponent<ProjectileDamage>());
		}

		public static ChildLocator? GetChildLocatorFromComponent(Component component)
		{
			return GetOrAdd(component, ChildLocators, (GameObject target) => target.GetComponent<ChildLocator>());
		}

		public static ChildLocator? GetChildLocator(GameObject gameObject)
		{
			return GetOrAdd(gameObject, ChildLocators, (GameObject target) => target.GetComponent<ChildLocator>());
		}

		public static ScaleParticleSystemDuration? GetScaleParticleSystemDuration(GameObject gameObject)
		{
			return GetOrAdd(gameObject, ScaleParticleSystemDurations, (GameObject target) => target.GetComponent<ScaleParticleSystemDuration>());
		}

		public static ScaleParticleSystemDuration? GetScaleParticleSystemDurationFromComponent(Component component)
		{
			return GetOrAdd(component, ScaleParticleSystemDurations, (GameObject target) => target.GetComponent<ScaleParticleSystemDuration>());
		}

		public static ObjectScaleCurve? GetObjectScaleCurve(GameObject gameObject)
		{
			return GetOrAdd(gameObject, ObjectScaleCurves, (GameObject target) => target.GetComponent<ObjectScaleCurve>());
		}

		public static CharacterDirection? GetCharacterDirectionFromComponent(Component component)
		{
			return GetOrAdd(component, CharacterDirections, (GameObject target) => target.GetComponent<CharacterDirection>());
		}

		public static CharacterModel? GetCharacterModelFromComponent(Component component)
		{
			return GetOrAdd(component, CharacterModels, (GameObject target) => target.GetComponent<CharacterModel>());
		}

		public static HurtBoxGroup? GetHurtBoxGroupFromComponent(Component component)
		{
			return GetOrAdd(component, HurtBoxGroups, (GameObject target) => target.GetComponent<HurtBoxGroup>());
		}

		public static HurtBox? GetHurtBoxFromComponent(Component component)
		{
			return GetOrAdd(component, HurtBoxes, (GameObject target) => target.GetComponent<HurtBox>());
		}

		public static Animator? GetAnimatorInChildren(GameObject gameObject)
		{
			return GetOrAdd(gameObject, AnimatorsInChildren, (GameObject target) => target.GetComponentInChildren<Animator>());
		}

		public static ParticleSystem? GetParticleSystem(Component component)
		{
			return GetOrAdd(component, ParticleSystems, (GameObject target) => target.GetComponent<ParticleSystem>());
		}

		public static ParticleSystem[]? GetParticleSystemsInChildren(Component component)
		{
			return GetOrAddArray<ParticleSystem>(component, ParticleSystemsInChildren, (Func<GameObject, ParticleSystem[]?>)((GameObject target) => target.GetComponentsInChildren<ParticleSystem>()));
		}

		public static ParticleSystem[]? GetParticleSystemsInChildren(GameObject gameObject)
		{
			return GetOrAddArray<ParticleSystem>(gameObject, ParticleSystemsInChildren, (Func<GameObject, ParticleSystem[]?>)((GameObject target) => target.GetComponentsInChildren<ParticleSystem>()));
		}

		public static Light[]? GetLightsInChildren(Component component)
		{
			return GetOrAddArray<Light>(component, LightsInChildren, (Func<GameObject, Light[]?>)((GameObject target) => target.GetComponentsInChildren<Light>()));
		}

		public static Renderer[]? GetRenderersInChildren(Component component)
		{
			return GetOrAddArray<Renderer>(component, RenderersInChildren, (Func<GameObject, Renderer[]?>)((GameObject target) => target.GetComponentsInChildren<Renderer>()));
		}

		public static Renderer[]? GetRenderersInChildren(GameObject gameObject)
		{
			return GetOrAddArray<Renderer>(gameObject, RenderersInChildren, (Func<GameObject, Renderer[]?>)((GameObject target) => target.GetComponentsInChildren<Renderer>()));
		}

		public static Transform? FindTransform(Transform transform, string childName)
		{
			string childName2 = childName;
			return GetOrFindTransform(transform, childName2, (Transform target) => target.Find(childName2), TransformFindCache);
		}

		public static Transform? FindChild(ChildLocator childLocator, string childName)
		{
			string childName2 = childName;
			return GetOrFindTransform(childLocator, childName2, (ChildLocator target) => target.FindChild(childName2), ChildLocatorFindCache);
		}

		private static T? GetOrAdd<T>(Component component, FixedConditionalWeakTable<GameObject, CacheBox<T>> cache, Func<GameObject, T?> factory) where T : class
		{
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return GetOrAdd(component.gameObject, cache, factory);
		}

		private static T? GetOrAdd<T>(GameObject gameObject, FixedConditionalWeakTable<GameObject, CacheBox<T>> cache, Func<GameObject, T?> factory) where T : class
		{
			if (!Object.op_Implicit((Object)(object)gameObject))
			{
				return null;
			}
			CacheBox<T> orCreateValue = cache.GetOrCreateValue(gameObject);
			if (IsMissing(orCreateValue.Value))
			{
				orCreateValue.Value = factory(gameObject);
			}
			return orCreateValue.Value;
		}

		private static T[]? GetOrAddArray<T>(Component component, FixedConditionalWeakTable<GameObject, CacheBox<T[]>> cache, Func<GameObject, T[]?> factory) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return GetOrAddArray(component.gameObject, cache, factory);
		}

		private static T[]? GetOrAddArray<T>(GameObject gameObject, FixedConditionalWeakTable<GameObject, CacheBox<T[]>> cache, Func<GameObject, T[]?> factory) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)gameObject))
			{
				return null;
			}
			CacheBox<T[]> orCreateValue = cache.GetOrCreateValue(gameObject);
			if (IsMissingArray(orCreateValue.Value))
			{
				orCreateValue.Value = factory(gameObject);
			}
			return orCreateValue.Value;
		}

		private static Transform? GetOrFindTransform<TSource>(TSource source, string childName, Func<TSource, Transform?> finder, FixedConditionalWeakTable<TSource, NamedTransformCache> cache) where TSource : class
		{
			if (source == null)
			{
				return null;
			}
			Object val = (Object)(object)((source is Object) ? source : null);
			if (val != null && !Object.op_Implicit(val))
			{
				return null;
			}
			NamedTransformCache orCreateValue = cache.GetOrCreateValue(source);
			if (orCreateValue.Values.TryGetValue(childName, out Transform value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			Transform val2 = finder(source);
			if (Object.op_Implicit((Object)(object)val2))
			{
				orCreateValue.Values[childName] = val2;
			}
			else
			{
				orCreateValue.Values.Remove(childName);
			}
			return val2;
		}

		private static bool IsMissing<T>(T? value) where T : class
		{
			if (value == null)
			{
				return true;
			}
			Object val = (Object)(object)((value is Object) ? value : null);
			if (val != null)
			{
				return !Object.op_Implicit(val);
			}
			return false;
		}

		private static bool IsMissingArray<T>(T[]? value) where T : Object
		{
			if (value == null)
			{
				return true;
			}
			for (int i = 0; i < value.Length; i++)
			{
				if (!Object.op_Implicit((Object)(object)value[i]))
				{
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class OptimizeDynamicBoneLateUpdatePatch
	{
		private sealed class DynamicBoneState
		{
			public int LastVisibleFrame = int.MinValue;
		}

		private static readonly Type? DynamicBoneType = AccessTools.TypeByName("DynamicBone");

		private static readonly MethodInfo? DynamicBoneLateUpdateMethod = ((DynamicBoneType != null) ? AccessTools.DeclaredMethod(DynamicBoneType, "LateUpdate", (Type[])null, (Type[])null) : null);

		private static readonly FieldInfo? DynamicBoneRootField = ((DynamicBoneType != null) ? AccessTools.Field(DynamicBoneType, "m_Root") : null);

		private static readonly FieldInfo? DynamicBoneNeverOptimizeField = ((DynamicBoneType != null) ? AccessTools.Field(DynamicBoneType, "neverOptimize") : null);

		private static readonly FixedConditionalWeakTable<Component, DynamicBoneState> StateByBone = new FixedConditionalWeakTable<Component, DynamicBoneState>();

		private static int cachedCameraFrame = int.MinValue;

		private static Camera? cachedMainCamera;

		private static bool Prepare()
		{
			if (DynamicBoneLateUpdateMethod == null)
			{
				ManualLogSource? globalLogger = RORO.GlobalLogger;
				if (globalLogger != null)
				{
					globalLogger.LogWarning((object)"DynamicBone.LateUpdate not found, skipping DynamicBone optimization.");
				}
				return false;
			}
			ManualLogSource? globalLogger2 = RORO.GlobalLogger;
			if (globalLogger2 != null)
			{
				globalLogger2.LogInfo((object)"DynamicBone.LateUpdate optimization enabled.");
			}
			return true;
		}

		private static MethodBase TargetMethod()
		{
			return DynamicBoneLateUpdateMethod;
		}

		[HarmonyPrefix]
		private static bool Prefix(Component __instance)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)__instance))
			{
				return true;
			}
			Behaviour val = (Behaviour)(object)((__instance is Behaviour) ? __instance : null);
			if (val != null && !val.isActiveAndEnabled)
			{
				return true;
			}
			bool flag = default(bool);
			int num;
			if (DynamicBoneNeverOptimizeField != null)
			{
				object value = DynamicBoneNeverOptimizeField.GetValue(__instance);
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0)
			{
				return true;
			}
			Renderer[] array = ResolveRenderers(__instance);
			if (!ROROConfig.EnableDynamicBoneInvisibleThrottling || array == null || array.Length == 0)
			{
				return true;
			}
			int num2 = Mathf.Max(2, ROROConfig.DynamicBoneInvisibleUpdateInterval);
			int num3 = Mathf.Max(1, ROROConfig.DynamicBoneVisibleMidUpdateInterval);
			int num4 = Mathf.Max(num3, ROROConfig.DynamicBoneVisibleFarUpdateInterval);
			int num5 = 1;
			int frameCount = Time.frameCount;
			DynamicBoneState orCreateValue = StateByBone.GetOrCreateValue(__instance);
			if (AnyRendererVisible(array))
			{
				orCreateValue.LastVisibleFrame = frameCount;
				Camera mainCamera = GetMainCamera();
				if ((Object)(object)mainCamera != (Object)null)
				{
					Vector3 val2 = GetReferencePosition(__instance) - ((Component)mainCamera).transform.position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					float num6 = Mathf.Max(0f, ROROConfig.DynamicBoneVisibleMidDistance);
					float num7 = Mathf.Max(num6, ROROConfig.DynamicBoneVisibleFarDistance);
					float num8 = num6 * num6;
					float num9 = num7 * num7;
					if (sqrMagnitude >= num9)
					{
						num5 = num4;
					}
					else if (sqrMagnitude >= num8)
					{
						num5 = num3;
					}
				}
			}
			else
			{
				if (frameCount - orCreateValue.LastVisibleFrame <= ROROConfig.DynamicBoneRecentlyVisibleGraceFrames)
				{
					return true;
				}
				num5 = num2;
			}
			if (num5 <= 1)
			{
				return true;
			}
			return (frameCount + (((Object)__instance).GetInstanceID() & 0x7FFFFFFF)) % num5 == 0;
		}

		private static Renderer[]? ResolveRenderers(Component dynamicBone)
		{
			object? obj = DynamicBoneRootField?.GetValue(dynamicBone);
			Transform val = (Transform)((obj is Transform) ? obj : null);
			Renderer[] array = (((Object)(object)val != (Object)null) ? OptimizedComponentCache.GetRenderersInChildren(((Component)val).gameObject) : null);
			if (array == null || array.Length == 0)
			{
				array = OptimizedComponentCache.GetRenderersInChildren(dynamicBone.gameObject);
			}
			return array;
		}

		private static Vector3 GetReferencePosition(Component dynamicBone)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			object? obj = DynamicBoneRootField?.GetValue(dynamicBone);
			Transform val = (Transform)((obj is Transform) ? obj : null);
			if (!((Object)(object)val != (Object)null))
			{
				return dynamicBone.transform.position;
			}
			return val.position;
		}

		private static Camera? GetMainCamera()
		{
			int frameCount = Time.frameCount;
			if (cachedCameraFrame != frameCount)
			{
				cachedMainCamera = Camera.main;
				cachedCameraFrame = frameCount;
			}
			return cachedMainCamera;
		}

		private static bool AnyRendererVisible(Renderer[] renderers)
		{
			foreach (Renderer val in renderers)
			{
				if (Object.op_Implicit((Object)(object)val) && val.enabled && val.isVisible)
				{
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class OptimizeGenericIkLateUpdatePatch
	{
		private sealed class GenericIkState
		{
			public int LastVisibleFrame = int.MinValue;
		}

		private static readonly Type? InverseKinematicsType = AccessTools.TypeByName("Generics.Dynamics.InverseKinematics");

		private static readonly MethodInfo? InverseKinematicsLateUpdateMethod = ((InverseKinematicsType != null) ? AccessTools.DeclaredMethod(InverseKinematicsType, "LateUpdate", (Type[])null, (Type[])null) : null);

		private static readonly FieldInfo? AnimatorField = ((InverseKinematicsType != null) ? AccessTools.Field(InverseKinematicsType, "animator") : null);

		private static readonly FixedConditionalWeakTable<Component, GenericIkState> StateByIk = new FixedConditionalWeakTable<Component, GenericIkState>();

		private static bool Prepare()
		{
			if (InverseKinematicsLateUpdateMethod == null)
			{
				ManualLogSource? globalLogger = RORO.GlobalLogger;
				if (globalLogger != null)
				{
					globalLogger.LogWarning((object)"Generics.Dynamics.InverseKinematics.LateUpdate not found, skipping GenericIK optimization.");
				}
				return false;
			}
			ManualLogSource? globalLogger2 = RORO.GlobalLogger;
			if (globalLogger2 != null)
			{
				globalLogger2.LogInfo((object)"Generics.Dynamics.InverseKinematics.LateUpdate optimization enabled.");
			}
			return true;
		}

		private static MethodBase TargetMethod()
		{
			return InverseKinematicsLateUpdateMethod;
		}

		[HarmonyPrefix]
		private static bool Prefix(Component __instance)
		{
			if (!ROROConfig.EnableGenericIkInvisibleThrottling || !Object.op_Implicit((Object)(object)__instance))
			{
				return true;
			}
			Behaviour val = (Behaviour)(object)((__instance is Behaviour) ? __instance : null);
			if (val != null && !val.isActiveAndEnabled)
			{
				return true;
			}
			Renderer[] array = ResolveRenderers(__instance);
			if (array == null || array.Length == 0)
			{
				return true;
			}
			int frameCount = Time.frameCount;
			GenericIkState orCreateValue = StateByIk.GetOrCreateValue(__instance);
			if (AnyRendererVisible(array))
			{
				orCreateValue.LastVisibleFrame = frameCount;
				return true;
			}
			if (frameCount - orCreateValue.LastVisibleFrame <= ROROConfig.GenericIkRecentlyVisibleGraceFrames)
			{
				return true;
			}
			int num = Mathf.Max(2, ROROConfig.GenericIkInvisibleUpdateInterval);
			return (frameCount + (((Object)__instance).GetInstanceID() & 0x7FFFFFFF)) % num == 0;
		}

		private static Renderer[]? ResolveRenderers(Component inverseKinematics)
		{
			object? obj = AnimatorField?.GetValue(inverseKinematics);
			Animator val = (Animator)((obj is Animator) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Renderer[] renderersInChildren = OptimizedComponentCache.GetRenderersInChildren(((Component)val).gameObject);
				if (renderersInChildren != null && renderersInChildren.Length != 0)
				{
					return renderersInChildren;
				}
			}
			return OptimizedComponentCache.GetRenderersInChildren(inverseKinematics.gameObject);
		}

		private static bool AnyRendererVisible(Renderer[] renderers)
		{
			foreach (Renderer val in renderers)
			{
				if (Object.op_Implicit((Object)(object)val) && val.enabled && val.isVisible)
				{
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ContextManager), "Update")]
	public static class OptimizeContextManagerPatch
	{
		private static readonly MethodInfo GameObjectGetInteractionDriverMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(InteractionDriver));

		private static readonly MethodInfo GameObjectGetInteractableMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(IInteractable));

		private static readonly MethodInfo GameObjectGetInspectableMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(IInspectable));

		private static readonly MethodInfo ComponentGetPlayerCharacterMasterControllerMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(PlayerCharacterMasterController));

		private static readonly MethodInfo CachedInteractionDriverMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInteractionDriver", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedInteractableMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInteractable", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedInspectableMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInspectable", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedPlayerCharacterMasterControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetPlayerCharacterMasterController", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInteractionDriverMethod, CachedInteractionDriverMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInteractableMethod, CachedInteractableMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInspectableMethod, CachedInspectableMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetPlayerCharacterMasterControllerMethod, CachedPlayerCharacterMasterControllerMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"ContextManager.Update optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(HUD), "Update")]
	public static class OptimizeHUDPatch
	{
		private static readonly MethodInfo GameObjectGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterBody));

		private static readonly MethodInfo GameObjectGetEquipmentSlotMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(EquipmentSlot));

		private static readonly MethodInfo GameObjectGetHealthComponentMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(HealthComponent));

		private static readonly MethodInfo GameObjectGetSkillLocatorMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(SkillLocator));

		private static readonly MethodInfo ComponentGetPlayerCharacterMasterControllerMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(PlayerCharacterMasterController));

		private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBody", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedEquipmentSlotMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetEquipmentSlot", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedHealthComponentMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHealthComponent", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedPlayerCharacterMasterControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetPlayerCharacterMasterController", (Type[])null, (Type[])null);

		private static readonly MethodInfo CachedSkillLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetSkillLocator", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetCharacterBodyMethod, CachedCharacterBodyMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetEquipmentSlotMethod, CachedEquipmentSlotMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetHealthComponentMethod, CachedHealthComponentMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetSkillLocatorMethod, CachedSkillLocatorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetPlayerCharacterMasterControllerMethod, CachedPlayerCharacterMasterControllerMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"HUD.Update optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(NetworkProximityChecker), "Update")]
	public static class OptimizeNetworkProximityCheckerPatch
	{
		private static readonly MethodInfo ComponentGetNetworkIdentityMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(NetworkIdentity));

		private static readonly MethodInfo CachedNetworkIdentityMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetNetworkIdentity", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetNetworkIdentityMethod, CachedNetworkIdentityMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"NetworkProximityChecker.Update optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	internal static class OptimizeGetComponentPatchTools
	{
		private static readonly MethodInfo ComponentGetComponentDefinition = typeof(Component).GetMethod("GetComponent", Type.EmptyTypes).GetGenericMethodDefinition();

		private static readonly MethodInfo GameObjectGetComponentDefinition = typeof(GameObject).GetMethod("GetComponent", Type.EmptyTypes).GetGenericMethodDefinition();

		private static readonly MethodInfo GameObjectGetComponentInChildrenDefinition = typeof(GameObject).GetMethod("GetComponentInChildren", Type.EmptyTypes).GetGenericMethodDefinition();

		private static readonly MethodInfo ComponentGetComponentsInChildrenDefinition = typeof(Component).GetMethod("GetComponentsInChildren", Type.EmptyTypes).GetGenericMethodDefinition();

		private static readonly MethodInfo GameObjectGetComponentsInChildrenDefinition = typeof(GameObject).GetMethod("GetComponentsInChildren", Type.EmptyTypes).GetGenericMethodDefinition();

		public static MethodInfo MakeComponentGetComponentMethod(Type componentType)
		{
			return ComponentGetComponentDefinition.MakeGenericMethod(componentType);
		}

		public static MethodInfo MakeGameObjectGetComponentMethod(Type componentType)
		{
			return GameObjectGetComponentDefinition.MakeGenericMethod(componentType);
		}

		public static MethodInfo MakeGameObjectGetComponentInChildrenMethod(Type componentType)
		{
			return GameObjectGetComponentInChildrenDefinition.MakeGenericMethod(componentType);
		}

		public static MethodInfo MakeComponentGetComponentsInChildrenMethod(Type componentType)
		{
			return ComponentGetComponentsInChildrenDefinition.MakeGenericMethod(componentType);
		}

		public static MethodInfo MakeGameObjectGetComponentsInChildrenMethod(Type componentType)
		{
			return GameObjectGetComponentsInChildrenDefinition.MakeGenericMethod(componentType);
		}

		public static bool ReplaceCall(CodeInstruction instruction, MethodInfo source, MethodInfo target)
		{
			if (!CodeInstructionExtensions.Calls(instruction, source))
			{
				return false;
			}
			instruction.opcode = OpCodes.Call;
			instruction.operand = target;
			return true;
		}
	}
	internal static class MenuHotspotThrottleState
	{
		private sealed class ThrottleState
		{
			public bool IsDirty = true;

			public float NextAllowedTime;
		}

		private static readonly FixedConditionalWeakTable<LobbyUserList, ThrottleState> LobbyStates = new FixedConditionalWeakTable<LobbyUserList, ThrottleState>();

		private static readonly FixedConditionalWeakTable<SocialUserIconBehavior, ThrottleState> AvatarStates = new FixedConditionalWeakTable<SocialUserIconBehavior, ThrottleState>();

		private static readonly FixedConditionalWeakTable<SurvivorIconController, ThrottleState> SurvivorStates = new FixedConditionalWeakTable<SurvivorIconController, ThrottleState>();

		public static void MarkLobbyDirty(LobbyUserList? lobbyUserList)
		{
			MarkDirty(lobbyUserList, LobbyStates);
		}

		public static void MarkAvatarDirty(SocialUserIconBehavior? behavior)
		{
			MarkDirty(behavior, AvatarStates);
		}

		public static void MarkSurvivorDirty(SurvivorIconController? controller)
		{
			MarkDirty(controller, SurvivorStates);
		}

		public static bool ShouldRunLobbyRefresh(LobbyUserList? lobbyUserList, float intervalSeconds)
		{
			return ShouldRun(lobbyUserList, intervalSeconds, LobbyStates);
		}

		public static bool ShouldRunAvatarRefresh(SocialUserIconBehavior? behavior, bool shouldForceRefresh, float intervalSeconds)
		{
			if (!shouldForceRefresh)
			{
				return ShouldRun(behavior, intervalSeconds, AvatarStates);
			}
			return true;
		}

		public static bool ShouldRunSurvivorAvailabilityRefresh(SurvivorIconController? controller, float intervalSeconds)
		{
			return ShouldRun(controller, intervalSeconds, SurvivorStates);
		}

		private static void MarkDirty<T>(T? instance, FixedConditionalWeakTable<T, ThrottleState> table) where T : class
		{
			if (instance != null)
			{
				ThrottleState orCreateValue = table.GetOrCreateValue(instance);
				orCreateValue.IsDirty = true;
				orCreateValue.NextAllowedTime = 0f;
			}
		}

		private static bool ShouldRun<T>(T? instance, float intervalSeconds, FixedConditionalWeakTable<T, ThrottleState> table) where T : class
		{
			if (instance == null)
			{
				return false;
			}
			ThrottleState orCreateValue = table.GetOrCreateValue(instance);
			float unscaledTime = Time.unscaledTime;
			if (!orCreateValue.IsDirty && unscaledTime < orCreateValue.NextAllowedTime)
			{
				return false;
			}
			orCreateValue.IsDirty = false;
			orCreateValue.NextAllowedTime = unscaledTime + intervalSeconds;
			return true;
		}
	}
	internal static class SteamAvatarHotspotCache
	{
		private readonly struct AvatarCacheKey : IEquatable<AvatarCacheKey>
		{
			private readonly ulong steamId;

			private readonly int size;

			public AvatarCacheKey(PlatformID platformId, AvatarSize avatarSize)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Expected I4, but got Unknown
				steamId = platformId.ID;
				size = (int)avatarSize;
			}

			public bool Equals(AvatarCacheKey other)
			{
				if (steamId == other.steamId)
				{
					return size == other.size;
				}
				return false;
			}

			public override bool Equals(object? obj)
			{
				if (obj is AvatarCacheKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return ((int)steamId * 397) ^ size;
			}
		}

		private sealed class PendingAvatarRequest
		{
			public readonly List<Action<Texture2D>> WaitingCallbacks = new List<Action<Texture2D>>();

			public float StartedAt;
		}

		private const float PendingRequestTimeoutSeconds = 5f;

		private static readonly object Sync = new object();

		private static readonly Dictionary<AvatarCacheKey, Texture2D> CachedTextures = new Dictionary<AvatarCacheKey, Texture2D>();

		private static readonly Dictionary<AvatarCacheKey, PendingAvatarRequest> PendingRequests = new Dictionary<AvatarCacheKey, PendingAvatarRequest>();

		public static bool ShouldRunOriginalRequest(PlatformID id, AvatarSize size, Action<Texture2D>? onReceived)
		{
			//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)
			AvatarCacheKey key = new AvatarCacheKey(id, size);
			Texture2D val = null;
			bool result = false;
			lock (Sync)
			{
				if (CachedTextures.TryGetValue(key, out Texture2D value))
				{
					if (Object.op_Implicit((Object)(object)value))
					{
						val = value;
					}
					else
					{
						CachedTextures.Remove(key);
					}
				}
				if (!Object.op_Implicit((Object)(object)val))
				{
					float unscaledTime = Time.unscaledTime;
					if (PendingRequests.TryGetValue(key, out PendingAvatarRequest value2))
					{
						if (unscaledTime - value2.StartedAt < 5f)
						{
							if (onReceived != null)
							{
								value2.WaitingCallbacks.Add(onReceived);
							}
							return false;
						}
						PendingRequests.Remove(key);
					}
					PendingRequests[key] = new PendingAvatarRequest
					{
						StartedAt = unscaledTime
					};
					result = true;
				}
			}
			if (Object.op_Implicit((Object)(object)val) && onReceived != null)
			{
				onReceived(val);
				return false;
			}
			return result;
		}

		public static void CompleteRequest(PlatformID id, AvatarSize size, Texture2D? texture)
		{
			//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)
			AvatarCacheKey key = new AvatarCacheKey(id, size);
			List<Action<Texture2D>> list = null;
			lock (Sync)
			{
				if (PendingRequests.TryGetValue(key, out PendingAvatarRequest value))
				{
					list = value.WaitingCallbacks;
					PendingRequests.Remove(key);
				}
				if (Object.op_Implicit((Object)(object)texture))
				{
					CachedTextures[key] = texture;
				}
				else
				{
					CachedTextures.Remove(key);
				}
			}
			if (!((Object)(object)texture == (Object)null) && list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					list[i](texture);
				}
			}
		}
	}
	[HarmonyPatch(typeof(LobbyUserList), "Update")]
	public static class OptimizeLobbyUserListUpdatePatch
	{
		private const float RefreshIntervalSeconds = 0.2f;

		[HarmonyPrefix]
		private static bool Prefix(LobbyUserList __instance)
		{
			return MenuHotspotThrottleState.ShouldRunLobbyRefresh(__instance, 0.2f);
		}
	}
	[HarmonyPatch(typeof(LobbyUserList), "OnEnable")]
	public static class OptimizeLobbyUserListOnEnablePatch
	{
		[HarmonyPostfix]
		private static void Postfix(LobbyUserList __instance)
		{
			MenuHotspotThrottleState.MarkLobbyDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(LobbyUserList), "OnLobbyChanged")]
	public static class OptimizeLobbyUserListOnLobbyChangedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(LobbyUserList __instance)
		{
			MenuHotspotThrottleState.MarkLobbyDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(LobbyUserList), "OnLobbyMemberDataUpdated")]
	public static class OptimizeLobbyUserListOnLobbyMemberDataUpdatedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(LobbyUserList __instance)
		{
			MenuHotspotThrottleState.MarkLobbyDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(LobbyUserList), "OnLobbyStateChanged")]
	public static class OptimizeLobbyUserListOnLobbyStateChangedPatch
	{
		[HarmonyPostfix]
		private static void Postfix(LobbyUserList __instance)
		{
			MenuHotspotThrottleState.MarkLobbyDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(LobbyUserListElement), "Refresh")]
	public static class OptimizeLobbyUserListElementRefreshPatch
	{
		private static readonly MethodInfo ChildLocatorFindChildMethod = AccessTools.Method(typeof(ChildLocator), "FindChild", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo CachedFindChildMethod = AccessTools.Method(typeof(OptimizedComponentCache), "FindChild", new Type[2]
		{
			typeof(ChildLocator),
			typeof(string)
		}, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ChildLocatorFindChildMethod, CachedFindChildMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"LobbyUserListElement.Refresh optimized: cached ChildLocator.FindChild calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(SocialUserIconBehavior), "Refresh")]
	public static class OptimizeSocialUserIconBehaviorRefreshPatch
	{
		private const float RefreshIntervalSeconds = 0.25f;

		[HarmonyPrefix]
		private static bool Prefix(SocialUserIconBehavior __instance, bool shouldForceRefresh)
		{
			return MenuHotspotThrottleState.ShouldRunAvatarRefresh(__instance, shouldForceRefresh, 0.25f);
		}
	}
	[HarmonyPatch(typeof(SteamUserManager), "GetSteamAvatar")]
	public static class OptimizeSteamUserManagerGetSteamAvatarPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(PlatformID id, AvatarSize size, Action<Texture2D> onRecieved)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return SteamAvatarHotspotCache.ShouldRunOriginalRequest(id, size, onRecieved);
		}
	}
	[HarmonyPatch(typeof(SocialUserIconBehavior), "HandleNewTexture")]
	public static class OptimizeSocialUserIconBehaviorHandleNewTexturePatch
	{
		[HarmonyPostfix]
		private static void Postfix(SocialUserIconBehavior __instance, Texture2D tex)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			SteamAvatarHotspotCache.CompleteRequest(__instance.userID, __instance.avatarSize, tex);
		}
	}
	[HarmonyPatch(typeof(SocialUserIconBehavior), "OnEnableBehavior")]
	public static class OptimizeSocialUserIconBehaviorOnEnablePatch
	{
		[HarmonyPostfix]
		private static void Postfix(SocialUserIconBehavior __instance)
		{
			MenuHotspotThrottleState.MarkAvatarDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(SocialUserIconBehavior), "RefreshWithUser")]
	public static class OptimizeSocialUserIconBehaviorRefreshWithUserPatch
	{
		[HarmonyPostfix]
		private static void Postfix(SocialUserIconBehavior __instance)
		{
			MenuHotspotThrottleState.MarkAvatarDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(SurvivorIconController), "UpdateAvailability")]
	public static class OptimizeSurvivorIconControllerAvailabilityPatch
	{
		private const float RefreshIntervalSeconds = 0.25f;

		[HarmonyPrefix]
		private static bool Prefix(SurvivorIconController __instance)
		{
			return MenuHotspotThrottleState.ShouldRunSurvivorAvailabilityRefresh(__instance, 0.25f);
		}
	}
	[HarmonyPatch(typeof(SurvivorIconController), "Awake")]
	public static class OptimizeSurvivorIconControllerAwakePatch
	{
		[HarmonyPostfix]
		private static void Postfix(SurvivorIconController __instance)
		{
			MenuHotspotThrottleState.MarkSurvivorDirty(__instance);
		}
	}
	[HarmonyPatch(typeof(KineticAura), "FixedUpdate")]
	public static class OptimizeKineticAuraPatch
	{
		private static readonly MethodInfo ComponentGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterMotor));

		private static readonly MethodInfo ComponentGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(Rigidbody));

		private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterMotor", new Type[1] { typeof(Component) }, (Type[])null);

		private static readonly MethodInfo CachedRigidbodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbodyFromComponent", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			int replacements = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterMotorMethod, CachedCharacterMotorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetRigidbodyMethod, CachedRigidbodyMethod))
				{
					replacements++;
				}
				yield return instruction;
			}
			ManualLogSource? globalLogger = RORO.GlobalLogger;
			if (globalLogger != null)
			{
				globalLogger.LogInfo((object)$"KineticAura.FixedUpdate optimized: cached GetComponent calls={replacements}");
			}
		}
	}
	[HarmonyPatch(typeof(ToolbotDash), "FixedUpdate")]
	public static class OptimizeToolbotDashPatch
	{
		private static readonly MethodInfo ComponentGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterMotor));

		private static readonly MethodInfo ComponentGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(Rigidbody));

		private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedC