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? enableDamageNumberLoadShedding; private static ConfigEntry? softParticleCap; private static ConfigEntry? hardParticleCap; private static ConfigEntry? absoluteParticleCap; private static ConfigEntry? softSpawnsPerFrame; private static ConfigEntry? hardSpawnsPerFrame; private static ConfigEntry? absoluteSpawnsPerFrame; private static ConfigEntry? softPeakDamageFraction; private static ConfigEntry? hardPeakDamageFraction; private static ConfigEntry? absolutePeakDamageFraction; private static ConfigEntry? softMinimumDamage; private static ConfigEntry? hardMinimumDamage; private static ConfigEntry? absoluteMinimumDamage; private static ConfigEntry? peakDamageHalfLifeSeconds; private static ConfigEntry? preserveCriticalHits; private static ConfigEntry? preserveImportantColors; private static ConfigEntry? enableDynamicBoneInvisibleThrottling; private static ConfigEntry? dynamicBoneInvisibleUpdateInterval; private static ConfigEntry? dynamicBoneRecentlyVisibleGraceFrames; private static ConfigEntry? dynamicBoneVisibleMidDistance; private static ConfigEntry? dynamicBoneVisibleFarDistance; private static ConfigEntry? dynamicBoneVisibleMidUpdateInterval; private static ConfigEntry? dynamicBoneVisibleFarUpdateInterval; private static ConfigEntry? enableGenericIkInvisibleThrottling; private static ConfigEntry? genericIkInvisibleUpdateInterval; private static ConfigEntry? 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("Damage Numbers", "Enable Load Shedding", true, "Reduces the number of spawned damage number particles during heavy combat."); softParticleCap = config.Bind("Damage Numbers", "Soft Particle Cap", 128, "Starts lightly sampling regular damage numbers when active particles reach this amount."); hardParticleCap = config.Bind("Damage Numbers", "Hard Particle Cap", 192, "Uses stronger sampling when active particles reach this amount."); absoluteParticleCap = config.Bind("Damage Numbers", "Absolute Particle Cap", 256, "Uses the strongest sampling when active particles reach this amount."); softSpawnsPerFrame = config.Bind("Damage Numbers", "Soft Spawns Per Frame", 24, "Starts lightly sampling regular damage numbers when this many spawns happen in one frame."); hardSpawnsPerFrame = config.Bind("Damage Numbers", "Hard Spawns Per Frame", 40, "Uses stronger sampling when this many spawns happen in one frame."); absoluteSpawnsPerFrame = config.Bind("Damage Numbers", "Absolute Spawns Per Frame", 56, "Uses the strongest sampling when this many spawns happen in one frame."); softPeakDamageFraction = config.Bind("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("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("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("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("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("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("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("Damage Numbers", "Preserve Critical Hits", true, "Always allow critical hit damage numbers through the load shedding filter."); preserveImportantColors = config.Bind("Damage Numbers", "Preserve Important Colors", true, "Always allow important color categories like heal and weak point through the load shedding filter."); enableDynamicBoneInvisibleThrottling = config.Bind("Dynamic Bones", "Enable Invisible Update Throttling", true, "Throttles DynamicBone LateUpdate calls when the affected renderers are offscreen."); dynamicBoneInvisibleUpdateInterval = config.Bind("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("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("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("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("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("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("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("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("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 : IDictionary, ICollection>, IEnumerable>, IEnumerable, IReadOnlyDictionary, IReadOnlyCollection>, FixedConditionalWeakTableManager.IShrinkable where TKey : class where TValue : class { private readonly struct WeakReferenceWrapper where T : class { public readonly int TargetHashCode; public readonly WeakReference? 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(target); } } public WeakReferenceWrapper(int targetHashCode) { TargetHashCode = targetHashCode; Target = null; WeakReference = null; } } [StructLayout(LayoutKind.Sequential, Size = 1)] private readonly struct WeakReferenceWrapperComparer : IEqualityComparer> where T : class { public bool Equals(WeakReferenceWrapper first, WeakReferenceWrapper 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 obj) { return obj.TargetHashCode; } } private ConstructorInfo? cachedConstructor; private readonly ConcurrentDictionary, TValue> valueByKey = new ConcurrentDictionary, TValue>(default(WeakReferenceWrapperComparer)); public TValue this[TKey key] { get { return valueByKey[new WeakReferenceWrapper(key, strongReference: true)]; } set { valueByKey[new WeakReferenceWrapper(key, strongReference: false)] = value; } } public ICollection Keys { get { List list = new List(valueByKey.Count); foreach (WeakReferenceWrapper key in valueByKey.Keys) { if (key.WeakReference != null && key.WeakReference.TryGetTarget(out var target)) { list.Add(target); } } return list.AsReadOnly(); } } public ICollection Values { get { List list = new List(valueByKey.Count); foreach (KeyValuePair, 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 key in valueByKey.Keys) { if (key.WeakReference != null && key.WeakReference.TryGetTarget(out var _)) { num++; } } return num; } } public int SpeculativeCount => valueByKey.Count; bool ICollection>.IsReadOnly => false; IEnumerable IReadOnlyDictionary.Keys => Keys; IEnumerable IReadOnlyDictionary.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(key, strongReference: false), value)) { throw new ArgumentException("The key already exists", "key"); } } public bool Remove(TKey key) { TValue value; return valueByKey.TryRemove(new WeakReferenceWrapper(key, strongReference: true), out value); } public bool TryGetValue(TKey key, out TValue value) { return valueByKey.TryGetValue(new WeakReferenceWrapper(key, strongReference: true), out value); } public TValue GetValue(TKey key, Func 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()); Add(key, value); return value; } void FixedConditionalWeakTableManager.IShrinkable.Shrink() { foreach (KeyValuePair, TValue> item in valueByKey) { if (item.Key.WeakReference != null && !item.Key.WeakReference.TryGetTarget(out var _)) { valueByKey.TryRemove(new WeakReferenceWrapper(item.Key.TargetHashCode), out var _); } } } public bool ContainsKey(TKey key) { return valueByKey.ContainsKey(new WeakReferenceWrapper(key, strongReference: true)); } public void Clear() { valueByKey.Clear(); } void ICollection>.Add(KeyValuePair item) { Add(item.Key, item.Value); } bool ICollection>.Contains(KeyValuePair item) { if (TryGetValue(item.Key, out var value)) { return EqualityComparer.Default.Equals(value, item.Value); } return false; } void ICollection>.CopyTo(KeyValuePair[] 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, TValue> item in valueByKey) { if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var target)) { array[arrayIndex++] = new KeyValuePair(target, item.Value); } } } bool ICollection>.Remove(KeyValuePair item) { if (TryGetValue(item.Key, out var value) && EqualityComparer.Default.Equals(value, item.Value)) { return Remove(item.Key); } return false; } public IEnumerator> GetEnumerator() { foreach (KeyValuePair, TValue> item in valueByKey) { if (item.Key.WeakReference != null && item.Key.WeakReference.TryGetTarget(out var target)) { yield return new KeyValuePair(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> Instances = new List>(); 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(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 Transpiler(IEnumerable 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 list = new List(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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 ParticleSystemField = AccessTools.FieldRefAccess("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 where T : class { public T? Value; } private sealed class NamedTransformCache { public readonly Dictionary Values = new Dictionary(); } private static readonly FixedConditionalWeakTable> CharacterBodies = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> CharacterMasters = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> EquipmentSlots = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> HealthComponents = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> HuntressTrackers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> DamageTrails = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> Rigidbodies = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> Rigidbodies2D = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> Inspectables = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> Interactables = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> InteractionDrivers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> InputBankTests = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> CameraTargetParamsCache = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ChefControllers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> CharacterMotors = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> RigidbodyMotors = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> KinematicCharacterMotors = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> NetworkIdentities = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> NetworkUsers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> FalseSonBossControllers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> OilGhostControllers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> PlayerCharacterMasterControllers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> SkillLocators = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> TeamFilters = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ProjectileControllers = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ProjectileDamages = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ChildLocators = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ScaleParticleSystemDurations = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ObjectScaleCurves = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> CharacterDirections = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> CharacterModels = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> HurtBoxGroups = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> HurtBoxes = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> AnimatorsInChildren = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ParticleSystems = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> ParticleSystemsInChildren = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> LightsInChildren = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable> RenderersInChildren = new FixedConditionalWeakTable>(); private static readonly FixedConditionalWeakTable TransformFindCache = new FixedConditionalWeakTable(); private static readonly FixedConditionalWeakTable ChildLocatorFindCache = new FixedConditionalWeakTable(); public static CharacterBody? GetCharacterBody(GameObject gameObject) { return GetOrAdd(gameObject, CharacterBodies, (GameObject target) => target.GetComponent()); } public static CharacterBody? GetCharacterBodyFromComponent(Component component) { return GetOrAdd(component, CharacterBodies, (GameObject target) => target.GetComponent()); } public static CharacterMaster? GetCharacterMaster(GameObject gameObject) { return GetOrAdd(gameObject, CharacterMasters, (GameObject target) => target.GetComponent()); } public static EquipmentSlot? GetEquipmentSlot(GameObject gameObject) { return GetOrAdd(gameObject, EquipmentSlots, (GameObject target) => target.GetComponent()); } public static HealthComponent? GetHealthComponent(GameObject gameObject) { return GetOrAdd(gameObject, HealthComponents, (GameObject target) => target.GetComponent()); } public static HealthComponent? GetHealthComponentFromComponent(Component component) { return GetOrAdd(component, HealthComponents, (GameObject target) => target.GetComponent()); } public static HuntressTracker? GetHuntressTracker(GameObject gameObject) { return GetOrAdd(gameObject, HuntressTrackers, (GameObject target) => target.GetComponent()); } public static DamageTrail? GetDamageTrail(GameObject gameObject) { return GetOrAdd(gameObject, DamageTrails, (GameObject target) => target.GetComponent()); } public static Rigidbody? GetRigidbody(GameObject gameObject) { return GetOrAdd(gameObject, Rigidbodies, (GameObject target) => target.GetComponent()); } public static Rigidbody? GetRigidbodyFromComponent(Component component) { return GetOrAdd(component, Rigidbodies, (GameObject target) => target.GetComponent()); } public static Rigidbody2D? GetRigidbody2D(GameObject gameObject) { return GetOrAdd(gameObject, Rigidbodies2D, (GameObject target) => target.GetComponent()); } public static IInspectable? GetInspectable(GameObject gameObject) { return GetOrAdd(gameObject, Inspectables, (GameObject target) => target.GetComponent()); } public static IInteractable? GetInteractable(GameObject gameObject) { return GetOrAdd(gameObject, Interactables, (GameObject target) => target.GetComponent()); } public static InteractionDriver? GetInteractionDriver(GameObject gameObject) { return GetOrAdd(gameObject, InteractionDrivers, (GameObject target) => target.GetComponent()); } public static InteractionDriver? GetInteractionDriverFromComponent(Component component) { return GetOrAdd(component, InteractionDrivers, (GameObject target) => target.GetComponent()); } public static InputBankTest? GetInputBankTest(GameObject gameObject) { return GetOrAdd(gameObject, InputBankTests, (GameObject target) => target.GetComponent()); } public static CameraTargetParams? GetCameraTargetParamsFromComponent(Component component) { return GetOrAdd(component, CameraTargetParamsCache, (GameObject target) => target.GetComponent()); } public static ChefController? GetChefController(GameObject gameObject) { return GetOrAdd(gameObject, ChefControllers, (GameObject target) => target.GetComponent()); } public static CharacterMotor? GetCharacterMotor(GameObject gameObject) { return GetOrAdd(gameObject, CharacterMotors, (GameObject target) => target.GetComponent()); } public static CharacterMotor? GetCharacterMotor(Component component) { return GetOrAdd(component, CharacterMotors, (GameObject target) => target.GetComponent()); } public static RigidbodyMotor? GetRigidbodyMotor(Component component) { return GetOrAdd(component, RigidbodyMotors, (GameObject target) => target.GetComponent()); } public static KinematicCharacterMotor? GetKinematicCharacterMotor(Component component) { return GetOrAdd(component, KinematicCharacterMotors, (GameObject target) => target.GetComponent()); } public static NetworkIdentity? GetNetworkIdentity(Component component) { return GetOrAdd(component, NetworkIdentities, (GameObject target) => target.GetComponent()); } public static NetworkUser? GetNetworkUser(GameObject gameObject) { return GetOrAdd(gameObject, NetworkUsers, (GameObject target) => target.GetComponent()); } public static FalseSonBossController? GetFalseSonBossControllerFromComponent(Component component) { return GetOrAdd(component, FalseSonBossControllers, (GameObject target) => target.GetComponent()); } public static OilGhostController? GetOilGhostController(GameObject gameObject) { return GetOrAdd(gameObject, OilGhostControllers, (GameObject target) => target.GetComponent()); } public static PlayerCharacterMasterController? GetPlayerCharacterMasterController(Component component) { return GetOrAdd(component, PlayerCharacterMasterControllers, (GameObject target) => target.GetComponent()); } public static SkillLocator? GetSkillLocator(GameObject gameObject) { return GetOrAdd(gameObject, SkillLocators, (GameObject target) => target.GetComponent()); } public static SkillLocator? GetSkillLocatorFromComponent(Component component) { return GetOrAdd(component, SkillLocators, (GameObject target) => target.GetComponent()); } public static TeamFilter? GetTeamFilter(GameObject gameObject) { return GetOrAdd(gameObject, TeamFilters, (GameObject target) => target.GetComponent()); } public static ProjectileController? GetProjectileController(GameObject gameObject) { return GetOrAdd(gameObject, ProjectileControllers, (GameObject target) => target.GetComponent()); } public static ProjectileDamage? GetProjectileDamage(GameObject gameObject) { return GetOrAdd(gameObject, ProjectileDamages, (GameObject target) => target.GetComponent()); } public static ChildLocator? GetChildLocatorFromComponent(Component component) { return GetOrAdd(component, ChildLocators, (GameObject target) => target.GetComponent()); } public static ChildLocator? GetChildLocator(GameObject gameObject) { return GetOrAdd(gameObject, ChildLocators, (GameObject target) => target.GetComponent()); } public static ScaleParticleSystemDuration? GetScaleParticleSystemDuration(GameObject gameObject) { return GetOrAdd(gameObject, ScaleParticleSystemDurations, (GameObject target) => target.GetComponent()); } public static ScaleParticleSystemDuration? GetScaleParticleSystemDurationFromComponent(Component component) { return GetOrAdd(component, ScaleParticleSystemDurations, (GameObject target) => target.GetComponent()); } public static ObjectScaleCurve? GetObjectScaleCurve(GameObject gameObject) { return GetOrAdd(gameObject, ObjectScaleCurves, (GameObject target) => target.GetComponent()); } public static CharacterDirection? GetCharacterDirectionFromComponent(Component component) { return GetOrAdd(component, CharacterDirections, (GameObject target) => target.GetComponent()); } public static CharacterModel? GetCharacterModelFromComponent(Component component) { return GetOrAdd(component, CharacterModels, (GameObject target) => target.GetComponent()); } public static HurtBoxGroup? GetHurtBoxGroupFromComponent(Component component) { return GetOrAdd(component, HurtBoxGroups, (GameObject target) => target.GetComponent()); } public static HurtBox? GetHurtBoxFromComponent(Component component) { return GetOrAdd(component, HurtBoxes, (GameObject target) => target.GetComponent()); } public static Animator? GetAnimatorInChildren(GameObject gameObject) { return GetOrAdd(gameObject, AnimatorsInChildren, (GameObject target) => target.GetComponentInChildren()); } public static ParticleSystem? GetParticleSystem(Component component) { return GetOrAdd(component, ParticleSystems, (GameObject target) => target.GetComponent()); } public static ParticleSystem[]? GetParticleSystemsInChildren(Component component) { return GetOrAddArray(component, ParticleSystemsInChildren, (Func)((GameObject target) => target.GetComponentsInChildren())); } public static ParticleSystem[]? GetParticleSystemsInChildren(GameObject gameObject) { return GetOrAddArray(gameObject, ParticleSystemsInChildren, (Func)((GameObject target) => target.GetComponentsInChildren())); } public static Light[]? GetLightsInChildren(Component component) { return GetOrAddArray(component, LightsInChildren, (Func)((GameObject target) => target.GetComponentsInChildren())); } public static Renderer[]? GetRenderersInChildren(Component component) { return GetOrAddArray(component, RenderersInChildren, (Func)((GameObject target) => target.GetComponentsInChildren())); } public static Renderer[]? GetRenderersInChildren(GameObject gameObject) { return GetOrAddArray(gameObject, RenderersInChildren, (Func)((GameObject target) => target.GetComponentsInChildren())); } 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(Component component, FixedConditionalWeakTable> cache, Func factory) where T : class { if (!Object.op_Implicit((Object)(object)component)) { return null; } return GetOrAdd(component.gameObject, cache, factory); } private static T? GetOrAdd(GameObject gameObject, FixedConditionalWeakTable> cache, Func factory) where T : class { if (!Object.op_Implicit((Object)(object)gameObject)) { return null; } CacheBox orCreateValue = cache.GetOrCreateValue(gameObject); if (IsMissing(orCreateValue.Value)) { orCreateValue.Value = factory(gameObject); } return orCreateValue.Value; } private static T[]? GetOrAddArray(Component component, FixedConditionalWeakTable> cache, Func factory) where T : Object { if (!Object.op_Implicit((Object)(object)component)) { return null; } return GetOrAddArray(component.gameObject, cache, factory); } private static T[]? GetOrAddArray(GameObject gameObject, FixedConditionalWeakTable> cache, Func factory) where T : Object { if (!Object.op_Implicit((Object)(object)gameObject)) { return null; } CacheBox orCreateValue = cache.GetOrCreateValue(gameObject); if (IsMissingArray(orCreateValue.Value)) { orCreateValue.Value = factory(gameObject); } return orCreateValue.Value; } private static Transform? GetOrFindTransform(TSource source, string childName, Func finder, FixedConditionalWeakTable 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? 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[]? 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 StateByBone = new FixedConditionalWeakTable(); 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 StateByIk = new FixedConditionalWeakTable(); 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 Transpiler(IEnumerable 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 LobbyStates = new FixedConditionalWeakTable(); private static readonly FixedConditionalWeakTable AvatarStates = new FixedConditionalWeakTable(); private static readonly FixedConditionalWeakTable SurvivorStates = new FixedConditionalWeakTable(); 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? instance, FixedConditionalWeakTable table) where T : class { if (instance != null) { ThrottleState orCreateValue = table.GetOrCreateValue(instance); orCreateValue.IsDirty = true; orCreateValue.NextAllowedTime = 0f; } } private static bool ShouldRun(T? instance, float intervalSeconds, FixedConditionalWeakTable 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 { 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> WaitingCallbacks = new List>(); public float StartedAt; } private const float PendingRequestTimeoutSeconds = 5f; private static readonly object Sync = new object(); private static readonly Dictionary CachedTextures = new Dictionary(); private static readonly Dictionary PendingRequests = new Dictionary(); public static bool ShouldRunOriginalRequest(PlatformID id, AvatarSize size, Action? 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> 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 Transpiler(IEnumerable 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 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 Transpiler(IEnumerable 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(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 Transpiler(IEnumerable 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)$"ToolbotDash.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(SoulSearchController), "FixedUpdate")] public static class OptimizeSoulSearchControllerPatch { private static readonly MethodInfo GameObjectGetHuntressTrackerMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(HuntressTracker)); private static readonly MethodInfo ComponentGetHealthComponentMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(HealthComponent)); private static readonly MethodInfo CachedHuntressTrackerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHuntressTracker", (Type[])null, (Type[])null); private static readonly MethodInfo CachedHealthComponentMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHealthComponentFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetHuntressTrackerMethod, CachedHuntressTrackerMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetHealthComponentMethod, CachedHealthComponentMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"SoulSearchController.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(OverloadSpike), "FixedUpdate")] public static class OptimizeOverloadSpikePatch { private static readonly MethodInfo ComponentGetFalseSonBossControllerMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(FalseSonBossController)); private static readonly MethodInfo CachedFalseSonBossControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetFalseSonBossControllerFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetFalseSonBossControllerMethod, CachedFalseSonBossControllerMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"OverloadSpike.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(NetworkTransformVisualizer), "FixedUpdate")] public static class OptimizeNetworkTransformVisualizerPatch { private static readonly MethodInfo GameObjectGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(Rigidbody)); private static readonly MethodInfo GameObjectGetRigidbody2DMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(Rigidbody2D)); private static readonly MethodInfo CachedRigidbodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbody", (Type[])null, (Type[])null); private static readonly MethodInfo CachedRigidbody2DMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbody2D", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetRigidbodyMethod, CachedRigidbodyMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetRigidbody2DMethod, CachedRigidbody2DMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"NetworkTransformVisualizer.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(AllPlayersTrigger), "FixedUpdate")] public static class OptimizeAllPlayersTriggerPatch { private static readonly MethodInfo ComponentGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterBody)); private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBodyFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterBodyMethod, CachedCharacterBodyMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"AllPlayersTrigger.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(MultiBodyTrigger), "FixedUpdate")] public static class OptimizeMultiBodyTriggerPatch { private static readonly MethodInfo ComponentGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterBody)); private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBodyFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterBodyMethod, CachedCharacterBodyMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"MultiBodyTrigger.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(GroundZoneController), "FixedUpdate")] public static class OptimizeGroundZoneControllerPatch { private static readonly MethodInfo ComponentGetRigidbodyMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(RigidbodyMotor)); private static readonly MethodInfo ComponentGetKinematicCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(KinematicCharacterMotor)); private static readonly MethodInfo CachedRigidbodyMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbodyMotor", (Type[])null, (Type[])null); private static readonly MethodInfo CachedKinematicCharacterMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetKinematicCharacterMotor", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetRigidbodyMotorMethod, CachedRigidbodyMotorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetKinematicCharacterMotorMethod, CachedKinematicCharacterMotorMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"GroundZoneController.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(VerticalLift), "FixedUpdate")] public static class OptimizeVerticalLiftPatch { private static readonly MethodInfo ComponentGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CharacterMotor)); private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterMotor", new Type[1] { typeof(Component) }, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetCharacterMotorMethod, CachedCharacterMotorMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"VerticalLift.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } internal static class MorgueHistoryRunReportCache { private sealed class CachedEntry { public string Path = string.Empty; public DateTime LastModifiedUtc; public RunReport? RunReport; } private const int MaxCachedEntries = 256; private static readonly object Sync = new object(); private static readonly Dictionary Entries = new Dictionary(StringComparer.Ordinal); private static readonly FieldInfo? HistoryPathField = AccessTools.Field(typeof(HistoryFileInfo), "path"); private static readonly FieldInfo? HistoryLastModifiedField = AccessTools.Field(typeof(HistoryFileInfo), "lastModified"); public static bool TryGet(HistoryFileInfo historyFileInfo, out RunReport? runReport) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) string path; DateTime lastModifiedUtc; string key = BuildCacheKey(historyFileInfo, out path, out lastModifiedUtc); lock (Sync) { if (Entries.TryGetValue(key, out CachedEntry value) && value.RunReport != null) { runReport = value.RunReport; return true; } } runReport = null; return false; } public static void Store(HistoryFileInfo historyFileInfo, RunReport? runReport) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (runReport == null) { return; } string path; DateTime lastModifiedUtc; string key = BuildCacheKey(historyFileInfo, out path, out lastModifiedUtc); lock (Sync) { Entries[key] = new CachedEntry { Path = path, LastModifiedUtc = lastModifiedUtc, RunReport = runReport }; if (Entries.Count > 256) { Entries.Clear(); } } } public static void Clear() { lock (Sync) { Entries.Clear(); } } private static string BuildCacheKey(HistoryFileInfo historyFileInfo, out string path, out DateTime lastModifiedUtc) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) path = HistoryPathField?.GetValue(historyFileInfo)?.ToString() ?? string.Empty; lastModifiedUtc = ((HistoryLastModifiedField != null) ? ((DateTime)(HistoryLastModifiedField.GetValue(historyFileInfo) ?? ((object)default(DateTime)))) : default(DateTime)); return path + "|" + lastModifiedUtc.Ticks; } } [HarmonyPatch(typeof(HistoryFileInfo), "LoadRunReport")] public static class OptimizeMorgueHistoryFileInfoLoadRunReportPatch { [HarmonyPrefix] private static bool Prefix(HistoryFileInfo __instance, ref RunReport __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (MorgueHistoryRunReportCache.TryGet(__instance, out RunReport runReport) && runReport != null) { __result = runReport; return false; } return true; } [HarmonyPostfix] private static void Postfix(HistoryFileInfo __instance, RunReport __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) MorgueHistoryRunReportCache.Store(__instance, __result); } } [HarmonyPatch(typeof(MorgueManager), "AddRunReportToHistory")] public static class OptimizeMorgueAddRunReportToHistoryPatch { [HarmonyPostfix] private static void Postfix() { MorgueHistoryRunReportCache.Clear(); } } [HarmonyPatch(typeof(MorgueManager), "EnforceHistoryLimit")] public static class OptimizeMorgueEnforceHistoryLimitPatch { [HarmonyPostfix] private static void Postfix() { MorgueHistoryRunReportCache.Clear(); } } [HarmonyPatch(typeof(NetworkAnimator), "FixedUpdate")] public static class OptimizeNetworkAnimatorFixedUpdatePatch { private delegate bool CheckAnimStateChangedDelegate(NetworkAnimator instance, ref int stateHash, ref float normalizedTime); private delegate void WriteParametersDelegate(NetworkAnimator instance, NetworkWriter writer, bool forceAll); private delegate void SendMessageDelegate(NetworkAnimator instance, short msgType, MessageBase msg); private static readonly FieldRef ParameterWriterRef = AccessTools.FieldRefAccess("m_ParameterWriter"); private static readonly Func GetSendMessagesAllowed = AccessTools.MethodDelegate>(AccessTools.PropertyGetter(typeof(NetworkAnimator), "sendMessagesAllowed"), (object)null, true); private static readonly CheckAnimStateChangedDelegate CheckAnimStateChanged = AccessTools.MethodDelegate(AccessTools.Method(typeof(NetworkAnimator), "CheckAnimStateChanged", (Type[])null, (Type[])null), (object)null, true); private static readonly WriteParametersDelegate WriteParameters = AccessTools.MethodDelegate(AccessTools.Method(typeof(NetworkAnimator), "WriteParameters", (Type[])null, (Type[])null), (object)null, true); private static readonly SendMessageDelegate SendMessage = AccessTools.MethodDelegate(AccessTools.Method(typeof(NetworkAnimator), "SendMessage", (Type[])null, (Type[])null), (object)null, true); private static readonly WriterBackedAnimationMessage CachedMessage = new WriterBackedAnimationMessage(); private static bool Prefix(NetworkAnimator __instance) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!GetSendMessagesAllowed(__instance)) { return false; } NetworkWriter val = ParameterWriterRef.Invoke(__instance); if (val == null) { val = new NetworkWriter(); ParameterWriterRef.Invoke(__instance) = val; } OptimizeNetworkAnimatorSendRatePatch.RunCheckSendRate(__instance, val); int stateHash = 0; float normalizedTime = 0f; if (!CheckAnimStateChanged(__instance, ref stateHash, ref normalizedTime)) { return false; } val.SeekZero(); WriteParameters(__instance, val, forceAll: false); CachedMessage.netId = ((NetworkBehaviour)__instance).netId; CachedMessage.stateHash = stateHash; CachedMessage.normalizedTime = normalizedTime; CachedMessage.parametersWriter = val; CachedMessage.parameterLength = val.Position; SendMessage(__instance, 40, (MessageBase)(object)CachedMessage); return false; } } [HarmonyPatch(typeof(NetworkAnimator), "CheckSendRate")] public static class OptimizeNetworkAnimatorSendRatePatch { private delegate void WriteParametersDelegate(NetworkAnimator instance, NetworkWriter writer, bool forceAll); private delegate void SendMessageDelegate(NetworkAnimator instance, short msgType, MessageBase msg); private static readonly FieldRef ParameterWriterRef = AccessTools.FieldRefAccess("m_ParameterWriter"); private static readonly FieldRef SendTimerRef = AccessTools.FieldRefAccess("m_SendTimer"); private static readonly Func GetSendMessagesAllowed = AccessTools.MethodDelegate>(AccessTools.PropertyGetter(typeof(NetworkAnimator), "sendMessagesAllowed"), (object)null, true); private static readonly WriteParametersDelegate WriteParameters = AccessTools.MethodDelegate(AccessTools.Method(typeof(NetworkAnimator), "WriteParameters", (Type[])null, (Type[])null), (object)null, true); private static readonly SendMessageDelegate SendMessage = AccessTools.MethodDelegate(AccessTools.Method(typeof(NetworkAnimator), "SendMessage", (Type[])null, (Type[])null), (object)null, true); private static readonly WriterBackedAnimationParametersMessage CachedMessage = new WriterBackedAnimationParametersMessage(); private static bool Prefix(NetworkAnimator __instance) { RunCheckSendRate(__instance, ParameterWriterRef.Invoke(__instance)); return false; } internal static void RunCheckSendRate(NetworkAnimator instance, NetworkWriter parameterWriter) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (!GetSendMessagesAllowed(instance)) { return; } float networkSendInterval = ((NetworkBehaviour)instance).GetNetworkSendInterval(); if (networkSendInterval != 0f && !(SendTimerRef.Invoke(instance) >= Time.time)) { SendTimerRef.Invoke(instance) = Time.time + networkSendInterval; if (parameterWriter == null) { parameterWriter = new NetworkWriter(); ParameterWriterRef.Invoke(instance) = parameterWriter; } parameterWriter.SeekZero(); WriteParameters(instance, parameterWriter, forceAll: true); CachedMessage.netId = ((NetworkBehaviour)instance).netId; CachedMessage.parametersWriter = parameterWriter; CachedMessage.parameterLength = parameterWriter.Position; SendMessage(instance, 41, (MessageBase)(object)CachedMessage); } } } internal sealed class WriterBackedAnimationMessage : MessageBase { public NetworkInstanceId netId; public int stateHash; public float normalizedTime; public NetworkWriter? parametersWriter; public int parameterLength; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(netId); writer.WritePackedUInt32((uint)stateHash); writer.Write(normalizedTime); if (parametersWriter == null || parameterLength <= 0) { writer.WriteBytesAndSize((byte[])null, 0); } else { writer.WriteBytesAndSize(parametersWriter.AsArray(), parameterLength); } } } internal sealed class WriterBackedAnimationParametersMessage : MessageBase { public NetworkInstanceId netId; public NetworkWriter? parametersWriter; public int parameterLength; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(netId); if (parametersWriter == null || parameterLength <= 0) { writer.WriteBytesAndSize((byte[])null, 0); } else { writer.WriteBytesAndSize(parametersWriter.AsArray(), parameterLength); } } } [HarmonyPatch(typeof(JailerTetherController), "FixedUpdate")] public static class OptimizeJailerTetherControllerPatch { private static readonly MethodInfo GameObjectGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterMotor)); private static readonly MethodInfo GameObjectGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(Rigidbody)); private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterMotor", new Type[1] { typeof(GameObject) }, (Type[])null); private static readonly MethodInfo CachedRigidbodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbody", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetCharacterMotorMethod, CachedCharacterMotorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetRigidbodyMethod, CachedRigidbodyMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"JailerTetherController.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(TarTetherController), "FixedUpdate")] public static class OptimizeTarTetherControllerPatch { private static readonly MethodInfo GameObjectGetCharacterMotorMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterMotor)); private static readonly MethodInfo GameObjectGetRigidbodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(Rigidbody)); private static readonly MethodInfo CachedCharacterMotorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterMotor", new Type[1] { typeof(GameObject) }, (Type[])null); private static readonly MethodInfo CachedRigidbodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetRigidbody", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetCharacterMotorMethod, CachedCharacterMotorMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetRigidbodyMethod, CachedRigidbodyMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"TarTetherController.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(ProjectileDamageTrail), "FixedUpdate")] public static class OptimizeProjectileDamageTrailPatch { private static readonly MethodInfo GameObjectGetDamageTrailMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(DamageTrail)); private static readonly MethodInfo CachedDamageTrailMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetDamageTrail", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetDamageTrailMethod, CachedDamageTrailMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"ProjectileDamageTrail.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(CleaverProjectile), "FixedUpdate")] public static class OptimizeCleaverProjectilePatch { private static readonly MethodInfo GameObjectGetChefControllerMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(ChefController)); private static readonly MethodInfo CachedChefControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChefController", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetChefControllerMethod, CachedChefControllerMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"CleaverProjectile.FixedUpdate optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(MissileController), "FixedUpdate")] public static class OptimizeMissileControllerPatch { private delegate Transform FindTargetDelegate(MissileController instance); private static readonly FieldRef TimerRef = AccessTools.FieldRefAccess("timer"); private static readonly FieldRef RigidbodyRef = AccessTools.FieldRefAccess("rigidbody"); private static readonly FieldRef TransformRef = AccessTools.FieldRefAccess("transform"); private static readonly FieldRef TargetComponentRef = AccessTools.FieldRefAccess("targetComponent"); private static readonly FieldRef TorquePidRef = AccessTools.FieldRefAccess("torquePID"); private static readonly FindTargetDelegate FindTarget = AccessTools.MethodDelegate(AccessTools.Method(typeof(MissileController), "FindTarget", (Type[])null, (Type[])null), (object)null, true); [HarmonyPrefix] private static bool Prefix(MissileController __instance) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) float num = TimerRef.Invoke(__instance) + Time.deltaTime; TimerRef.Invoke(__instance) = num; Rigidbody val = RigidbodyRef.Invoke(__instance); Transform val2 = TransformRef.Invoke(__instance); ProjectileTargetComponent val3 = TargetComponentRef.Invoke(__instance); if (num < __instance.giveupTimer) { val.velocity = val2.forward * __instance.maxVelocity; Transform target = val3.target; if (Object.op_Implicit((Object)(object)target) && num >= __instance.delayTimer) { val.velocity = val2.forward * (__instance.maxVelocity + num * __instance.acceleration); Vector3 val4 = target.position + Random.insideUnitSphere * __instance.turbulence - val2.position; if (val4 != Vector3.zero) { Quaternion rotation = val2.rotation; Quaternion targetQuat = Util.QuaternionSafeLookRotation(val4); QuaternionPID val5 = TorquePidRef.Invoke(__instance); val5.inputQuat = rotation; val5.targetQuat = targetQuat; val.angularVelocity = val5.UpdatePID(); } } } Transform target2 = val3.target; if (!Object.op_Implicit((Object)(object)target2)) { val3.target = FindTarget(__instance); } else { HealthComponent healthComponentFromComponent = OptimizedComponentCache.GetHealthComponentFromComponent((Component)(object)target2); if ((Object)(object)healthComponentFromComponent != (Object)null && !healthComponentFromComponent.alive) { val3.target = FindTarget(__instance); } } if (num > __instance.deathTimer) { Object.Destroy((Object)(object)((Component)__instance).gameObject); } return false; } } [HarmonyPatch(typeof(DaggerController), "FixedUpdate")] public static class OptimizeDaggerControllerPatch { [HarmonyPrefix] private static bool Prefix(DaggerController __instance) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) float num = (__instance.timer += Time.fixedDeltaTime); if (num < __instance.giveupTimer) { Transform target = __instance.target; if (Object.op_Implicit((Object)(object)target)) { Vector3 val = target.position - __instance.transform.position; if (val != Vector3.zero) { __instance.transform.rotation = Util.QuaternionSafeLookRotation(val); } if (num >= __instance.delayTimer) { __instance.rigidbody.AddForce(__instance.transform.forward * __instance.acceleration); if (!__instance.hasPlayedSound) { Util.PlaySound("Play_item_proc_dagger_fly", ((Component)__instance).gameObject); __instance.hasPlayedSound = true; } } } } else { __instance.rigidbody.useGravity = true; } Transform target2 = __instance.target; if (!Object.op_Implicit((Object)(object)target2)) { __instance.target = __instance.FindTarget(); } else { HealthComponent healthComponentFromComponent = OptimizedComponentCache.GetHealthComponentFromComponent((Component)(object)target2); if ((Object)(object)healthComponentFromComponent != (Object)null && !healthComponentFromComponent.alive) { __instance.target = __instance.FindTarget(); } } if (num > __instance.deathTimer) { Object.Destroy((Object)(object)((Component)__instance).gameObject); } return false; } } [HarmonyPatch(typeof(ProjectileFireChildren), "Update")] public static class OptimizeProjectileFireChildrenPatch { [HarmonyPrefix] private static bool Prefix(ProjectileFireChildren __instance) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) __instance.timer += Time.deltaTime; __instance.nextSpawnTimer += Time.deltaTime; if (__instance.timer >= __instance.duration) { Object.Destroy((Object)(object)((Component)__instance).gameObject); } float num = (__instance.useSeparateDurationForFiring ? __instance.customFiringDuration : __instance.duration) / (float)__instance.count; if (__instance.nextSpawnTimer < num || !NetworkServer.active || __instance.spawned >= __instance.count) { return false; } __instance.spawned++; __instance.nextSpawnTimer -= num; Transform transform = ((Component)__instance).transform; GameObject obj = Object.Instantiate(__instance.childProjectilePrefab, transform.position, Util.QuaternionSafeLookRotation(transform.forward)); ProjectileController projectileController = OptimizedComponentCache.GetProjectileController(obj); if ((Object)(object)projectileController != (Object)null) { projectileController.procChainMask = __instance.projectileController.procChainMask; projectileController.procCoefficient = __instance.projectileController.procCoefficient * __instance.childProcCoefficient; projectileController.Networkowner = __instance.projectileController.owner; } TeamFilter teamFilter = OptimizedComponentCache.GetTeamFilter(obj); TeamFilter teamFilter2 = OptimizedComponentCache.GetTeamFilter(((Component)__instance).gameObject); if ((Object)(object)teamFilter != (Object)null && (Object)(object)teamFilter2 != (Object)null) { teamFilter.teamIndex = teamFilter2.teamIndex; } ProjectileDamage projectileDamage = OptimizedComponentCache.GetProjectileDamage(obj); if ((Object)(object)projectileDamage != (Object)null) { projectileDamage.damage = __instance.projectileDamage.damage * __instance.childDamageCoefficient; projectileDamage.crit = __instance.projectileDamage.crit; projectileDamage.force = __instance.projectileDamage.force; projectileDamage.damageColorIndex = __instance.projectileDamage.damageColorIndex; } NetworkServer.Spawn(obj); return false; } } [HarmonyPatch(typeof(WeakState), "FixedUpdate")] public class OptimizeQueenWeakStatePatch { private static readonly MethodInfo GetRandomGrubPointMethod = AccessTools.Method(typeof(OptimizeQueenWeakStatePatch), "GetRandomGrubPoint", (Type[])null, (Type[])null); private static readonly string[] CachedGrubPoints = new string[9] { "GrubSpawnPoint1", "GrubSpawnPoint2", "GrubSpawnPoint3", "GrubSpawnPoint4", "GrubSpawnPoint5", "GrubSpawnPoint6", "GrubSpawnPoint7", "GrubSpawnPoint8", "GrubSpawnPoint9" }; public static string GetRandomGrubPoint() { return CachedGrubPoints[Random.Range(0, CachedGrubPoints.Length)]; } private static IEnumerable Transpiler(IEnumerable instructions) { //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown List list = new List(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, "GrubSpawnPoint")) { 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.Call, (object)GetRandomGrubPointMethod)); } } return list; } } [HarmonyPatch(typeof(RunCameraManager), "Update")] public static class OptimizeRunCameraManagerPatch { private const string PopOutPanelContainerName = "PopoutPanelContainer"; private static readonly MethodInfo GameObjectFindMethod = AccessTools.Method(typeof(GameObject), "Find", new Type[1] { typeof(string) }, (Type[])null); private static readonly MethodInfo GetRectTransformMethod = typeof(GameObject).GetMethods(BindingFlags.Instance | BindingFlags.Public).Single((MethodInfo method) => method.Name == "GetComponent" && method.IsGenericMethodDefinition && method.GetGenericArguments().Length == 1 && method.GetParameters().Length == 0).MakeGenericMethod(typeof(RectTransform)); private static readonly MethodInfo CachedFindMethod = AccessTools.Method(typeof(OptimizeRunCameraManagerPatch), "GetCachedPopOutContainer", (Type[])null, (Type[])null); private static readonly MethodInfo CachedRectTransformMethod = AccessTools.Method(typeof(OptimizeRunCameraManagerPatch), "GetCachedRectTransform", (Type[])null, (Type[])null); private static GameObject? cachedPopOutContainer; private static RectTransform? cachedPopOutRectTransform; [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int findReplacements = 0; int rectTransformReplacements = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, GameObjectFindMethod)) { instruction.operand = CachedFindMethod; findReplacements++; } else if (CodeInstructionExtensions.Calls(instruction, GetRectTransformMethod)) { instruction.opcode = OpCodes.Call; instruction.operand = CachedRectTransformMethod; rectTransformReplacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"RunCameraManager.Update optimized: GameObject.Find={findReplacements}, RectTransform.GetComponent={rectTransformReplacements}"); } } private static GameObject? GetCachedPopOutContainer(string objectName) { if (!string.Equals(objectName, "PopoutPanelContainer")) { return GameObject.Find(objectName); } if (!Object.op_Implicit((Object)(object)cachedPopOutContainer)) { cachedPopOutContainer = GameObject.Find("PopoutPanelContainer"); cachedPopOutRectTransform = (Object.op_Implicit((Object)(object)cachedPopOutContainer) ? cachedPopOutContainer.GetComponent() : null); } return cachedPopOutContainer; } private static RectTransform? GetCachedRectTransform(GameObject gameObject) { if (!Object.op_Implicit((Object)(object)gameObject)) { cachedPopOutContainer = null; cachedPopOutRectTransform = null; return null; } if ((Object)(object)cachedPopOutContainer != (Object)(object)gameObject || !Object.op_Implicit((Object)(object)cachedPopOutRectTransform)) { cachedPopOutContainer = gameObject; cachedPopOutRectTransform = gameObject.GetComponent(); } return cachedPopOutRectTransform; } } [HarmonyPatch(typeof(SniperRangeIndicator), "FixedUpdate")] public class OptimizeSniperUIPatch { private static readonly string[] CachedDistances; private static readonly string MaxDistanceString; private static readonly string InfinityString; static OptimizeSniperUIPatch() { CachedDistances = new string[1000]; MaxDistanceString = "Dis: 999m"; InfinityString = "Dis: ---m"; for (int i = 0; i < 1000; i++) { CachedDistances[i] = $"Dis: {i:D3}m"; } } private static bool Prefix(SniperRangeIndicator __instance) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) float num = float.PositiveInfinity; InputBankTest val = default(InputBankTest); if (Object.op_Implicit((Object)(object)__instance.hudElement.targetCharacterBody) && ((Component)__instance.hudElement.targetCharacterBody).TryGetComponent(ref val)) { Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(val.aimOrigin, val.aimDirection); GameObject gameObject = ((Component)__instance.hudElement.targetCharacterBody).gameObject; Ray val3 = val2; LayerIndex val4 = LayerIndex.world; int num2 = LayerMask.op_Implicit(((LayerIndex)(ref val4)).mask); val4 = LayerIndex.entityPrecise; RaycastHit val5 = default(RaycastHit); if (Util.CharacterRaycast(gameObject, val3, ref val5, float.PositiveInfinity, LayerMask.op_Implicit(num2 | LayerMask.op_Implicit(((LayerIndex)(ref val4)).mask)), (QueryTriggerInteraction)0)) { num = ((RaycastHit)(ref val5)).distance; } } if (float.IsInfinity(num)) { ((TMP_Text)__instance.label).text = InfinityString; } else if (num > 999f) { ((TMP_Text)__instance.label).text = MaxDistanceString; } else { int num3 = Mathf.FloorToInt(num); ((TMP_Text)__instance.label).text = CachedDistances[num3]; } return false; } } internal static class OptimizeStateVfxPatchTools { public static readonly MethodInfo GameObjectGetChildLocatorMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(ChildLocator)); public static readonly MethodInfo ComponentGetChildLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ChildLocator)); public static readonly MethodInfo GameObjectGetObjectScaleCurveMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(ObjectScaleCurve)); public static readonly MethodInfo GameObjectGetScaleParticleSystemDurationMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(ScaleParticleSystemDuration)); public static readonly MethodInfo ComponentGetScaleParticleSystemDurationMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(ScaleParticleSystemDuration)); public static readonly MethodInfo GameObjectGetAnimatorInChildrenMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentInChildrenMethod(typeof(Animator)); public static readonly MethodInfo CachedChildLocatorFromComponentMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChildLocatorFromComponent", (Type[])null, (Type[])null); public static readonly MethodInfo CachedChildLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetChildLocator", (Type[])null, (Type[])null); public static readonly MethodInfo CachedObjectScaleCurveMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetObjectScaleCurve", (Type[])null, (Type[])null); public static readonly MethodInfo CachedScaleParticleSystemDurationMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetScaleParticleSystemDuration", (Type[])null, (Type[])null); public static readonly MethodInfo CachedScaleParticleSystemDurationFromComponentMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetScaleParticleSystemDurationFromComponent", (Type[])null, (Type[])null); public static readonly MethodInfo CachedAnimatorInChildrenMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetAnimatorInChildren", (Type[])null, (Type[])null); public static IEnumerable ReplaceInstructions(IEnumerable instructions, string logName, bool replaceChildLocatorFromGameObject = false, bool replaceChildLocator = false, bool replaceObjectScaleCurve = false, bool replaceScaleDurationFromGameObject = false, bool replaceScaleDurationFromComponent = false, bool replaceAnimatorInChildrenFromGameObject = false) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if ((replaceChildLocatorFromGameObject && OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetChildLocatorMethod, CachedChildLocatorMethod)) || (replaceChildLocator && OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetChildLocatorMethod, CachedChildLocatorFromComponentMethod)) || (replaceObjectScaleCurve && OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetObjectScaleCurveMethod, CachedObjectScaleCurveMethod)) || (replaceScaleDurationFromGameObject && OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetScaleParticleSystemDurationMethod, CachedScaleParticleSystemDurationMethod)) || (replaceScaleDurationFromComponent && OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetScaleParticleSystemDurationMethod, CachedScaleParticleSystemDurationFromComponentMethod)) || (replaceAnimatorInChildrenFromGameObject && OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetAnimatorInChildrenMethod, CachedAnimatorInChildrenMethod))) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"{logName} optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(PortalJump), "FixedUpdate")] public static class OptimizePortalJumpPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "PortalJump.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: true, replaceObjectScaleCurve: true); } } [HarmonyPatch(typeof(GroundSwipe), "FixedUpdate")] public static class OptimizeGroundSwipePatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "GroundSwipe.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: true, replaceScaleDurationFromGameObject: true); } } [HarmonyPatch(typeof(SeekingBomb), "FixedUpdate")] public static class OptimizeSeekingBombStatePatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "SeekingBomb.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: true, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: true); } } [HarmonyPatch(typeof(BaseChargeFist), "FixedUpdate")] public static class OptimizeBaseChargeFistPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "BaseChargeFist.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(Flamebreath), "FixedUpdate")] public static class OptimizeFlamebreathPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "Flamebreath.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(Ignite), "FixedUpdate")] public static class OptimizeIgnitePatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "Ignite.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(BlinkState), "FixedUpdate")] public static class OptimizeBlinkStatePatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "BlinkState.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: true, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(Flamethrower), "OnEnter")] public static class OptimizeDroneFlamethrowerPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "DroneFlamethrower.OnEnter", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(ClubSwing3), "FixedUpdate")] public static class OptimizeClubSwing3Patch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "ClubSwing3.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(ClubForsakenBoss), "FixedUpdate")] public static class OptimizeClubForsakenBossPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "ClubForsakenBoss.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(SwatAwayPlayersWindup), "FixedUpdate")] public static class OptimizeSwatAwayPlayersWindupPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "SwatAwayPlayersWindup.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(Flamethrower), "FixedUpdate")] public static class OptimizeMageFlamethrowerPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "MageFlamethrower.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(ChargeLunarGuns), "FixedUpdate")] public static class OptimizeChargeLunarGunsPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "ChargeLunarGuns.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: true); } } [HarmonyPatch(typeof(Beam), "FixedUpdate")] public static class OptimizeBeamPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "Beam.FixedUpdate", replaceChildLocatorFromGameObject: true); } } [HarmonyPatch(typeof(FlamethrowerCannon), "FixedUpdate")] public static class OptimizeFlamethrowerCannonPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "FlamethrowerCannon.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(FlamethrowerTurret), "FixedUpdate")] public static class OptimizeFlamethrowerTurretPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "FlamethrowerTurret.FixedUpdate", replaceChildLocatorFromGameObject: false, replaceChildLocator: false, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: true); } } [HarmonyPatch(typeof(Meditate), "Update")] public static class OptimizeMeditatePatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeStateVfxPatchTools.ReplaceInstructions(instructions, "Meditate.Update", replaceChildLocatorFromGameObject: true, replaceChildLocator: true, replaceObjectScaleCurve: false, replaceScaleDurationFromGameObject: false, replaceScaleDurationFromComponent: false, replaceAnimatorInChildrenFromGameObject: true); } } internal static class SurvivorAvailabilityCache { private sealed class CachedEntry { public int Version; public bool Value; } private static readonly object Sync = new object(); private static readonly Dictionary CachedAvailability = new Dictionary(); private static int version; public static bool TryGet(SurvivorIndex survivorIndex, out bool isUnlocked) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) lock (Sync) { if (CachedAvailability.TryGetValue(survivorIndex, out CachedEntry value) && value.Version == version) { isUnlocked = value.Value; return true; } } isUnlocked = false; return false; } public static void Store(SurvivorIndex survivorIndex, bool isUnlocked) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) lock (Sync) { CachedAvailability[survivorIndex] = new CachedEntry { Version = version, Value = isUnlocked }; } } public static void Invalidate() { lock (Sync) { version++; if (CachedAvailability.Count > 0) { CachedAvailability.Clear(); } } } } [HarmonyPatch(typeof(SurvivorCatalog), "SurvivorIsUnlockedOnThisClient")] public static class OptimizeSurvivorCatalogAvailabilityPatch { [HarmonyPrefix] private static bool Prefix(SurvivorIndex survivorIndex, ref bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (SurvivorAvailabilityCache.TryGet(survivorIndex, out var isUnlocked)) { __result = isUnlocked; return false; } return true; } [HarmonyPostfix] private static void Postfix(SurvivorIndex survivorIndex, bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) SurvivorAvailabilityCache.Store(survivorIndex, __result); } } [HarmonyPatch(typeof(UserProfile), "GrantUnlockable")] public static class OptimizeSurvivorAvailabilityGrantUnlockablePatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(UserProfile), "RevokeUnlockable")] public static class OptimizeSurvivorAvailabilityRevokeUnlockablePatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(LocalUserManager), "AddMainUser", new Type[] { typeof(UserProfile) })] public static class OptimizeSurvivorAvailabilityAddMainUserPatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(LocalUserManager), "RemoveUser", new Type[] { typeof(int) })] public static class OptimizeSurvivorAvailabilityRemoveUserByIndexPatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(LocalUser), "set_userProfile")] public static class OptimizeSurvivorAvailabilitySetUserProfilePatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(LocalUserManager), "ClearUsers")] public static class OptimizeSurvivorAvailabilityClearUsersPatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(LocalUserManager), "SetLocalUsers")] public static class OptimizeSurvivorAvailabilitySetLocalUsersPatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(SurvivorCatalog), "SetSurvivorDefs")] public static class OptimizeSurvivorAvailabilitySetSurvivorDefsPatch { [HarmonyPostfix] private static void Postfix() { SurvivorAvailabilityCache.Invalidate(); } } [HarmonyPatch(typeof(ProjectileDirectionalTargetFinder), "FixedUpdate")] public static class OptimizeProjectileDirectionalTargetFinderPatch { [HarmonyPrefix] private static bool Prefix(ProjectileDirectionalTargetFinder __instance) { __instance.searchTimer -= Time.fixedDeltaTime; if (__instance.searchTimer > 0f) { return false; } __instance.searchTimer += __instance.targetSearchInterval; Transform val = __instance.targetComponent.target; if (__instance.allowTargetLoss && Object.op_Implicit((Object)(object)val) && (Object)(object)__instance.lastFoundTransform == (Object)(object)val && !__instance.PassesFilters(__instance.lastFoundHurtBox)) { __instance.SetTarget((HurtBox)null); val = null; } if (!__instance.onlySearchIfNoTarget || !Object.op_Implicit((Object)(object)val)) { __instance.SearchForTarget(); val = __instance.targetComponent.target; } __instance.hasTarget = (Object)(object)val != (Object)null; if (__instance.hadTargetLastUpdate != __instance.hasTarget) { if (__instance.hasTarget) { UnityEvent onNewTargetFound = __instance.onNewTargetFound; if (onNewTargetFound != null) { onNewTargetFound.Invoke(); } } else { UnityEvent onTargetLost = __instance.onTargetLost; if (onTargetLost != null) { onTargetLost.Invoke(); } } } __instance.hadTargetLastUpdate = __instance.hasTarget; return false; } } [HarmonyPatch(typeof(ProjectileSphereTargetFinder), "FixedUpdate")] public static class OptimizeProjectileSphereTargetFinderPatch { [HarmonyPrefix] private static bool Prefix(ProjectileSphereTargetFinder __instance) { __instance.searchTimer -= Time.fixedDeltaTime; if (__instance.searchTimer > 0f) { return false; } __instance.searchTimer += __instance.targetSearchInterval; Transform val = __instance.targetComponent.target; if (__instance.allowTargetLoss && Object.op_Implicit((Object)(object)val) && (Object)(object)__instance.lastFoundTransform == (Object)(object)val && !__instance.PassesFilters(__instance.lastFoundHurtBox)) { __instance.SetTarget((HurtBox)null); val = null; } if (!__instance.onlySearchIfNoTarget || !Object.op_Implicit((Object)(object)val)) { __instance.SearchForTarget(); val = __instance.targetComponent.target; } __instance.hasTarget = (Object)(object)val != (Object)null; if (__instance.hadTargetLastUpdate != __instance.hasTarget) { if (__instance.hasTarget) { UnityEvent onNewTargetFound = __instance.onNewTargetFound; if (onNewTargetFound != null) { onNewTargetFound.Invoke(); } } else { UnityEvent onTargetLost = __instance.onTargetLost; if (onTargetLost != null) { onTargetLost.Invoke(); } } } __instance.hadTargetLastUpdate = __instance.hasTarget; return false; } } [HarmonyPatch(typeof(ProjectileSteerTowardTarget), "FixedUpdate")] public static class OptimizeProjectileSteerTowardTargetPatch { [HarmonyPrefix] private static bool Prefix(ProjectileSteerTowardTarget __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) Transform target = __instance.targetComponent.target; if (Object.op_Implicit((Object)(object)target)) { Vector3 val = target.position - __instance.transform.position; if (__instance.yAxisOnly) { val.y = 0f; } if (val != Vector3.zero) { __instance.transform.forward = Vector3.RotateTowards(__instance.transform.forward, val, __instance.rotationSpeed * (MathF.PI / 180f) * Time.fixedDeltaTime, 0f); } if (__instance.increaseSpeedOverTime && !__instance._reachedMaxSpeed) { __instance._rotationSpeed += __instance.rotationAddPerSecond * Time.fixedDeltaTime; if (__instance._rotationSpeed > __instance.maxRotationSpeed) { __instance._rotationSpeed = __instance.maxRotationSpeed; __instance._reachedMaxSpeed = true; } } } return false; } } [HarmonyPatch(typeof(ProjectileStopOnTargetLoss), "FixedUpdate")] public static class OptimizeProjectileStopOnTargetLossPatch { [HarmonyPrefix] private static bool Prefix(ProjectileStopOnTargetLoss __instance) { Transform target = __instance.projectileTargetComponent.target; if ((Object)(object)target != (Object)(object)__instance.targetTransform) { __instance.SetTarget(target); } HurtBox targetHurtbox = __instance.targetHurtbox; bool flag = Object.op_Implicit((Object)(object)targetHurtbox) && Object.op_Implicit((Object)(object)targetHurtbox.healthComponent) && targetHurtbox.healthComponent.alive; if (((Behaviour)__instance.projectileSimple).enabled != flag) { ((Behaviour)__instance.projectileSimple).enabled = flag; } return false; } } internal static class TextMeshHotspotDeduplication { private static readonly FieldRef CurrentTextField = AccessTools.FieldRefAccess("m_text"); private static readonly FieldRef CurrentMaxVisibleCharactersField = AccessTools.FieldRefAccess("m_maxVisibleCharacters"); private static readonly FieldRef CurrentFontColorField = AccessTools.FieldRefAccess("m_fontColor"); private static readonly FieldRef CurrentFontSizeField = AccessTools.FieldRefAccess("m_fontSize"); private static readonly FieldRef CurrentAlignmentField = AccessTools.FieldRefAccess("m_textAlignment"); private static readonly FieldRef CurrentFontAssetField = AccessTools.FieldRefAccess("m_fontAsset"); private static readonly FieldRef CurrentVertsDirtyField = AccessTools.FieldRefAccess("m_VertsDirty"); private static readonly FieldRef CurrentLayoutDirtyField = AccessTools.FieldRefAccess("m_isLayoutDirty"); private static readonly FieldRef CurrentMaterialDirtyField = AccessTools.FieldRefAccess("m_isMaterialDirty"); public static bool ShouldApplyString(TMP_Text? textComponent, string? incomingText) { if ((Object)(object)textComponent == (Object)null) { return true; } return !string.Equals(CurrentTextField.Invoke(textComponent), incomingText); } public static bool ShouldApplyStringBuilder(TMP_Text? textComponent, StringBuilder? sourceText, int startIndex, int length) { if ((Object)(object)textComponent == (Object)null || sourceText == null) { return true; } string text = CurrentTextField.Invoke(textComponent) ?? string.Empty; if (length < 0 || startIndex < 0 || startIndex + length > sourceText.Length) { return true; } if (text.Length != length) { return true; } for (int i = 0; i < length; i++) { if (text[i] != sourceText[startIndex + i]) { return true; } } return false; } public static bool ShouldApplyWholeStringBuilder(TMP_Text? textComponent, StringBuilder? sourceText) { if (sourceText == null) { return true; } return ShouldApplyStringBuilder(textComponent, sourceText, 0, sourceText.Length); } public static bool ShouldApplyMaxVisibleCharacters(TMP_Text? textComponent, int value) { if ((Object)(object)textComponent == (Object)null) { return true; } return CurrentMaxVisibleCharactersField.Invoke(textComponent) != value; } public static bool ShouldApplyAlpha(TMP_Text? textComponent, float value) { if ((Object)(object)textComponent == (Object)null) { return true; } return !Mathf.Approximately(CurrentFontColorField.Invoke(textComponent).a, value); } public static bool ShouldApplyFontSize(TMP_Text? textComponent, float value) { if ((Object)(object)textComponent == (Object)null) { return true; } return !Mathf.Approximately(CurrentFontSizeField.Invoke(textComponent), value); } public static bool ShouldApplyAlignment(TMP_Text? textComponent, TextAlignmentOptions value) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between I4 and Unknown if ((Object)(object)textComponent == (Object)null) { return true; } return (int)CurrentAlignmentField.Invoke(textComponent) != (int)value; } public static bool ShouldApplyFont(TMP_Text? textComponent, TMP_FontAsset? value) { if ((Object)(object)textComponent == (Object)null) { return true; } return (Object)(object)CurrentFontAssetField.Invoke(textComponent) != (Object)(object)value; } public static bool ShouldSetVerticesDirty(Graphic? graphic) { if ((Object)(object)graphic == (Object)null || !(graphic is TextMeshProUGUI)) { return true; } return !CurrentVertsDirtyField.Invoke(graphic); } public static bool ShouldSetLayoutDirty(TMP_Text? textComponent) { if ((Object)(object)textComponent == (Object)null) { return true; } return !CurrentLayoutDirtyField.Invoke(textComponent); } public static bool ShouldSetMaterialDirty(TMP_Text? textComponent) { if ((Object)(object)textComponent == (Object)null) { return true; } return !CurrentMaterialDirtyField.Invoke(textComponent); } } [HarmonyPatch(typeof(TMP_Text), "set_text")] public static class OptimizeTmpTextSetterPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, string value) { return TextMeshHotspotDeduplication.ShouldApplyString(__instance, value); } } [HarmonyPatch(typeof(TMP_Text), "SetText", new Type[] { typeof(string), typeof(bool) })] public static class OptimizeTmpTextSetTextStringPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, string sourceText) { return TextMeshHotspotDeduplication.ShouldApplyString(__instance, sourceText); } } [HarmonyPatch(typeof(TMP_Text), "SetText", new Type[] { typeof(StringBuilder) })] public static class OptimizeTmpTextSetTextStringBuilderPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, StringBuilder sourceText) { return TextMeshHotspotDeduplication.ShouldApplyWholeStringBuilder(__instance, sourceText); } } [HarmonyPatch(typeof(TMP_Text), "SetText", new Type[] { typeof(StringBuilder), typeof(int), typeof(int) })] public static class OptimizeTmpTextSetTextStringBuilderRangePatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, StringBuilder sourceText, int start, int length) { return TextMeshHotspotDeduplication.ShouldApplyStringBuilder(__instance, sourceText, start, length); } } [HarmonyPatch(typeof(TMP_Text), "set_maxVisibleCharacters")] public static class OptimizeTmpTextMaxVisibleCharactersPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, int value) { return TextMeshHotspotDeduplication.ShouldApplyMaxVisibleCharacters(__instance, value); } } [HarmonyPatch(typeof(TMP_Text), "set_alpha")] public static class OptimizeTmpTextAlphaPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, float value) { return TextMeshHotspotDeduplication.ShouldApplyAlpha(__instance, value); } } [HarmonyPatch(typeof(TMP_Text), "set_fontSize")] public static class OptimizeTmpTextFontSizePatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, float value) { return TextMeshHotspotDeduplication.ShouldApplyFontSize(__instance, value); } } [HarmonyPatch(typeof(TMP_Text), "set_alignment")] public static class OptimizeTmpTextAlignmentPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, TextAlignmentOptions value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return TextMeshHotspotDeduplication.ShouldApplyAlignment(__instance, value); } } [HarmonyPatch(typeof(TMP_Text), "set_font")] public static class OptimizeTmpTextFontPatch { [HarmonyPrefix] private static bool Prefix(TMP_Text __instance, TMP_FontAsset value) { return TextMeshHotspotDeduplication.ShouldApplyFont(__instance, value); } } [HarmonyPatch(typeof(Graphic), "SetVerticesDirty")] public static class OptimizeTmpGraphicSetVerticesDirtyPatch { [HarmonyPrefix] private static bool Prefix(Graphic __instance) { return TextMeshHotspotDeduplication.ShouldSetVerticesDirty(__instance); } } [HarmonyPatch(typeof(TextMeshProUGUI), "SetLayoutDirty")] public static class OptimizeTmpTextSetLayoutDirtyPatch { [HarmonyPrefix] private static bool Prefix(TextMeshProUGUI __instance) { return TextMeshHotspotDeduplication.ShouldSetLayoutDirty((TMP_Text?)(object)__instance); } } [HarmonyPatch(typeof(TextMeshProUGUI), "SetMaterialDirty")] public static class OptimizeTmpTextSetMaterialDirtyPatch { [HarmonyPrefix] private static bool Prefix(TextMeshProUGUI __instance) { return TextMeshHotspotDeduplication.ShouldSetMaterialDirty((TMP_Text?)(object)__instance); } } [HarmonyPatch(typeof(ProximityHighlight), "FixedUpdate")] public static class OptimizeProximityHighlightPatch { private static readonly MethodInfo ComponentGetInteractionDriverMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(InteractionDriver)); private static readonly MethodInfo CachedInteractionDriverMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInteractionDriverFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, ComponentGetInteractionDriverMethod, CachedInteractionDriverMethod, "ProximityHighlight.FixedUpdate"); } } [HarmonyPatch(typeof(ScreenDamage), "Update")] public static class OptimizeScreenDamagePatch { private static readonly MethodInfo GameObjectGetHealthComponentMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(HealthComponent)); private static readonly MethodInfo CachedHealthComponentMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetHealthComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, GameObjectGetHealthComponentMethod, CachedHealthComponentMethod, "ScreenDamage.Update"); } } [HarmonyPatch(typeof(NetworkUser), "Update")] public static class OptimizeNetworkUserPatch { private static readonly MethodInfo GameObjectGetCharacterMasterMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterMaster)); private static readonly MethodInfo CachedCharacterMasterMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterMaster", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, GameObjectGetCharacterMasterMethod, CachedCharacterMasterMethod, "NetworkUser.Update"); } } [HarmonyPatch(typeof(DisplayStock), "Update")] public static class OptimizeDisplayStockPatch { private static readonly MethodInfo ComponentGetSkillLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(SkillLocator)); private static readonly MethodInfo CachedSkillLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetSkillLocatorFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, ComponentGetSkillLocatorMethod, CachedSkillLocatorMethod, "DisplayStock.Update"); } } [HarmonyPatch(typeof(SniperScopeChargeIndicatorController), "FixedUpdate")] public static class OptimizeSniperScopeChargeIndicatorPatch { private static readonly MethodInfo ComponentGetSkillLocatorMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(SkillLocator)); private static readonly MethodInfo CachedSkillLocatorMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetSkillLocatorFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, ComponentGetSkillLocatorMethod, CachedSkillLocatorMethod, "SniperScopeChargeIndicatorController.FixedUpdate"); } } [HarmonyPatch(typeof(FireAuraController), "FixedUpdate")] public static class OptimizeFireAuraControllerPatch { private static readonly MethodInfo GameObjectGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterBody)); private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBody", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, GameObjectGetCharacterBodyMethod, CachedCharacterBodyMethod, "FireAuraController.FixedUpdate"); } } [HarmonyPatch(typeof(GhostGunController), "FixedUpdate")] public static class OptimizeGhostGunControllerPatch { private static readonly MethodInfo GameObjectGetInputBankTestMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(InputBankTest)); private static readonly MethodInfo CachedInputBankTestMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInputBankTest", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, GameObjectGetInputBankTestMethod, CachedInputBankTestMethod, "GhostGunController.FixedUpdate"); } } [HarmonyPatch(typeof(OilController), "Update")] public static class OptimizeOilControllerPatch { private static readonly MethodInfo GameObjectGetOilGhostControllerMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(OilGhostController)); private static readonly MethodInfo CachedOilGhostControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetOilGhostController", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, GameObjectGetOilGhostControllerMethod, CachedOilGhostControllerMethod, "OilController.Update"); } } [HarmonyPatch(typeof(MusicController), "LateUpdate")] public static class OptimizeMusicControllerPatch { private static readonly MethodInfo GameObjectGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterBody)); private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBody", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, GameObjectGetCharacterBodyMethod, CachedCharacterBodyMethod, "MusicController.LateUpdate"); } } [HarmonyPatch(typeof(BazaarController), "Update")] public static class OptimizeBazaarControllerPatch { private static readonly MethodInfo GameObjectGetInputBankTestMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(InputBankTest)); private static readonly MethodInfo GameObjectGetCharacterBodyMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(CharacterBody)); private static readonly MethodInfo CachedInputBankTestMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetInputBankTest", (Type[])null, (Type[])null); private static readonly MethodInfo CachedCharacterBodyMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCharacterBody", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetInputBankTestMethod, CachedInputBankTestMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetCharacterBodyMethod, CachedCharacterBodyMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"BazaarController.Update optimized: cached GetComponent calls={replacements}"); } } } [HarmonyPatch(typeof(HelfireController), "LateUpdate")] public static class OptimizeHelfireControllerPatch { private static readonly MethodInfo ComponentGetCameraTargetParamsMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(CameraTargetParams)); private static readonly MethodInfo CachedCameraTargetParamsMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetCameraTargetParamsFromComponent", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { return OptimizeUiAndUtilityPatchTools.ReplaceInstructions(instructions, ComponentGetCameraTargetParamsMethod, CachedCameraTargetParamsMethod, "HelfireController.LateUpdate"); } } [HarmonyPatch(typeof(Nameplate), "LateUpdate")] public static class OptimizeNameplatePatch { private static readonly MethodInfo ComponentGetPlayerCharacterMasterControllerMethod = OptimizeGetComponentPatchTools.MakeComponentGetComponentMethod(typeof(PlayerCharacterMasterController)); private static readonly MethodInfo GameObjectGetNetworkUserMethod = OptimizeGetComponentPatchTools.MakeGameObjectGetComponentMethod(typeof(NetworkUser)); private static readonly MethodInfo CachedPlayerCharacterMasterControllerMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetPlayerCharacterMasterController", (Type[])null, (Type[])null); private static readonly MethodInfo CachedNetworkUserMethod = AccessTools.Method(typeof(OptimizedComponentCache), "GetNetworkUser", (Type[])null, (Type[])null); [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, ComponentGetPlayerCharacterMasterControllerMethod, CachedPlayerCharacterMasterControllerMethod) || OptimizeGetComponentPatchTools.ReplaceCall(instruction, GameObjectGetNetworkUserMethod, CachedNetworkUserMethod)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"Nameplate.LateUpdate optimized: cached GetComponent calls={replacements}"); } } } internal static class OptimizeUiAndUtilityPatchTools { internal static IEnumerable ReplaceInstructions(IEnumerable instructions, MethodInfo source, MethodInfo target, string label) { int replacements = 0; foreach (CodeInstruction instruction in instructions) { if (OptimizeGetComponentPatchTools.ReplaceCall(instruction, source, target)) { replacements++; } yield return instruction; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)$"{label} optimized: cached GetComponent calls={replacements}"); } } } internal static class UiTextStyleHotspotTools { public static bool IsAlreadyApplied(TextStyle textStyle, TextMeshProUGUI? label, bool useAlignment) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)label == (Object)null) { return false; } if ((Object)(object)((TMP_Text)label).font != (Object)(object)textStyle.font) { return false; } if (!Mathf.Approximately(((TMP_Text)label).fontSize, textStyle.fontSize)) { return false; } if (!AreColorsEqual(((Graphic)label).color, textStyle.color)) { return false; } if (useAlignment && ((TMP_Text)label).alignment != textStyle.alignment) { return false; } return true; } private static bool AreColorsEqual(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g) && Mathf.Approximately(a.b, b.b)) { return Mathf.Approximately(a.a, b.a); } return false; } } [HarmonyPatch(typeof(TextStyle), "Apply")] public static class OptimizeUiSkinTextStyleApplyPatch { [HarmonyPrefix] private static bool Prefix(TextStyle __instance, TextMeshProUGUI label, bool useAlignment) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return !UiTextStyleHotspotTools.IsAlreadyApplied(__instance, label, useAlignment); } } [HarmonyPatch(typeof(SummonEliteVultures), "FixedUpdate")] public class OptimizeVulturesPatch { private static readonly MethodInfo GetFastVultureMuzzleMethod; private static readonly string[] CachedVultureMuzzles; static OptimizeVulturesPatch() { GetFastVultureMuzzleMethod = AccessTools.Method(typeof(OptimizeVulturesPatch), "GetFastVultureMuzzle", (Type[])null, (Type[])null); CachedVultureMuzzles = new string[10]; string arg = SummonEliteVultures.summonMuzzleString ?? "Muzzle"; for (int i = 0; i < CachedVultureMuzzles.Length; i++) { CachedVultureMuzzles[i] = $"{arg} {i}"; } } public static string GetFastVultureMuzzle(SummonEliteVultures instance) { int value = Traverse.Create((object)instance).Field("summonCount").Value; if (value >= 0 && value < CachedVultureMuzzles.Length) { return CachedVultureMuzzles[value]; } return $"{SummonEliteVultures.summonMuzzleString} {value}"; } private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown List list = new List(instructions); FieldInfo objB = AccessTools.Field(typeof(SummonEliteVultures), "summonMuzzleString"); MethodInfo objB2 = AccessTools.Method(typeof(string), "Concat", new Type[3] { typeof(string), typeof(string), typeof(string) }, (Type[])null); int num = -1; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldsfld && object.Equals(list[i].operand, objB)) { 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, objB2)) { 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)GetFastVultureMuzzleMethod)); } } return list; } } } namespace ROR_O.patches.mods { [HarmonyPatch] public class OptimizeLookingGlassPatch { internal static readonly Dictionary DescriptionCache = new Dictionary(); private static MethodBase? TargetMethod() { Type type = AccessTools.TypeByName("LookingGlass.ItemStatsNameSpace.ItemStats"); if (type == null) { return null; } ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)"Mod LookingGlass found! Apply patch !"); } return AccessTools.Method(type, "GetItemDescription", (Type[])null, (Type[])null); } private static bool Prefix(ItemDef itemDef, int newItemCount, CharacterMaster master, bool withOneMore, bool forceNew, ref string __result) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected I4, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected I4, but got Unknown if ((Object)(object)itemDef == (Object)null) { return true; } float num = ((master != null) ? master.luck : 0f); string key = $"{itemDef.itemIndex}_{newItemCount}_{num}_{withOneMore}_{forceNew}"; if (DescriptionCache.TryGetValue(key, out string value)) { __result = value; return false; } if (Language.IsTokenInvalid(itemDef.descriptionToken)) { __result = Language.GetString(itemDef.pickupToken); return false; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append($""); stringBuilder.Append(Language.GetString(itemDef.descriptionToken)); stringBuilder.Append("\n"); try { if (ItemStats.itemStatsCalculations.Value && ItemDefinitions.allItemDefinitions.ContainsKey((int)itemDef.itemIndex)) { ItemStatsDef val = ItemDefinitions.allItemDefinitions[(int)itemDef.itemIndex]; if (withOneMore && val.descriptions.Count != 0) { if (newItemCount == 0 || forceNew) { stringBuilder.Append("\nWith this item, you will have:"); } else { stringBuilder.Append("\nWith another stack, you will have:"); } newItemCount++; } bool flag = false; if (val.isScrap && ((Object)(object)master == (Object)null || master.inventory.GetItemCountEffective(Items.StatsFromScrap) <= 0)) { flag = true; } if (!flag) { List list = null; if (val.calculateValuesFlat != null) { list = val.calculateValuesFlat(newItemCount); } else if (val.calculateValuesNew != null) { list = val.calculateValuesNew(num, newItemCount, 1f); } else if (val.calculateValues != null) { list = val.calculateValues(master, newItemCount); } else if (val.calculateValuesBody != null) { object obj = ((master != null) ? master.GetBody() : null); if (obj == null) { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); obj = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null); } CharacterBody val2 = (CharacterBody)obj; if ((Object)(object)val2 != (Object)null) { list = val.calculateValuesBody(val2, newItemCount); } } if (list != null) { AppendFormattedStats(stringBuilder, val, list, white: true); } } } } catch (Exception) { } stringBuilder.Append(""); string text = stringBuilder.ToString(); DescriptionCache[key] = text; __result = text; return false; } private static void AppendFormattedStats(StringBuilder sb, ItemStatsDef statsDef, List values, bool white) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected I4, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected I4, but got Unknown for (int i = 0; i < statsDef.descriptions.Count; i++) { sb.Append('\n'); if (white) { sb.Append(""); } sb.Append(statsDef.descriptions[i]); if (white) { sb.Append(""); } ValueType val = statsDef.valueTypes[i]; switch ((int)val) { default: if ((int)val != 17) { sb.Append(""); sb.Append(values[i].ToString("0.##")); sb.Append("m"); break; case 1: sb.Append("\">"); sb.Append((values[i] * 100f).ToString("0.##")); sb.Append("%"); break; case 2: sb.Append("\">"); sb.Append(values[i].ToString("0.##")); sb.Append(" HP"); break; case 3: sb.Append("\">"); sb.Append(values[i].ToString("0.##")); sb.Append(" HP/s"); break; case 4: sb.Append("\">"); sb.Append(values[i].ToString("0.##")); sb.Append(""); break; case 5: sb.Append("\">"); sb.Append(values[i].ToString("0.#")); sb.Append("$"); break; case 6: sb.Append("\">"); sb.Append(values[i].ToString("0.##")); sb.Append(" seconds"); break; case 7: sb.Append("\">"); sb.Append((values[i] * 100f).ToString("0.##")); sb.Append("% HP"); break; case 8: sb.Append("\">"); sb.Append((values[i] * 100f).ToString("0.##")); sb.Append("% HP/s"); break; case 9: sb.Append("\">"); sb.Append(values[i].ToString("0.0##")); sb.Append(""); break; } } } } [HarmonyPatch(typeof(Run), "Start")] public class ClearLookingGlassCachePatch { [HarmonyPostfix] public static void Postfix() { OptimizeLookingGlassPatch.DescriptionCache.Clear(); ManualLogSource? globalLogger = RORO.GlobalLogger; if (globalLogger != null) { globalLogger.LogInfo((object)"The LookingGlass cache has been successfully cleared for a new race!"); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }