Decompiled source of PeakSafeOptimizer v1.0.0
plugins/PeakSafeOptimizer.dll
Decompiled 9 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Peak; using Peak.Afflictions; using Peak.Network; using PeakSafeOptimizer.Config; using PeakSafeOptimizer.Diagnostics; using PeakSafeOptimizer.Graphics; using PeakSafeOptimizer.Infrastructure; using PeakSafeOptimizer.Patches.Scale; using Photon.Pun; using UnityEngine; using UnityEngine.Animations.Rigging; using UnityEngine.Playables; using UnityEngine.SceneManagement; using Zorro.Core; using Zorro.Core.Serizalization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PeakSafeOptimizer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+2651244b36adcdccf970b931a35bed725d4c6566")] [assembly: AssemblyProduct("PeakSafeOptimizer")] [assembly: AssemblyTitle("PeakSafeOptimizer")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PeakSafeOptimizer { internal sealed class CollisionCallbackReuse { private readonly ManualLogSource _log; private bool _applied; private bool _originalValue; private bool _hasOriginalValue; private bool _loggedBlocked; internal CollisionCallbackReuse(ManualLogSource log) { _log = log; } internal void Evaluate(PatchInstaller installer) { ConfigEntry<bool> collisionCallbackReuse = OptimizerConfig.CollisionCallbackReuse; bool flag = collisionCallbackReuse != null && collisionCallbackReuse.Value && installer != null && installer.IsInstalled(PatchId.SnowballContactSnapshot) && installer.IsInstalled(PatchId.SnowballContactConsume); if (flag == _applied) { if (!flag && !_loggedBlocked) { ConfigEntry<bool> collisionCallbackReuse2 = OptimizerConfig.CollisionCallbackReuse; if (collisionCallbackReuse2 != null && collisionCallbackReuse2.Value) { LogBlocked(installer); } } return; } _loggedBlocked = false; try { if (flag) { if (!_hasOriginalValue) { _originalValue = Physics.reuseCollisionCallbacks; _hasOriginalValue = true; } Physics.reuseCollisionCallbacks = true; _applied = true; ManualLogSource log = _log; if (log != null) { log.LogInfo((object)("PeakSafeOptimizer | Physics.reuseCollisionCallbacks = true " + $"(was {_originalValue}); the Snowball cross-frame collision reference is guarded.")); } } else { Restore("guard unavailable"); } } catch (Exception ex) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogError((object)("Collision callback reuse toggle failed safely: " + ex.GetType().Name + ": " + ex.Message)); } } } internal void Shutdown() { if (_applied) { Restore("shutdown"); } } private void Restore(string reason) { _applied = false; if (!_hasOriginalValue) { return; } try { Physics.reuseCollisionCallbacks = _originalValue; ManualLogSource log = _log; if (log != null) { log.LogInfo((object)$"PeakSafeOptimizer | Physics.reuseCollisionCallbacks restored to {_originalValue} ({reason})."); } } catch (Exception ex) { ManualLogSource log2 = _log; if (log2 != null) { log2.LogError((object)("Collision callback reuse restore failed safely: " + ex.GetType().Name + ": " + ex.Message)); } } } private void LogBlocked(PatchInstaller installer) { _loggedBlocked = true; bool flag = installer?.IsInstalled(PatchId.SnowballContactSnapshot) ?? false; bool flag2 = installer?.IsInstalled(PatchId.SnowballContactConsume) ?? false; ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("PeakSafeOptimizer | CollisionCallbackReuse stays off: it needs both Snowball guards " + $"(SnowballContactSnapshot installed={flag}, SnowballContactConsume installed={flag2}).")); } } } [BepInPlugin("com.peak.safeoptimizer", "PeakSafeOptimizer", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.peak.safeoptimizer"; public const string PluginName = "PeakSafeOptimizer"; public const string PluginVersion = "1.0.0"; private Harmony _harmony; private LifecycleRegistry _lifecycle; private OptimizerConfig _settings; private PatchInstaller _installer; private BoneWeightCap _boneWeightCap; private CollisionCallbackReuse _collisionReuse; private int _mainThreadId; private readonly ConcurrentQueue<PatchId> _pendingSettingChanges = new ConcurrentQueue<PatchId>(); private void Awake() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown try { _mainThreadId = Thread.CurrentThread.ManagedThreadId; _settings = OptimizerConfig.Bind(((BaseUnityPlugin)this).Config); RateLimitedDiagnostics.Initialize(((BaseUnityPlugin)this).Logger, _settings.DetailedDiagnostics); _lifecycle = new LifecycleRegistry(((BaseUnityPlugin)this).Logger); _lifecycle.Register(RateLimitedDiagnostics.Reset); BuildFingerprint buildFingerprint = BuildFingerprint.Capture(); ((BaseUnityPlugin)this).Logger.LogInfo((object)buildFingerprint.ToDiagnosticString()); _harmony = new Harmony("com.peak.safeoptimizer"); _installer = new PatchInstaller(_harmony, buildFingerprint, ((BaseUnityPlugin)this).Logger); PatchCatalogSnapshot catalog = PatchCatalog.Discover(typeof(Plugin).Assembly, _settings, _lifecycle, ((BaseUnityPlugin)this).Logger); foreach (string item in _installer.Install(catalog).FormatReport()) { ((BaseUnityPlugin)this).Logger.LogInfo((object)item); } _boneWeightCap = new BoneWeightCap(((BaseUnityPlugin)this).Logger); _collisionReuse = new CollisionCallbackReuse(((BaseUnityPlugin)this).Logger); _collisionReuse.Evaluate(_installer); ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Plugin startup failed safely; no failure will escape Awake. {arg}"); RollbackAfterFailedStartup(); } } private void RollbackAfterFailedStartup() { try { ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Startup rollback: unsubscribe SettingChanged failed safely: " + ex.GetType().Name + ": " + ex.Message)); } if (UninstallAll("Startup rollback")) { ShutdownGlobalLanes(); DisposeLifecycle("Startup rollback"); _lifecycle = null; _harmony = null; _installer = null; _settings = null; ((BaseUnityPlugin)this).Logger.LogWarning((object)"PeakSafeOptimizer | startup rolled back: all known patches were removed."); } else { ((BaseUnityPlugin)this).Logger.LogError((object)"PeakSafeOptimizer | startup rollback left one or more patches attached; their state was retained rather than reset underneath live Harmony methods."); } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { try { if (((args != null) ? args.ChangedSetting : null) == null || _settings == null || !_settings.TryGetPatchIds(args.ChangedSetting, out var ids)) { return; } bool flag = Thread.CurrentThread.ManagedThreadId != _mainThreadId; for (int i = 0; i < ids.Count; i++) { if (flag) { _pendingSettingChanges.Enqueue(ids[i]); } else { ApplySettingChange(ids[i]); } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("HotReload failed safely: " + ex.GetType().Name + ": " + ex.Message)); } } private void Update() { PatchId result; while (_pendingSettingChanges.TryDequeue(out result)) { ApplySettingChange(result); } _boneWeightCap?.Update(Time.unscaledDeltaTime); _collisionReuse?.Evaluate(_installer); } private void ApplySettingChange(PatchId id) { if (_settings == null || _installer == null) { return; } bool flag = _settings.IsEnabled(id); PatchStatus patchStatus = _installer.Toggle(id, flag); PatchStatusEntry patchStatusEntry = ((patchStatus.Entries.Count > 0) ? patchStatus.Entries[0] : null); if (patchStatusEntry != null) { switch (patchStatusEntry.Outcome) { case PatchOutcome.Applied: ((BaseUnityPlugin)this).Logger.LogInfo((object)(flag ? $"HotReload: {id} enabled→installed" : $"HotReload: {id} disabled→uninstalled")); break; case PatchOutcome.Skipped: ((BaseUnityPlugin)this).Logger.LogInfo((object)(flag ? $"HotReload: {id} enabled→{patchStatusEntry.Result}: {patchStatusEntry.Reason}" : $"HotReload: {id} disabled→{patchStatusEntry.Result}: {patchStatusEntry.Reason}")); break; case PatchOutcome.Failed: ((BaseUnityPlugin)this).Logger.LogError((object)$"HotReload: {id} {patchStatusEntry.Result}: {patchStatusEntry.Reason}"); break; } } } private void OnDestroy() { try { ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Unsubscribe SettingChanged failed: {arg}"); } ShutdownGlobalLanes(); if (UninstallAll("Shutdown")) { DisposeLifecycle("Shutdown"); _lifecycle = null; _harmony = null; _installer = null; _settings = null; } else { ((BaseUnityPlugin)this).Logger.LogError((object)"PeakSafeOptimizer shutdown left one or more patches attached; state was retained to keep those methods safe until process exit."); } } private bool UninstallAll(string phase) { if (_installer == null) { return true; } try { foreach (PatchStatusEntry entry in _installer.UninstallAll().Entries) { if (entry.Outcome == PatchOutcome.Failed) { ((BaseUnityPlugin)this).Logger.LogError((object)$"{phase}: {entry.Name} {entry.Result}: {entry.Reason}"); } } return !_installer.HasInstalledPatches; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)(phase + ": verified uninstall failed safely: " + ex.GetType().Name + ": " + ex.Message)); return false; } } private void ShutdownGlobalLanes() { try { _collisionReuse?.Shutdown(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Collision reuse shutdown failed safely: " + ex.GetType().Name + ": " + ex.Message)); } _collisionReuse = null; try { _boneWeightCap?.Shutdown(); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Bone weight cap shutdown failed safely: " + ex2.GetType().Name + ": " + ex2.Message)); } _boneWeightCap = null; } private void DisposeLifecycle(string phase) { try { _lifecycle?.Dispose(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)(phase + ": lifecycle dispose failed safely: " + ex.GetType().Name + ": " + ex.Message)); } } } } namespace PeakSafeOptimizer.Patches.Stability { internal sealed class EmoteWheelGuardModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.EmoteWheelGuard, () => new PatchDefinition(PatchId.EmoteWheelGuard, EmoteWheelGuardPatch.Initialize, EmoteWheelGuardPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(EmoteWheelGuardPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, EmoteWheelGuardPatch.Reset)); } } internal static class EmoteWheelGuardPatch { internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo field = typeof(Character).GetField("localCharacter", BindingFlags.Static | BindingFlags.Public); if (field == null || !field.IsStatic || field.FieldType != typeof(Character)) { throw new InvalidOperationException("Character.localCharacter failed structural self-check"); } StabilityPatchValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); StabilityPatchValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "stats", typeof(CharacterStats)); } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(GUIManager), "UpdateEmoteWheel", typeof(void), Type.EmptyTypes, requirePublic: false); } internal static void Reset() { } internal static bool Prefix() { if (Object.op_Implicit((Object)(object)Character.localCharacter)) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter.data != (Object)null && localCharacter.refs != null && (Object)(object)localCharacter.refs.stats != (Object)null) { return true; } RateLimitedDiagnostics.Hit("EmoteWheelGuard.localCharacter-members-unavailable"); return false; } RateLimitedDiagnostics.Hit("EmoteWheelGuard.localCharacter-unavailable"); return false; } } internal sealed class IKItemGuardModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.IKItemGuard, () => new PatchDefinition(PatchId.IKItemGuard, IKItemGuardPatch.Initialize, IKItemGuardPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(IKItemGuardPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, IKItemGuardPatch.Reset)); } } internal static class IKItemGuardPatch { private static FieldRef<CharacterAnimations, Character> _character; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = StabilityPatchValidation.RequireInstanceField(typeof(CharacterAnimations), "character", typeof(Character)); if (fieldInfo.IsPublic) { throw new InvalidOperationException("CharacterAnimations.character is no longer a private instance field"); } StabilityPatchValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "IKHandTargetLeft", typeof(Transform)); StabilityPatchValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); StabilityPatchValidation.RequireInstanceProperty(typeof(CharacterData), "currentItem", typeof(Item)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "IKHandTargetRight", typeof(Transform)); _character = AccessTools.FieldRefAccess<CharacterAnimations, Character>(fieldInfo) ?? throw new InvalidOperationException("IKItemGuard accessor creation failed"); } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterAnimations), "ConfigureIK", typeof(void), Type.EmptyTypes); } internal static void Reset() { _character = null; } internal static bool Prefix(CharacterAnimations __instance) { FieldRef<CharacterAnimations, Character> character = _character; if (character == null) { RateLimitedDiagnostics.Hit("IKItemGuard.accessors-unavailable"); return true; } Character val = character.Invoke(__instance); if ((Object)(object)val == (Object)null || val.refs == null || (Object)(object)val.data == (Object)null) { return true; } if ((Object)(object)val.refs.IKHandTargetLeft == (Object)null) { return true; } Item currentItem = val.data.currentItem; if ((Object)(object)currentItem == (Object)null) { return true; } Transform val2 = ((Component)currentItem).transform.Find("Hand_R"); Transform val3 = ((Component)currentItem).transform.Find("Hand_L"); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { RateLimitedDiagnostics.Hit("IKItemGuard.hand-node-missing"); return false; } return true; } } internal static class ParachutePatch { private static FieldRef<CharacterData, Character> _character; private static FieldRef<CharacterBackpackHandler, Character> _handlerCharacter; internal static void Initialize() { FieldInfo fieldInfo = StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "character", typeof(Character)); FieldInfo fieldInfo2 = StabilityPatchValidation.RequireInstanceField(typeof(CharacterBackpackHandler), "character", typeof(Character)); ValidateCharacterStructure(); ValidateCharacterDataStructure(); ValidateInventoryStructure(); ValidateBackpackStructure(); FieldRef<CharacterData, Character> obj = AccessTools.FieldRefAccess<CharacterData, Character>(fieldInfo); FieldRef<CharacterBackpackHandler, Character> val = AccessTools.FieldRefAccess<CharacterBackpackHandler, Character>(fieldInfo2); if (obj == null || val == null) { throw new InvalidOperationException("Parachute FieldRef accessor creation failed"); } _character = obj; _handlerCharacter = val; } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterData), "UpdateHasParachute", typeof(void), Type.EmptyTypes); } internal static void Reset() { _character = null; _handlerCharacter = null; } internal static bool Prefix(CharacterData __instance) { Character val = _character.Invoke(__instance); if ((Object)(object)val != (Object)null && val.isScoutmaster) { return false; } __instance.hasParachute = false; __instance.currentParachuteSlot = null; __instance.currentParachuteItem = null; if ((Object)(object)val == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.character-null-or-destroyed"); return false; } CharacterData data = val.data; if ((Object)(object)data == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.characterData-null-or-destroyed"); return false; } Item currentItem = data.currentItem; if ((Object)(object)currentItem != (Object)null) { GameObject gameObject = ((Component)currentItem).gameObject; if ((Object)(object)gameObject == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.held-gameObject-null-or-destroyed"); } else if (gameObject.CompareTag("Parachute")) { __instance.currentParachuteItem = currentItem; __instance.hasParachute = true; return false; } } Player player = val.player; if ((Object)(object)player == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.player-null-or-destroyed"); return false; } ItemSlot[] itemSlots = player.itemSlots; if (itemSlots == null) { RateLimitedDiagnostics.Hit("Parachute.itemSlots-null"); return false; } ItemSlot[] array = itemSlots; foreach (ItemSlot val2 in array) { if (val2 == null) { RateLimitedDiagnostics.Hit("Parachute.slot-null"); } else if (!val2.IsEmpty()) { Item prefab = val2.prefab; if ((Object)(object)prefab == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.nonempty-prefab-null-or-destroyed"); } else if ((Object)(object)((Component)prefab).gameObject == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.prefab-gameObject-null-or-destroyed"); } else if (((Component)prefab).CompareTag("Parachute")) { __instance.currentParachuteSlot = val2; __instance.hasParachute = true; return false; } } } CharacterRefs refs = val.refs; if (refs == null) { RateLimitedDiagnostics.Hit("Parachute.characterRefs-null"); return false; } CharacterBackpackHandler backpackHandler = refs.backpackHandler; if ((Object)(object)backpackHandler == (Object)null) { RateLimitedDiagnostics.Hit("Parachute.backpackHandler-null-or-destroyed"); return false; } Character val3 = _handlerCharacter.Invoke(backpackHandler); if ((Object)(object)val3 == (Object)null || (Object)(object)val3 != (Object)(object)val) { RateLimitedDiagnostics.Hit("Parachute.backpackHandler-owner-invalid"); return false; } if (player.backpackSlot == null) { RateLimitedDiagnostics.Hit("Parachute.backpackSlot-null"); return false; } BackpackOnBackVisuals activeBackpackVisuals = backpackHandler.activeBackpackVisuals; Item currentParachuteItem = default(Item); if ((Object)(object)activeBackpackVisuals != (Object)null && ((BackpackVisuals)activeBackpackVisuals).ContainsParachute(ref currentParachuteItem)) { __instance.currentParachuteItem = currentParachuteItem; __instance.hasParachute = true; } return false; } private static void ValidateCharacterStructure() { StabilityPatchValidation.RequireInstanceField(typeof(Character), "isScoutmaster", typeof(bool)); StabilityPatchValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); StabilityPatchValidation.RequireInstanceProperty(typeof(Character), "player", typeof(Player)); StabilityPatchValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); } private static void ValidateCharacterDataStructure() { StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "hasParachute", typeof(bool)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "currentParachuteSlot", typeof(ItemSlot)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "currentParachuteItem", typeof(Item)); StabilityPatchValidation.RequireInstanceProperty(typeof(CharacterData), "currentItem", typeof(Item)); } private static void ValidateInventoryStructure() { StabilityPatchValidation.RequireInstanceField(typeof(Player), "itemSlots", typeof(ItemSlot[])); StabilityPatchValidation.RequireInstanceField(typeof(Player), "backpackSlot", typeof(BackpackSlot)); StabilityPatchValidation.RequireInstanceMethod(typeof(ItemSlot), "IsEmpty", typeof(bool), Type.EmptyTypes); StabilityPatchValidation.RequireInstanceProperty(typeof(ItemSlot), "prefab", typeof(Item)); } private static void ValidateBackpackStructure() { StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "backpackHandler", typeof(CharacterBackpackHandler)); StabilityPatchValidation.RequireInstanceProperty(typeof(CharacterBackpackHandler), "activeBackpackVisuals", typeof(BackpackOnBackVisuals)); Type type = typeof(Item).MakeByRefType(); ParameterInfo parameterInfo = StabilityPatchValidation.RequireInstanceMethod(typeof(BackpackVisuals), "ContainsParachute", typeof(bool), new Type[1] { type }).GetParameters()[0]; if (!parameterInfo.IsOut || parameterInfo.IsIn) { throw new InvalidOperationException("BackpackVisuals.ContainsParachute parameter is no longer an out Item"); } } } internal sealed class RopeSegmentGuardModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.RopeSegmentGuard, () => new PatchDefinition(PatchId.RopeSegmentGuard, RopeSegmentGuardPatch.Initialize, RopeSegmentGuardPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(RopeSegmentGuardPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, RopeSegmentGuardPatch.Reset)); } } internal static class RopeSegmentGuardPatch { private static FieldRef<CharacterRopeHandling, Character> _character; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = StabilityPatchValidation.RequireInstanceField(typeof(CharacterRopeHandling), "character", typeof(Character)); if (fieldInfo.IsPublic) { throw new InvalidOperationException("CharacterRopeHandling.character is no longer a private instance field"); } StabilityPatchValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "heldRope", typeof(Rope)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "isRopeClimbing", typeof(bool)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "ropePercent", typeof(float)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "ropeClimbWorldNormal", typeof(Vector3)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "ropeClimbWorldUp", typeof(Vector3)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "ropeClimbNormal", typeof(Vector3)); StabilityPatchValidation.RequireInstanceField(typeof(Rope), "climbingAPI", typeof(RopeClimbingAPI)); StabilityPatchValidation.RequireInstanceMethod(typeof(Rope), "GetRopeSegments", typeof(List<Transform>), Type.EmptyTypes); StabilityPatchValidation.RequireInstanceMethod(typeof(RopeClimbingAPI), "GetUp", typeof(Vector3), new Type[1] { typeof(float) }); StabilityPatchValidation.RequireInstanceMethod(typeof(RopeClimbingAPI), "GetSegmentFromPercent", typeof(Transform), new Type[1] { typeof(float) }); _character = AccessTools.FieldRefAccess<CharacterRopeHandling, Character>(fieldInfo) ?? throw new InvalidOperationException("RopeSegmentGuard accessor creation failed"); } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterRopeHandling), "Climbing", typeof(void), Type.EmptyTypes, requirePublic: false); } internal static void Reset() { _character = null; } internal static bool Prefix(CharacterRopeHandling __instance) { FieldRef<CharacterRopeHandling, Character> character = _character; if (character == null) { RateLimitedDiagnostics.Hit("RopeSegmentGuard.accessors-unavailable"); return true; } Character val = character.Invoke(__instance); CharacterData val2 = (((Object)(object)val != (Object)null) ? val.data : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { RateLimitedDiagnostics.Hit("RopeSegmentGuard.character-unavailable"); return true; } Rope heldRope = val2.heldRope; if ((Object)(object)heldRope == (Object)null || (Object)(object)((MonoBehaviourPun)heldRope).photonView == (Object)null) { return true; } if ((Object)(object)heldRope.climbingAPI == (Object)null) { RateLimitedDiagnostics.Hit("RopeSegmentGuard.climbingAPI-null"); return false; } List<Transform> ropeSegments = heldRope.GetRopeSegments(); if (ropeSegments == null) { RateLimitedDiagnostics.Hit("RopeSegmentGuard.segments-null"); return false; } if (ropeSegments.Count == 0) { RateLimitedDiagnostics.Hit("RopeSegmentGuard.segments-empty"); return false; } return true; } } internal static class RunBasedValuesPatch { private static StructFieldRef<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, int>> _ints; private static StructFieldRef<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, float>> _floats; internal static void Initialize() { Type typeFromHandle = typeof(SerializableRunBasedValues); if (!typeFromHandle.IsValueType || typeFromHandle.IsEnum) { throw new InvalidOperationException("SerializableRunBasedValues is no longer a non-enum value type"); } FieldInfo fieldInfo = StabilityPatchValidation.RequireInstanceField(typeFromHandle, "runBasedInts", typeof(Dictionary<RUNBASEDVALUETYPE, int>)); FieldInfo fieldInfo2 = StabilityPatchValidation.RequireInstanceField(typeFromHandle, "runBasedFloats", typeof(Dictionary<RUNBASEDVALUETYPE, float>)); if (fieldInfo.IsInitOnly || fieldInfo2.IsInitOnly) { throw new InvalidOperationException("RunBasedValues dictionary fields are unexpectedly readonly"); } StructFieldRef<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, int>> obj = AccessTools.StructFieldRefAccess<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, int>>(fieldInfo); StructFieldRef<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, float>> val = AccessTools.StructFieldRefAccess<SerializableRunBasedValues, Dictionary<RUNBASEDVALUETYPE, float>>(fieldInfo2); if (obj == null || val == null) { throw new InvalidOperationException("RunBasedValues StructFieldRef accessor creation failed"); } _ints = obj; _floats = val; } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(SerializableRunBasedValues), "SerializeRunBasedValues", typeof(void), new Type[1] { typeof(BinarySerializer) }); } internal static void Reset() { _ints = null; _floats = null; } internal static void Prefix(ref SerializableRunBasedValues __instance) { if (_ints.Invoke(ref __instance) == null) { _ints.Invoke(ref __instance) = new Dictionary<RUNBASEDVALUETYPE, int>(); RateLimitedDiagnostics.Hit("RunBasedValues.runBasedInts-null"); } if (_floats.Invoke(ref __instance) == null) { _floats.Invoke(ref __instance) = new Dictionary<RUNBASEDVALUETYPE, float>(); RateLimitedDiagnostics.Hit("RunBasedValues.runBasedFloats-null"); } } } internal sealed class StabilityPatchModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.RunBasedValues, () => new PatchDefinition(PatchId.RunBasedValues, RunBasedValuesPatch.Initialize, RunBasedValuesPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(RunBasedValuesPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: false, RunBasedValuesPatch.Reset)); context.Register(PatchId.Parachute, () => new PatchDefinition(PatchId.Parachute, ParachutePatch.Initialize, ParachutePatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(ParachutePatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, ParachutePatch.Reset)); } } internal static class StabilityPatchValidation { private const BindingFlags DeclaredInstance = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; internal static FieldInfo RequireInstanceField(Type declaringType, string name, Type fieldType) { FieldInfo field = declaringType.GetField(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { throw new MissingFieldException(declaringType.FullName, name); } if (field.DeclaringType != declaringType || field.IsStatic || field.FieldType != fieldType) { throw new InvalidOperationException("Unexpected field structure for " + declaringType.FullName + "." + name); } return field; } internal static PropertyInfo RequireInstanceProperty(Type declaringType, string name, Type propertyType, bool requirePublicGetter = true) { PropertyInfo property = declaringType.GetProperty(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo = property?.GetGetMethod(nonPublic: true); if (property == null || property.DeclaringType != declaringType || property.PropertyType != propertyType || property.GetIndexParameters().Length != 0 || methodInfo == null || methodInfo.IsStatic || methodInfo.ContainsGenericParameters || (requirePublicGetter && !methodInfo.IsPublic)) { throw new InvalidOperationException("Unexpected property structure for " + declaringType.FullName + "." + name); } return property; } internal static MethodInfo RequireInstanceMethod(Type declaringType, string name, Type returnType, Type[] parameterTypes, bool requirePublic = true) { MethodInfo method = declaringType.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); if (method == null) { throw new MissingMethodException(declaringType.FullName, name); } if (method.DeclaringType != declaringType || method.IsStatic || method.ReturnType != returnType || method.ContainsGenericParameters || (requirePublic && !method.IsPublic)) { throw new InvalidOperationException("Unexpected method structure for " + declaringType.FullName + "." + name); } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length != parameterTypes.Length) { throw new InvalidOperationException("Unexpected parameter count for " + declaringType.FullName + "." + name); } for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType != parameterTypes[i]) { throw new InvalidOperationException($"Unexpected parameter {i} for {declaringType.FullName}.{name}"); } } return method; } } } namespace PeakSafeOptimizer.Patches.Scale { internal sealed class AnimatedMouthMaterialModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.AnimatedMouthMaterial, () => new PatchDefinition(PatchId.AnimatedMouthMaterial, AnimatedMouthMaterialPatch.Initialize, AnimatedMouthMaterialPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(AnimatedMouthMaterialPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, AnimatedMouthMaterialPatch.Reset)); } } internal static class AnimatedMouthMaterialPatch { private sealed class State { internal int LastUseTalkSprites = -1; internal int LastAmplitudeIndex = -1; } private static Func<AnimatedMouth, Object> _getAudioSource; private static FieldRef<AnimatedMouth, float[]> _lastBuffer; private static FieldRef<AnimatedMouth, PushToTalkSetting> _pushToTalkSetting; private static FieldRef<AnimatedMouth, float> _volumePeak; private static Func<AnimatedMouth, float[], float> _micLevel; private static Func<PushToTalkSetting, PushToTalkType> _getPushToTalkValue; private static ConditionalWeakTable<AnimatedMouth, State> _state; internal static void Initialize() { ResolveAndValidateTarget(); Type? typeFromHandle = typeof(AnimatedMouth); FieldInfo field = ScaleValidation.RequireInstanceFieldByTypeName(typeFromHandle, "audioSource", "UnityEngine.AudioSource"); ScaleValidation.RequireInstanceField(typeFromHandle, "isGhost", typeof(bool)); ScaleValidation.RequireInstanceField(typeFromHandle, "character", typeof(Character)); ScaleValidation.RequireInstanceField(typeFromHandle, "mouthRenderer", typeof(Renderer)); ScaleValidation.RequireInstanceField(typeFromHandle, "mouthTextures", typeof(Texture2D[])); ScaleValidation.RequireInstanceField(typeFromHandle, "amplitudeIndex", typeof(int)); ScaleValidation.RequireInstanceField(typeFromHandle, "isSpeaking", typeof(bool)); ScaleValidation.RequireInstanceField(typeFromHandle, "volume", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "amplitudePeakLimiter", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "minAmplitudeThreshold", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "amplitudeHighestDecay", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "amplitudeSmoothing", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "talkThreshold", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "amplitudeMult", typeof(float)); ScaleValidation.RequireInstanceField(typeFromHandle, "decibelToAmountCurve", typeof(AnimationCurve)); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeFromHandle, "m_lastSentLocalBuffer", typeof(float[])); FieldInfo fieldInfo2 = ScaleValidation.RequireInstanceField(typeFromHandle, "pushToTalkSetting", typeof(PushToTalkSetting)); FieldInfo fieldInfo3 = ScaleValidation.RequireInstanceField(typeFromHandle, "volumePeak", typeof(float)); ScaleValidation.RequireInstanceProperty(typeFromHandle, "NormalizedAmplitude", typeof(float)); ScaleValidation.RequireInstanceProperty(typeFromHandle, "VoiceHandler", typeof(CharacterVoiceHandler)); MethodInfo methodInfo = ScaleValidation.RequireInstanceMethod(typeFromHandle, "MicrophoneLevelMax", typeof(float), new Type[1] { typeof(float[]) }, requirePublic: false); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceField(typeof(Character), "input", typeof(CharacterInput)); ScaleValidation.RequireInstanceProperty(typeof(Character), "IsLocal", typeof(bool)); ScaleValidation.RequireInstanceProperty(typeof(CharacterData), "dead", typeof(bool)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "passedOut", typeof(bool)); ScaleValidation.RequireInstanceField(typeof(CharacterInput), "pushToTalkPressed", typeof(bool)); ScaleValidation.RequireInstanceProperty(typeof(CharacterVoiceHandler), "LastReadSquaredMax", typeof(float)); ScaleValidation.RequireInstanceProperty(typeof(CharacterVoiceHandler), "LastAudioBuffer", typeof(float[])); PropertyInfo propertyInfo = ScaleValidation.RequireInheritedInstanceProperty(typeof(PushToTalkSetting), "Value", typeof(PushToTalkType)); if (!Enum.IsDefined(typeof(PushToTalkType), (object)(PushToTalkType)1) || !Enum.IsDefined(typeof(PushToTalkType), (object)(PushToTalkType)2)) { throw new InvalidOperationException("PushToTalkType values are no longer defined"); } Func<AnimatedMouth, Object> func = ScaleEmit.CreateUnityObjectFieldGetter<AnimatedMouth>(field); FieldRef<AnimatedMouth, float[]> val = AccessTools.FieldRefAccess<AnimatedMouth, float[]>(fieldInfo); FieldRef<AnimatedMouth, PushToTalkSetting> val2 = AccessTools.FieldRefAccess<AnimatedMouth, PushToTalkSetting>(fieldInfo2); FieldRef<AnimatedMouth, float> val3 = AccessTools.FieldRefAccess<AnimatedMouth, float>(fieldInfo3); Func<AnimatedMouth, float[], float> func2 = (Func<AnimatedMouth, float[], float>)methodInfo.CreateDelegate(typeof(Func<AnimatedMouth, float[], float>)); Func<PushToTalkSetting, PushToTalkType> func3 = EmitPushToTalkValueGetter(propertyInfo.GetGetMethod(nonPublic: true)); if (func == null || val == null || val2 == null || val3 == null || func2 == null || func3 == null) { throw new InvalidOperationException("AnimatedMouthMaterial accessor creation failed"); } _getAudioSource = func; _lastBuffer = val; _pushToTalkSetting = val2; _volumePeak = val3; _micLevel = func2; _getPushToTalkValue = func3; _state = new ConditionalWeakTable<AnimatedMouth, State>(); } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(AnimatedMouth), "ProcessMicData", typeof(void), new Type[1] { typeof(float[]) }, requirePublic: false); } internal static void Reset() { _getAudioSource = null; _lastBuffer = null; _pushToTalkSetting = null; _volumePeak = null; _micLevel = null; _getPushToTalkValue = null; _state = null; } private static Func<PushToTalkSetting, PushToTalkType> EmitPushToTalkValueGetter(MethodInfo getter) { DynamicMethod dynamicMethod = new DynamicMethod("PSO_GetPushToTalkValue", typeof(PushToTalkType), new Type[1] { typeof(PushToTalkSetting) }, typeof(AnimatedMouthMaterialPatch).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, getter.DeclaringType); iLGenerator.Emit(OpCodes.Callvirt, getter); iLGenerator.Emit(OpCodes.Ret); return (Func<PushToTalkSetting, PushToTalkType>)dynamicMethod.CreateDelegate(typeof(Func<PushToTalkSetting, PushToTalkType>)); } internal static bool Prefix(AnimatedMouth __instance, float[] buffer) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Invalid comparison between Unknown and I4 //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Invalid comparison between Unknown and I4 Func<AnimatedMouth, Object> getAudioSource = _getAudioSource; FieldRef<AnimatedMouth, float[]> lastBuffer = _lastBuffer; FieldRef<AnimatedMouth, PushToTalkSetting> pushToTalkSetting = _pushToTalkSetting; FieldRef<AnimatedMouth, float> volumePeak = _volumePeak; Func<AnimatedMouth, float[], float> micLevel = _micLevel; Func<PushToTalkSetting, PushToTalkType> getPushToTalkValue = _getPushToTalkValue; ConditionalWeakTable<AnimatedMouth, State> state = _state; if (getAudioSource == null || lastBuffer == null || pushToTalkSetting == null || volumePeak == null || micLevel == null || getPushToTalkValue == null || state == null) { RateLimitedDiagnostics.Hit("AnimatedMouthMaterial.accessors-unavailable"); return true; } Renderer mouthRenderer = __instance.mouthRenderer; if ((Object)(object)mouthRenderer == (Object)null) { RateLimitedDiagnostics.Hit("AnimatedMouthMaterial.mouthRenderer-null"); return true; } Texture2D[] mouthTextures = __instance.mouthTextures; if (mouthTextures == null || mouthTextures.Length == 0) { RateLimitedDiagnostics.Hit("AnimatedMouthMaterial.mouthTextures-empty"); return true; } Character character = __instance.character; if ((Object)(object)character == (Object)null) { RateLimitedDiagnostics.Hit("AnimatedMouthMaterial.character-null"); return true; } if (getAudioSource(__instance) == (Object)null) { return false; } if (!__instance.isGhost && (character.data.dead || character.data.passedOut)) { return false; } bool isLocal = character.IsLocal; float num = ((!isLocal) ? __instance.VoiceHandler.LastReadSquaredMax : micLevel(__instance, buffer)); if (!isLocal) { lastBuffer.Invoke(__instance) = __instance.VoiceHandler.LastAudioBuffer; } float num2 = AnimatedMouth.MicrophoneLevelMaxDecibels(num); PushToTalkSetting arg = pushToTalkSetting.Invoke(__instance); PushToTalkType val = getPushToTalkValue(arg); if (isLocal && (((int)val == 1 && !character.input.pushToTalkPressed) || ((int)val == 2 && character.input.pushToTalkPressed))) { num2 = -80f; } float num3 = __instance.decibelToAmountCurve.Evaluate(num2); if (num3 > __instance.amplitudePeakLimiter) { __instance.amplitudePeakLimiter = num3; } if (__instance.amplitudePeakLimiter > __instance.minAmplitudeThreshold) { __instance.amplitudePeakLimiter -= __instance.amplitudeHighestDecay * Time.deltaTime; __instance.amplitudePeakLimiter = Mathf.Max(__instance.amplitudePeakLimiter, __instance.minAmplitudeThreshold); } __instance.volume = num3 / __instance.amplitudePeakLimiter; float num4 = volumePeak.Invoke(__instance); num4 = ((!(__instance.volume > num4)) ? Mathf.Lerp(num4, 0f, Time.deltaTime * __instance.amplitudeSmoothing) : Mathf.Lerp(num4, __instance.volume, Time.deltaTime * __instance.amplitudeSmoothing)); volumePeak.Invoke(__instance) = num4; int num5; bool isSpeaking; if (num4 > __instance.talkThreshold) { num5 = 1; isSpeaking = true; } else { isSpeaking = false; num5 = 0; } __instance.isSpeaking = isSpeaking; State value = state.GetValue(__instance, (AnimatedMouth _) => new State()); Material material = mouthRenderer.material; if (value.LastUseTalkSprites != num5 || material.GetInt("_UseTalkSprites") != num5) { material.SetInt("_UseTalkSprites", num5); value.LastUseTalkSprites = num5; } int num6 = (__instance.amplitudeIndex = (int)(__instance.NormalizedAmplitude * (float)(mouthTextures.Length - 1))); Texture2D val2 = mouthTextures[num6]; if (value.LastAmplitudeIndex != num6 || (Object)(object)material.GetTexture("_TalkSprite") != (Object)(object)val2) { material.SetTexture("_TalkSprite", (Texture)(object)val2); value.LastAmplitudeIndex = num6; } return false; } } internal sealed class AnimatorValuesHashModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.AnimatorValuesHash, () => new PatchDefinition(PatchId.AnimatorValuesHash, AnimatorValuesHashPatch.Initialize, AnimatorValuesHashPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(AnimatorValuesHashPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, AnimatorValuesHashPatch.Reset)); } } internal static class AnimatorValuesHashPatch { private static Func<AnimatorValues, Object> _getAnimator; private static FieldRef<AnimatorValues, Character> _character; private static Func<string, int> _stringToHash; private static Func<Object, int, float> _getFloat; private static Action<Object, int, float> _setFloat; private static Action<Object, int, float, float, float> _setFloatDamped; private static Func<Object, int, bool> _getBool; private static Action<Object, int, bool> _setBool; private static int _inputXHash; private static int _inputYHash; private static int _isGroundedHash; private static int _sprintHash; private static int _velocityYHash; internal static void Initialize() { ResolveAndValidateTarget(); Type? typeFromHandle = typeof(AnimatorValues); FieldInfo fieldInfo = ScaleValidation.RequireInstanceFieldByTypeName(typeFromHandle, "anim", "UnityEngine.Animator"); FieldInfo fieldInfo2 = ScaleValidation.RequireInstanceField(typeFromHandle, "character", typeof(Character)); ScaleValidation.RequireInstanceField(typeof(Character), "input", typeof(CharacterInput)); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); ScaleValidation.RequireInstanceField(typeof(CharacterInput), "movementInput", typeof(Vector2)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "isGrounded", typeof(bool)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "isSprinting", typeof(bool)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "avarageVelocity", typeof(Vector3)); ScaleValidation.RequireInstanceField(typeof(CharacterRefs), "movement", typeof(CharacterMovement)); ScaleValidation.RequireInstanceField(typeof(CharacterMovement), "sprintAnimationDisabled", typeof(bool)); Type fieldType = fieldInfo.FieldType; MethodInfo methodInfo = RequireMethod(fieldType, "StringToHash", typeof(int), true, typeof(string)); MethodInfo methodInfo2 = RequireMethod(fieldType, "GetFloat", typeof(float), false, typeof(int)); MethodInfo methodInfo3 = RequireMethod(fieldType, "SetFloat", typeof(void), false, typeof(int), typeof(float)); MethodInfo methodInfo4 = RequireMethod(fieldType, "SetFloat", typeof(void), false, typeof(int), typeof(float), typeof(float), typeof(float)); MethodInfo methodInfo5 = RequireMethod(fieldType, "GetBool", typeof(bool), false, typeof(int)); MethodInfo methodInfo6 = RequireMethod(fieldType, "SetBool", typeof(void), false, typeof(int), typeof(bool)); Func<AnimatorValues, Object> func = ScaleEmit.CreateUnityObjectFieldGetter<AnimatorValues>(fieldInfo); FieldRef<AnimatorValues, Character> val = AccessTools.FieldRefAccess<AnimatorValues, Character>(fieldInfo2); Func<string, int> func2 = (Func<string, int>)methodInfo.CreateDelegate(typeof(Func<string, int>)); Func<Object, int, float> func3 = EmitGetFloat(fieldType, methodInfo2); Action<Object, int, float> action = EmitSetFloat(fieldType, methodInfo3); Action<Object, int, float, float, float> action2 = EmitSetFloatDamped(fieldType, methodInfo4); Func<Object, int, bool> func4 = EmitGetBool(fieldType, methodInfo5); Action<Object, int, bool> action3 = EmitSetBool(fieldType, methodInfo6); if (func == null || val == null || func2 == null || func3 == null || action == null || action2 == null || func4 == null || action3 == null) { throw new InvalidOperationException("AnimatorValuesHash accessor creation failed"); } _getAnimator = func; _character = val; _stringToHash = func2; _getFloat = func3; _setFloat = action; _setFloatDamped = action2; _getBool = func4; _setBool = action3; _inputXHash = func2("Input X"); _inputYHash = func2("Input Y"); _isGroundedHash = func2("Is Grounded"); _sprintHash = func2("Sprint"); _velocityYHash = func2("Velocity Y"); } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(AnimatorValues), "Update", typeof(void), Type.EmptyTypes, requirePublic: false); } internal static void Reset() { _getAnimator = null; _character = null; _stringToHash = null; _getFloat = null; _setFloat = null; _setFloatDamped = null; _getBool = null; _setBool = null; _inputXHash = 0; _inputYHash = 0; _isGroundedHash = 0; _sprintHash = 0; _velocityYHash = 0; } internal static bool Prefix(AnimatorValues __instance) { //IL_00c2: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) Func<AnimatorValues, Object> getAnimator = _getAnimator; FieldRef<AnimatorValues, Character> character = _character; Func<Object, int, float> getFloat = _getFloat; Action<Object, int, float> setFloat = _setFloat; Action<Object, int, float, float, float> setFloatDamped = _setFloatDamped; Func<Object, int, bool> getBool = _getBool; Action<Object, int, bool> setBool = _setBool; if (getAnimator == null || character == null || _stringToHash == null || getFloat == null || setFloat == null || setFloatDamped == null || getBool == null || setBool == null) { return true; } Object val = getAnimator(__instance); Character val2 = character.Invoke(__instance); if (val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val2.input == (Object)null || (Object)(object)val2.data == (Object)null || val2.refs == null || (Object)(object)val2.refs.movement == (Object)null) { return true; } CharacterData data = val2.data; Vector2 movementInput = val2.input.movementInput; SetFloatIfChanged(val, _inputXHash, movementInput.x, getFloat, setFloat); SetFloatIfChanged(val, _inputYHash, movementInput.y, getFloat, setFloat); SetBoolIfChanged(val, _isGroundedHash, data.isGrounded, getBool, setBool); if (val2.refs.movement.sprintAnimationDisabled) { SetFloatIfChanged(val, _sprintHash, 0f, getFloat, setFloat); } else { float num = (data.isSprinting ? 1f : 0f); if (getFloat(val, _sprintHash) != num) { setFloatDamped(val, _sprintHash, num, 0.125f, Time.deltaTime); } } SetFloatIfChanged(val, _velocityYHash, data.avarageVelocity.y, getFloat, setFloat); if (data.isGrounded) { val2.refs.movement.sprintAnimationDisabled = false; } return false; } private static void SetFloatIfChanged(Object animator, int hash, float target, Func<Object, int, float> getFloat, Action<Object, int, float> setFloat) { if (getFloat(animator, hash) != target) { setFloat(animator, hash, target); } } private static void SetBoolIfChanged(Object animator, int hash, bool target, Func<Object, int, bool> getBool, Action<Object, int, bool> setBool) { if (getBool(animator, hash) != target) { setBool(animator, hash, target); } } private static MethodInfo RequireMethod(Type owner, string name, Type returnType, bool isStatic, params Type[] parameterTypes) { BindingFlags bindingAttr = (BindingFlags)(0x10 | (isStatic ? 8 : 4)); MethodInfo method = owner.GetMethod(name, bindingAttr, null, parameterTypes, null); if (method == null || method.DeclaringType != owner || method.IsStatic != isStatic || method.ReturnType != returnType || method.ContainsGenericParameters) { throw new MissingMethodException(owner.FullName, name); } return method; } private static Func<Object, int, float> EmitGetFloat(Type animatorType, MethodInfo methodInfo) { DynamicMethod dynamicMethod = NewAnimatorMethod("PSO_AnimatorGetFloat", typeof(float), typeof(int)); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); EmitAnimatorCallPrefix(iLGenerator, animatorType, 1); iLGenerator.Emit(OpCodes.Callvirt, methodInfo); iLGenerator.Emit(OpCodes.Ret); return (Func<Object, int, float>)dynamicMethod.CreateDelegate(typeof(Func<Object, int, float>)); } private static Action<Object, int, float> EmitSetFloat(Type animatorType, MethodInfo methodInfo) { DynamicMethod dynamicMethod = NewAnimatorMethod("PSO_AnimatorSetFloat", typeof(void), typeof(int), typeof(float)); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); EmitAnimatorCallPrefix(iLGenerator, animatorType, 2); iLGenerator.Emit(OpCodes.Callvirt, methodInfo); iLGenerator.Emit(OpCodes.Ret); return (Action<Object, int, float>)dynamicMethod.CreateDelegate(typeof(Action<Object, int, float>)); } private static Action<Object, int, float, float, float> EmitSetFloatDamped(Type animatorType, MethodInfo methodInfo) { DynamicMethod dynamicMethod = NewAnimatorMethod("PSO_AnimatorSetFloatDamped", typeof(void), typeof(int), typeof(float), typeof(float), typeof(float)); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); EmitAnimatorCallPrefix(iLGenerator, animatorType, 4); iLGenerator.Emit(OpCodes.Callvirt, methodInfo); iLGenerator.Emit(OpCodes.Ret); return (Action<Object, int, float, float, float>)dynamicMethod.CreateDelegate(typeof(Action<Object, int, float, float, float>)); } private static Func<Object, int, bool> EmitGetBool(Type animatorType, MethodInfo methodInfo) { DynamicMethod dynamicMethod = NewAnimatorMethod("PSO_AnimatorGetBool", typeof(bool), typeof(int)); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); EmitAnimatorCallPrefix(iLGenerator, animatorType, 1); iLGenerator.Emit(OpCodes.Callvirt, methodInfo); iLGenerator.Emit(OpCodes.Ret); return (Func<Object, int, bool>)dynamicMethod.CreateDelegate(typeof(Func<Object, int, bool>)); } private static Action<Object, int, bool> EmitSetBool(Type animatorType, MethodInfo methodInfo) { DynamicMethod dynamicMethod = NewAnimatorMethod("PSO_AnimatorSetBool", typeof(void), typeof(int), typeof(bool)); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); EmitAnimatorCallPrefix(iLGenerator, animatorType, 2); iLGenerator.Emit(OpCodes.Callvirt, methodInfo); iLGenerator.Emit(OpCodes.Ret); return (Action<Object, int, bool>)dynamicMethod.CreateDelegate(typeof(Action<Object, int, bool>)); } private static DynamicMethod NewAnimatorMethod(string name, Type returnType, params Type[] parametersAfterAnimator) { Type[] array = new Type[parametersAfterAnimator.Length + 1]; array[0] = typeof(Object); Array.Copy(parametersAfterAnimator, 0, array, 1, parametersAfterAnimator.Length); return new DynamicMethod(name, returnType, array, typeof(AnimatorValuesHashPatch).Module, skipVisibility: true); } private static void EmitAnimatorCallPrefix(ILGenerator il, Type animatorType, int argumentCount) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, animatorType); for (int i = 1; i <= argumentCount; i++) { il.Emit(OpCodes.Ldarg, i); } } } internal sealed class BarAfflictionLayoutModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.BarAfflictionLayout, () => new PatchDefinition(PatchId.BarAfflictionLayout, BarAfflictionLayoutPatch.Initialize, BarAfflictionLayoutPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(BarAfflictionLayoutPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, BarAfflictionLayoutPatch.Reset)); } } internal static class BarAfflictionLayoutPatch { private static Func<BarAffliction, Object> _getRtf; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo field = ScaleValidation.RequireInstanceFieldByTypeName(typeof(BarAffliction), "rtf", "UnityEngine.RectTransform"); ScaleValidation.RequireInstanceProperty(typeof(BarAffliction), "width", typeof(float)); ScaleValidation.RequireInstanceField(typeof(BarAffliction), "size", typeof(float)); _getRtf = ScaleEmit.CreateUnityObjectFieldGetter<BarAffliction>(field) ?? throw new InvalidOperationException("BarAfflictionLayout accessor creation failed"); } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(BarAffliction), "UpdateAffliction", typeof(void), new Type[1] { typeof(StaminaBar) }, requirePublic: true); } internal static void Reset() { _getRtf = null; } internal static bool Prefix(BarAffliction __instance) { Func<BarAffliction, Object> getRtf = _getRtf; if (getRtf == null) { RateLimitedDiagnostics.Hit("BarAfflictionLayout.accessors-unavailable"); return true; } if (getRtf(__instance) == (Object)null) { RateLimitedDiagnostics.Hit("BarAfflictionLayout.rtf-null"); return true; } float width = __instance.width; if (Mathf.Lerp(width, __instance.size, Mathf.Min(Time.deltaTime * 10f, 0.1f)) == width) { return false; } return true; } } internal sealed class BodypartDragIdentityModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.BodypartDragIdentity, () => new PatchDefinition(PatchId.BodypartDragIdentity, BodypartDragIdentityPatch.Initialize, BodypartDragIdentityPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(BodypartDragIdentityPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, BodypartDragIdentityPatch.Reset)); } } internal static class BodypartDragIdentityPatch { private const string RigidbodyTypeName = "UnityEngine.Rigidbody"; private static FieldRef<Bodypart, Character> _character; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeof(Bodypart), "character", typeof(Character)); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceProperty(typeof(CharacterData), "currentRagdollControll", typeof(float)); FieldInfo fieldInfo2 = ScaleValidation.RequireInstanceFieldByTypeName(typeof(Bodypart), "rig", "UnityEngine.Rigidbody"); ScaleValidation.RequireInstancePropertyByTypeName(fieldInfo2.FieldType, "isKinematic", typeof(bool).FullName, requireSetter: true); ScaleValidation.RequireInstancePropertyByTypeName(fieldInfo2.FieldType, "linearVelocity", "UnityEngine.Vector3", requireSetter: true); ScaleValidation.RequireInstancePropertyByTypeName(fieldInfo2.FieldType, "angularVelocity", "UnityEngine.Vector3", requireSetter: true); _character = AccessTools.FieldRefAccess<Bodypart, Character>(fieldInfo) ?? throw new InvalidOperationException("BodypartDragIdentity FieldRef creation failed"); } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(Bodypart), "Drag", typeof(void), new Type[2] { typeof(float), typeof(bool) }, requirePublic: false); } internal static void Reset() { _character = null; } internal static bool Prefix(Bodypart __instance, float drag, bool ignoreRagdoll) { FieldRef<Bodypart, Character> character = _character; if (character == null || (Object)(object)__instance == (Object)null) { return true; } float num = drag; if (!ignoreRagdoll) { Character val = character.Invoke(__instance); CharacterData val2 = (((Object)(object)val != (Object)null) ? val.data : null); if ((Object)(object)val2 == (Object)null) { return true; } num = Mathf.Lerp(1f, drag, val2.currentRagdollControll); } return num != 1f; } } internal sealed class BodypartMovementForceIdentityModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.BodypartMovementForceIdentity, () => new PatchDefinition(PatchId.BodypartMovementForceIdentity, BodypartMovementForceIdentityPatch.Initialize, BodypartMovementForceIdentityPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(BodypartMovementForceIdentityPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, BodypartMovementForceIdentityPatch.Reset)); } } internal static class BodypartMovementForceIdentityPatch { private static FieldRef<Bodypart, Character> _character; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeof(Bodypart), "character", typeof(Character)); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "worldMovementInput_Lerp", typeof(Vector3)); ScaleValidation.RequireInstanceMethod(typeof(Bodypart), "AddForce", typeof(void), new Type[2] { typeof(Vector3), typeof(ForceMode) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(Bodypart), "ApplyForces", typeof(void), Type.EmptyTypes, requirePublic: false); ScaleValidation.RequireInstanceField(typeof(Bodypart), "forcesToAdd", typeof(Vector3)); ScaleValidation.RequireInstanceFieldByTypeName(typeof(Bodypart), "rig", "UnityEngine.Rigidbody"); _character = AccessTools.FieldRefAccess<Bodypart, Character>(fieldInfo) ?? throw new InvalidOperationException("BodypartMovementForceIdentity FieldRef creation failed"); } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(Bodypart), "AddMovementForce", typeof(void), new Type[1] { typeof(float) }, requirePublic: false); } internal static void Reset() { _character = null; } internal static bool Prefix(Bodypart __instance, float movementForce, bool __runOriginal) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_004d: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!__runOriginal) { return false; } FieldRef<Bodypart, Character> character = _character; if (character == null || (Object)(object)__instance == (Object)null) { return true; } Character val = character.Invoke(__instance); if ((Object)(object)val == (Object)null) { return true; } CharacterData data = val.data; if ((Object)(object)data == (Object)null) { return true; } Vector3 worldMovementInput_Lerp = data.worldMovementInput_Lerp; Vector3 val2 = movementForce * worldMovementInput_Lerp; if (val2.x == 0f && val2.y == 0f) { return val2.z != 0f; } return true; } } internal sealed class CampfireProtectionMergeModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.CampfireProtectionMerge, () => new PatchDefinition(PatchId.CampfireProtectionMerge, CampfireProtectionMergePatch.Initialize, CampfireProtectionMergePatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(CampfireProtectionMergePatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, CampfireProtectionMergePatch.Reset)); } } internal static class CampfireProtectionMergePatch { private static FieldRef<Campfire, List<Character>> _charactersInRadius; private static FieldRef<Campfire, float> _timebuffLastApplied; private static FieldRef<Affliction_NoHunger> _campfireBuffGetter; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeof(Campfire), "_charactersInRadius", typeof(List<Character>)); FieldInfo fieldInfo2 = ScaleValidation.RequireInstanceField(typeof(Campfire), "_timebuffLastApplied", typeof(float)); ScaleValidation.RequireInstanceField(typeof(Campfire), "moraleBoostRadius", typeof(float)); FieldInfo field = typeof(Campfire).GetField("s_CampfireBuff", BindingFlags.Static | BindingFlags.NonPublic); if (field == null || !field.IsStatic || field.FieldType != typeof(Affliction_NoHunger)) { throw new InvalidOperationException("Campfire.s_CampfireBuff failed structural self-check"); } FieldRef<Affliction_NoHunger> val = AccessTools.StaticFieldRefAccess<Affliction_NoHunger>(field); if (val == null) { throw new InvalidOperationException("Campfire.s_CampfireBuff getter creation failed"); } ScaleValidation.RequireStaticField(typeof(Character), "localCharacter", typeof(Character)); ScaleValidation.RequireStaticProperty(typeof(PlayerHandler), "Exists", typeof(bool)); ScaleValidation.RequireStaticMethod(typeof(PlayerHandler), "GetAllPlayerCharacters", typeof(List<Character>), Type.EmptyTypes, requirePublic: true); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); ScaleValidation.RequireInstanceField(typeof(CharacterRefs), "afflictions", typeof(CharacterAfflictions)); ScaleValidation.RequireInstanceProperty(typeof(CharacterData), "dead", typeof(bool)); ScaleValidation.RequireInstanceProperty(typeof(Character), "Center", typeof(Vector3)); ScaleValidation.RequireInstanceProperty(typeof(CharacterAfflictions), "canGetHungry", typeof(bool)); ScaleValidation.RequireInstanceMethod(typeof(CharacterAfflictions), "AddAffliction", typeof(void), new Type[2] { typeof(Affliction), typeof(bool) }, requirePublic: true); ScaleValidation.RequireStaticProperty(typeof(Singleton<OrbFogHandler>), "Instance", typeof(OrbFogHandler)); ScaleValidation.RequireInstanceProperty(typeof(OrbFogHandler), "PlayersAreResting", typeof(bool)); FieldRef<Campfire, List<Character>> obj = AccessTools.FieldRefAccess<Campfire, List<Character>>(fieldInfo); FieldRef<Campfire, float> val2 = AccessTools.FieldRefAccess<Campfire, float>(fieldInfo2); if (obj == null || val2 == null) { throw new InvalidOperationException("CampfireProtectionMerge accessor creation failed"); } _charactersInRadius = obj; _timebuffLastApplied = val2; _campfireBuffGetter = val; } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(Campfire), "ApplyCampfireProtection", typeof(void), Type.EmptyTypes, requirePublic: false); } internal static void Reset() { _charactersInRadius = null; _timebuffLastApplied = null; _campfireBuffGetter = null; } internal static bool Prefix(Campfire __instance) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) FieldRef<Campfire, List<Character>> charactersInRadius = _charactersInRadius; FieldRef<Campfire, float> timebuffLastApplied = _timebuffLastApplied; FieldRef<Affliction_NoHunger> campfireBuffGetter = _campfireBuffGetter; Affliction val = null; if (campfireBuffGetter != null) { val = (Affliction)(object)campfireBuffGetter.Invoke(); } if (charactersInRadius == null || timebuffLastApplied == null || val == null) { RateLimitedDiagnostics.Hit("CampfireProtectionMerge.accessors-unavailable"); return true; } List<Character> list = charactersInRadius.Invoke(__instance); if (list == null) { RateLimitedDiagnostics.Hit("CampfireProtectionMerge.charactersInRadius-null"); return true; } bool playersAreResting = true; list.Clear(); if (PlayerHandler.Exists) { List<Character> allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters == null) { RateLimitedDiagnostics.Hit("CampfireProtectionMerge.roster-null"); return true; } Vector3 position = ((Component)__instance).transform.position; float moraleBoostRadius = __instance.moraleBoostRadius; for (int i = 0; i < allPlayerCharacters.Count; i++) { Character val2 = allPlayerCharacters[i]; if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.data == (Object)null) && !val2.data.dead) { if (!(Vector3.Distance(position, val2.Center) > moraleBoostRadius)) { list.Add(val2); } else { playersAreResting = false; } } } } OrbFogHandler instance = Singleton<OrbFogHandler>.Instance; if (Object.op_Implicit((Object)(object)instance)) { instance.PlayersAreResting = playersAreResting; } Character localCharacter = Character.localCharacter; bool flag = (Object)(object)localCharacter != (Object)null && list.Contains(localCharacter); if (!PlayerHandler.Exists || flag) { if ((Object)(object)localCharacter == (Object)null || localCharacter.refs == null) { RateLimitedDiagnostics.Hit("CampfireProtectionMerge.localCharacter-null"); return false; } CharacterAfflictions afflictions = localCharacter.refs.afflictions; if ((Object)(object)afflictions == (Object)null) { RateLimitedDiagnostics.Hit("CampfireProtectionMerge.afflictions-null"); return false; } if (afflictions.canGetHungry || Time.time - timebuffLastApplied.Invoke(__instance) > 2f) { afflictions.AddAffliction(val, false); timebuffLastApplied.Invoke(__instance) = Time.time; } } return false; } } internal sealed class CollisionCharacterLookupModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.CollisionCharacterLookup, () => new PatchDefinition(PatchId.CollisionCharacterLookup, CollisionCharacterLookupPatch.Initialize, CollisionCharacterLookupPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(CollisionCharacterLookupPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, CollisionCharacterLookupPatch.Reset)); } } internal static class CollisionCharacterLookupPatch { private const string CollisionTypeName = "UnityEngine.Collision"; private const string ColliderTypeName = "UnityEngine.Collider"; private const string RigidbodyTypeName = "UnityEngine.Rigidbody"; private const string CapsuleColliderTypeName = "UnityEngine.CapsuleCollider"; private static FieldRef<CharacterMovement, Character> _character; private static Func<object, bool> _hasRigidbody; private static Func<object, Character> _tryGetCharacter; internal static void Initialize() { MethodInfo methodInfo = ResolveAndValidateTarget(); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeof(CharacterMovement), "character", typeof(Character)); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "sincePalJump", typeof(float)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "isCrouching", typeof(bool)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "sinceStandOnPlayer", typeof(float)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "lastStoodOnPlayer", typeof(Character)); Type parameterType = methodInfo.GetParameters()[0].ParameterType; if (!string.Equals(parameterType.FullName, "UnityEngine.Collision", StringComparison.Ordinal)) { throw new InvalidOperationException("CharacterMovement.StandOnPlayer collision type mismatch"); } PropertyInfo propertyInfo = ScaleValidation.RequireInstancePropertyByTypeName(parameterType, "collider", "UnityEngine.Collider", requireSetter: false); PropertyInfo propertyInfo2 = ScaleValidation.RequireInstancePropertyByTypeName(parameterType, "rigidbody", "UnityEngine.Rigidbody", requireSetter: false); Type propertyType = propertyInfo.PropertyType; Type fieldType = typeof(Dictionary<, >).MakeGenericType(propertyType, typeof(Character)); MethodInfo tryGetCharacter = ScaleValidation.RequireStaticMethod(typeof(CharacterRagdoll), "TryGetCharacterFromCollider", typeof(bool), new Type[2] { propertyType, typeof(Character).MakeByRefType() }, requirePublic: true); ScaleValidation.RequireStaticField(typeof(CharacterRagdoll), "COLLIDERS_TO_CHARACTERS", fieldType); ScaleValidation.RequireInstanceField(typeof(CharacterRagdoll), "partList", typeof(List<Bodypart>)); ScaleValidation.RequireInstanceField(typeof(CharacterRagdoll), "character", typeof(Character)); ScaleValidation.RequireInstanceMethod(typeof(CharacterRagdoll), "Start", typeof(void), Type.EmptyTypes, requirePublic: false); ScaleValidation.RequireInstanceMethod(typeof(CharacterRagdoll), "RegisterBodypartColliders", typeof(void), Type.EmptyTypes, requirePublic: false); ScaleValidation.RequireInstanceField(typeof(Bodypart), "colliders", typeof(List<RigCreatorCollider>)); MethodInfo methodInfo2 = ScaleValidation.RequireInstanceMethodByTypeNames(typeof(RigCreatorCollider), "Col", "UnityEngine.CapsuleCollider", Array.Empty<string>()); if (!propertyType.IsAssignableFrom(methodInfo2.ReturnType)) { throw new InvalidOperationException("RigCreatorCollider.Col is not a Collider"); } FieldRef<CharacterMovement, Character> obj = AccessTools.FieldRefAccess<CharacterMovement, Character>(fieldInfo); Func<object, bool> func = EmitHasRigidbody(parameterType, propertyInfo2.GetGetMethod(nonPublic: true)); Func<object, Character> func2 = EmitCharacterLookup(parameterType, propertyInfo.GetGetMethod(nonPublic: true), tryGetCharacter); if (obj == null || func == null || func2 == null) { throw new InvalidOperationException("CollisionCharacterLookup accessor creation failed"); } _character = obj; _hasRigidbody = func; _tryGetCharacter = func2; } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethodByTypeNames(typeof(CharacterMovement), "StandOnPlayer", typeof(bool).FullName, new string[1] { "UnityEngine.Collision" }); } internal static void Reset() { _character = null; _hasRigidbody = null; _tryGetCharacter = null; } internal static bool Prefix(CharacterMovement __instance, object collision, ref bool __result) { FieldRef<CharacterMovement, Character> character = _character; Func<object, bool> hasRigidbody = _hasRigidbody; Func<object, Character> tryGetCharacter = _tryGetCharacter; if (character == null || hasRigidbody == null || tryGetCharacter == null) { return true; } Character val = character.Invoke(__instance); if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null || collision == null) { return true; } CharacterData data = val.data; if (data.sincePalJump < 0.5f || data.isCrouching) { __result = false; return false; } if (!hasRigidbody(collision)) { __result = false; return false; } Character val2 = tryGetCharacter(collision); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.data == (Object)null) { return true; } if ((Object)(object)val2 == (Object)(object)val || !val2.data.isCrouching) { __result = false; return false; } data.sinceStandOnPlayer = 0f; data.lastStoodOnPlayer = val2; __result = true; return false; } private static Func<object, bool> EmitHasRigidbody(Type collisionType, MethodInfo rigidbodyGetter) { if (rigidbodyGetter == null || rigidbodyGetter.IsStatic) { throw new MissingMethodException("UnityEngine.Collision", "get_rigidbody"); } DynamicMethod dynamicMethod = new DynamicMethod("PSO_CollisionHasRigidbody", typeof(bool), new Type[1] { typeof(object) }, typeof(CollisionCharacterLookupPatch).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, collisionType); iLGenerator.Emit(OpCodes.Callvirt, rigidbodyGetter); iLGenerator.Emit(OpCodes.Ldnull); iLGenerator.Emit(OpCodes.Call, ResolveUnityObjectInequality()); iLGenerator.Emit(OpCodes.Ret); return (Func<object, bool>)dynamicMethod.CreateDelegate(typeof(Func<object, bool>)); } private static Func<object, Character> EmitCharacterLookup(Type collisionType, MethodInfo colliderGetter, MethodInfo tryGetCharacter) { if (colliderGetter == null || colliderGetter.IsStatic) { throw new MissingMethodException("UnityEngine.Collision", "get_collider"); } DynamicMethod dynamicMethod = new DynamicMethod("PSO_CollisionCharacterLookup", typeof(Character), new Type[1] { typeof(object) }, typeof(CollisionCharacterLookupPatch).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); LocalBuilder local = iLGenerator.DeclareLocal(typeof(Character)); Label label = iLGenerator.DefineLabel(); Label label2 = iLGenerator.DefineLabel(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, collisionType); iLGenerator.Emit(OpCodes.Callvirt, colliderGetter); iLGenerator.Emit(OpCodes.Dup); iLGenerator.Emit(OpCodes.Ldnull); iLGenerator.Emit(OpCodes.Call, ResolveUnityObjectInequality()); iLGenerator.Emit(OpCodes.Brfalse_S, label2); iLGenerator.Emit(OpCodes.Ldloca_S, local); iLGenerator.Emit(OpCodes.Call, tryGetCharacter); iLGenerator.Emit(OpCodes.Brtrue_S, label); iLGenerator.Emit(OpCodes.Ldnull); iLGenerator.Emit(OpCodes.Ret); iLGenerator.MarkLabel(label2); iLGenerator.Emit(OpCodes.Pop); iLGenerator.Emit(OpCodes.Ldnull); iLGenerator.Emit(OpCodes.Ret); iLGenerator.MarkLabel(label); iLGenerator.Emit(OpCodes.Ldloc, local); iLGenerator.Emit(OpCodes.Ret); return (Func<object, Character>)dynamicMethod.CreateDelegate(typeof(Func<object, Character>)); } private static MethodInfo ResolveUnityObjectInequality() { MethodInfo method = typeof(Object).GetMethod("op_Inequality", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Object), typeof(Object) }, null); if (method == null || method.ReturnType != typeof(bool)) { throw new MissingMethodException("UnityEngine.Object", "op_Inequality"); } return method; } } internal sealed class CollisionContactsNoAllocModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.CollisionContactsNoAlloc, () => new PatchDefinition(PatchId.CollisionContactsNoAlloc, CollisionContactsNoAllocPatch.Initialize, CollisionContactsNoAllocPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(CollisionContactsNoAllocPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, CollisionContactsNoAllocPatch.Reset)); } } internal static class CollisionContactsNoAllocPatch { private const string RocketRpcName = "RocketExplodeRPC"; private static FieldRef<CharacterMovement, Character> _character; private static FieldRef<CharacterMovement, bool> _rocketActive; private static FieldRef<CharacterMovement, float> _currentRocketTime; private static Func<CharacterMovement, Collision, bool> _standOnPlayer; private static Func<CharacterMovement, Rigidbody, bool> _standableRig; private static Func<CharacterMovement, bool> _doGroundChecks; private static Func<CharacterMovement, float, bool> _acceptableAngle; private static Func<CollisionModifier, Character, bool> _canStand; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeof(CharacterMovement), "character", typeof(Character)); FieldInfo fieldInfo2 = ScaleValidation.RequireInstanceField(typeof(CharacterMovement), "rocketActive", typeof(bool)); FieldInfo fieldInfo3 = ScaleValidation.RequireInstanceField(typeof(CharacterMovement), "_currentRocketTime", typeof(float)); MethodInfo methodInfo = ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "StandOnPlayer", typeof(bool), new Type[1] { typeof(Collision) }, requirePublic: false); MethodInfo methodInfo2 = ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "StandableRig", typeof(bool), new Type[1] { typeof(Rigidbody) }, requirePublic: false); MethodInfo methodInfo3 = ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "DoGroundChecks", typeof(bool), Type.EmptyTypes, requirePublic: false); MethodInfo methodInfo4 = ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "AcceptableAngle", typeof(bool), new Type[1] { typeof(float) }, requirePublic: false); MethodInfo methodInfo5 = ScaleValidation.RequireInstanceMethod(typeof(CollisionModifier), "CanStand", typeof(bool), new Type[1] { typeof(Character) }, requirePublic: false); ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "AddGroundSample", typeof(void), new Type[1] { typeof(PlayerGroundSample) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "AddGroundSample_All", typeof(void), new Type[1] { typeof(PlayerGroundSample) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(CollisionModifier), "Collide", typeof(void), new Type[4] { typeof(Character), typeof(ContactPoint), typeof(Collision), typeof(Bodypart) }, requirePublic: true); ScaleValidation.RequireInstanceField(typeof(CollisionModifier), "standable", typeof(bool)); ScaleValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); ScaleValidation.RequireInstanceField(typeof(CharacterRefs), "view", typeof(PhotonView)); ScaleValidation.RequireInstanceProperty(typeof(Character), "IsLocal", typeof(bool)); RequireRocketRpc(); RequireGroundSampleShape(); FieldRef<CharacterMovement, Character> obj = AccessTools.FieldRefAccess<CharacterMovement, Character>(fieldInfo); FieldRef<CharacterMovement, bool> val = AccessTools.FieldRefAccess<CharacterMovement, bool>(fieldInfo2); FieldRef<CharacterMovement, float> val2 = AccessTools.FieldRefAccess<CharacterMovement, float>(fieldInfo3); Func<CharacterMovement, Collision, bool> func = (Func<CharacterMovement, Collision, bool>)methodInfo.CreateDelegate(typeof(Func<CharacterMovement, Collision, bool>)); Func<CharacterMovement, Rigidbody, bool> func2 = (Func<CharacterMovement, Rigidbody, bool>)methodInfo2.CreateDelegate(typeof(Func<CharacterMovement, Rigidbody, bool>)); Func<CharacterMovement, bool> func3 = (Func<CharacterMovement, bool>)methodInfo3.CreateDelegate(typeof(Func<CharacterMovement, bool>)); Func<CharacterMovement, float, bool> func4 = (Func<CharacterMovement, float, bool>)methodInfo4.CreateDelegate(typeof(Func<CharacterMovement, float, bool>)); Func<CollisionModifier, Character, bool> func5 = (Func<CollisionModifier, Character, bool>)methodInfo5.CreateDelegate(typeof(Func<CollisionModifier, Character, bool>)); if (obj == null || val == null || val2 == null || func == null || func2 == null || func3 == null || func4 == null || func5 == null) { throw new InvalidOperationException("CollisionContactsNoAlloc accessor creation failed"); } _character = obj; _rocketActive = val; _currentRocketTime = val2; _standOnPlayer = func; _standableRig = func2; _doGroundChecks = func3; _acceptableAngle = func4; _canStand = func5; } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(CharacterMovement), "OnCollision", typeof(void), new Type[3] { typeof(Collision), typeof(bool), typeof(Bodypart) }, requirePublic: false); } internal static void Reset() { _character = null; _rocketActive = null; _currentRocketTime = null; _standOnPlayer = null; _standableRig = null; _doGroundChecks = null; _acceptableAngle = null; _canStand = null; } internal static bool Prefix(CharacterMovement __instance, Collision collision, bool collisionEnter, Bodypart bodypart) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) FieldRef<CharacterMovement, Character> character = _character; Func<CharacterMovement, Collision, bool> standOnPlayer = _standOnPlayer; Func<CharacterMovement, Rigidbody, bool> standableRig = _standableRig; Func<CharacterMovement, bool> doGroundChecks = _doGroundChecks; Func<CharacterMovement, float, bool> acceptableAngle = _acceptableAngle; Func<CollisionModifier, Character, bool> canStand = _canStand; if (character == null || standOnPlayer == null || standableRig == null || doGroundChecks == null || acceptableAngle == null || canStand == null || (Object)(object)__instance == (Object)null || collision == null) { return true; } Character val = character.Invoke(__instance); if ((Object)(object)val == (Object)null) { return true; } Collider collider = collision.collider; if ((Object)(object)collider == (Object)null) { return true; } if (collision.contactCount <= 0) { return true; } ContactPoint contact = collision.GetContact(0); CollisionModifier component = ((Component)collider).GetComponent<CollisionModifier>(); if ((Object)(object)component != (Object)null) { component.Collide(val, contact, collision, bodypart); if (!component.standable || !canStand(component, val)) { return false; } } bool flag = false; if (standOnPlayer(__instance, collision)) { flag = true; } else if (!standableRig(__instance, collision.rigidbody)) { return false; } if (_rocketActive.Invoke(__instance) && _currentRocketTime.Invoke(__instance) > 1f && val.IsLocal) { PhotonView val2 = val.refs?.view; if ((Object)(object)val2 == (Object)null) { RateLimitedDiagnostics.Hit("CollisionContactsNoAlloc.rocket-view-unavailable"); return true; } val2.RPC("RocketExplodeRPC", (RpcTarget)0, Array.Empty<object>()); _rocketActive.Invoke(__instance) = false; } float arg = Vector3.Angle(Vector3.up, ((ContactPoint)(ref contact)).normal); if (doGroundChecks(__instance)) { if (acceptableAngle(__instance, arg) || flag) { __instance.AddGroundSample(new PlayerGroundSample(((ContactPoint)(ref contact)).point, ((ContactPoint)(ref contact)).normal)); } __instance.AddGroundSample_All(new PlayerGroundSample(((ContactPoint)(ref contact)).point, ((ContactPoint)(ref contact)).normal)); } return false; } private static void RequireRocketRpc() { MethodInfo method = typeof(CharacterMovement).GetMethod("RocketExplodeRPC", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null || method.ReturnType != typeof(void) || method.GetParameters().Length != 0) { throw new MissingMethodException(typeof(CharacterMovement).FullName, "RocketExplodeRPC"); } if (((MemberInfo)method).GetCustomAttribute<PunRPC>() == null) { throw new InvalidOperationException("CharacterMovement.RocketExplodeRPC is no longer a PunRPC"); } } private static void RequireGroundSampleShape() { Type typeFromHandle = typeof(PlayerGroundSample); if (!typeFromHandle.IsValueType) { throw new InvalidOperationException("PlayerGroundSample is no longer a struct"); } if (typeFromHandle.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { typeof(Vector3), typeof(Vector3) }, null) == null) { throw new MissingMethodException(typeFromHandle.FullName, ".ctor(Vector3, Vector3)"); } ScaleValidation.RequireInstanceField(typeFromHandle, "point", typeof(Vector3)); ScaleValidation.RequireInstanceField(typeFromHandle, "normal", typeof(Vector3)); ScaleValidation.RequireInstanceField(typeFromHandle, "IsValid", typeof(bool)); } } internal sealed class GenericOptimizerRangeModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.GenericOptimizerRange, () => new PatchDefinition(PatchId.GenericOptimizerRange, GenericOptimizerRangePatch.Initialize, GenericOptimizerRangePatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(GenericOptimizerRangePatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, GenericOptimizerRangePatch.Reset)); } } internal static class GenericOptimizerRangePatch { internal static void Initialize() { ResolveAndValidateTarget(); ScaleValidation.RequireStaticField(typeof(Character), "AllCharacters", typeof(List<Character>)); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceProperty(typeof(CharacterData), "dead", typeof(bool)); ScaleValidation.RequireInstanceProperty(typeof(Character), "Center", typeof(Vector3)); ScaleValidation.RequireInstanceField(typeof(GenericOptimizer), "rangeToDisableScripts", typeof(float)); ScaleValidation.RequireInstanceProperty(typeof(GenericOptimizer), "transform", typeof(Transform)); ScaleValidation.RequireStaticMethod(typeof(Vector3), "Distance", typeof(float), new Type[2] { typeof(Vector3), typeof(Vector3) }, requirePublic: true); } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(GenericOptimizer), "AnyCharacterWithinRange", typeof(bool), new Type[1] { typeof(float) }, requirePublic: true); } internal static void Reset() { } internal static bool Prefix(GenericOptimizer __instance, float range, ref bool __result) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if (!(range >= 0f)) { RateLimitedDiagnostics.Hit("GenericOptimizerRange.non-positive-range-fallback"); return true; } List<Character> allCharacters = Character.AllCharacters; if (allCharacters == null) { RateLimitedDiagnostics.Hit("GenericOptimizerRange.allCharacters-null"); return true; } Transform transform = ((Component)__instance).transform; if ((Object)(object)transform == (Object)null) { RateLimitedDiagnostics.Hit("GenericOptimizerRange.transform-null"); return true; } Vector3 position = transform.position; bool flag = float.IsPositiveInfinity(range); float num = range * range; if (!flag && range > 0f && (!(num > 0f) || float.IsInfinity(num))) { return true; } for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if ((Object)(object)val == (Object)null) { continue; } CharacterData data = val.data; if ((Object)(object)data == (Object)null || data.dead) { continue; } if (flag) { if (Vector3.Distance(val.Center, position) < range) { __result = true; return false; } continue; } Vector3 val2 = val.Center - position; if (((Vector3)(ref val2)).sqrMagnitude < num) { __result = true; return false; } } __result = false; return false; } } internal sealed class HeatEmissionScanModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.HeatEmissionScan, () => new PatchDefinition(PatchId.HeatEmissionScan, HeatEmissionScanPatch.Initialize, HeatEmissionScanPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(HeatEmissionScanPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, HeatEmissionScanPatch.Reset)); } } internal static class HeatEmissionScanPatch { private static FieldRef<CharacterHeatEmission, Character> _character; private static FieldRef<CharacterHeatEmission, float> _counter; private static FieldRef<CharacterAfflictions, Character> _afflictionsCharacter; private static bool _ownerShortCircuitProven; internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo fieldInfo = ScaleValidation.RequireInstanceField(typeof(CharacterHeatEmission), "character", typeof(Character)); FieldInfo fieldInfo2 = ScaleValidation.RequireInstanceField(typeof(CharacterHeatEmission), "counter", typeof(float)); ScaleValidation.RequireInstanceField(typeof(CharacterHeatEmission), "radius", typeof(float)); ScaleValidation.RequireInstanceField(typeof(CharacterHeatEmission), "heatAmount", typeof(float)); ScaleValidation.RequireInstanceField(typeof(CharacterHeatEmission), "rate", typeof(float)); ScaleValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); ScaleValidation.RequireInstanceField(typeof(Character), "data", typeof(CharacterData)); ScaleValidation.RequireInstanceField(typeof(CharacterRefs), "hip", typeof(Bodypart)); ScaleValidation.RequireInstanceField(typeof(CharacterRefs), "afflictions", typeof(CharacterAfflictions)); ScaleValidation.RequireInstanceField(typeof(CharacterData), "sinceAddedCold", typeof(float)); ScaleValidation.RequireStaticField(typeof(Character), "AllCharacters", typeof(List<Character>)); ScaleValidation.RequireInstanceProperty(typeof(Character), "Center", typeof(Vector3)); ScaleValidation.RequireInheritedInstanceProperty(typeof(Bodypart), "transform", typeof(Transform)); ScaleValidation.RequireInstanceMethod(typeof(CharacterAfflictions), "SubtractStatus", typeof(void), new Type[4] { typeof(STATUSTYPE), typeof(float), typeof(bool), typeof(bool) }, requirePublic: true); FieldRef<CharacterHeatEmission, Character> val = AccessTools.FieldRefAccess<CharacterHeatEmission, Character>(fieldInfo); FieldRef<CharacterHeatEmission, float> val2 = AccessTools.FieldRefAccess<CharacterHeatEmission, float>(fieldInfo2); if (val == null || val2 == null) { throw new InvalidOperationException("HeatEmissionScan FieldRef creation failed"); } _ownerShortCircuitProven = false; _afflictionsCharacter = null; try { FieldRef<CharacterAfflictions, Character> val3 = AccessTools.FieldRefAccess<CharacterAfflictions, Character>(ScaleValidation.RequireInstanceField(typeof(CharacterAfflictions), "character", typeof(Character))); if (val3 != null) { _afflictionsCharacter = val3; _ownerShortCircuitProven = true; } } catch (Exception) { _ownerShortCircuitProven = false; _afflictionsCharacter = null; } _character = val; _counter = val2; } internal static MethodInfo ResolveAndValidateTarget() { return ScaleValidation.RequireInstanceMethod(typeof(CharacterHeatEmission), "Update", typeof(void), Type.EmptyTypes, requirePublic: true); } internal static void Reset() { _character = null; _counter = null; _afflictionsCharacter = null; _ownerShortCircuitProven = false; } internal static bool Prefix(CharacterHeatEmission __instance) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) FieldRef<CharacterHeatEmission, Character> character = _character; FieldRef<CharacterHeatEmission, float> counter = _counter; if (character == null || counter == null) { RateLimitedDiagnostics.Hit("HeatEmissionScan.accessors-unavailable"); return true; } Character val = character.Invoke(__instance); if ((Object)(object)val == (Object)null) { RateLimitedDiagnostics.Hit("HeatEmissionScan.character-null"); return true; } CharacterRefs refs = val.refs; Bodypart val2 = refs?.hip; CharacterData data = val.data; if (refs == null || (Object)(object)val2 == (Object)null || (Object)(object)data == (Object)null) { RateLimitedDiagnostics.Hit("HeatEmissionScan.owner-refs-incomplete"); return true; } List<Character> allCharacters = Character.AllCharacters; if (allCharacters == null) { RateLimitedDiagnostics.Hit("HeatEmissionScan.allCharacters-null"); return true; } Transform transform = ((Component)__instance).transform; Transform transform2 = val2.transform; if ((Object)(object)transform == (Object)null || (Object)(object)transform2 == (Object)null) { RateLimitedDiagnostics.Hit("HeatEmissionScan.transform-null"); return true; } float radius = __instance.radius; float num = radius * radius; if (radius > 0f && (!(num > 0f) || float.IsInfinity(num))) { RateLimitedDiagnostics.Hit("HeatEmissionScan.radius-out-of-square-range"); return true; } transform.position = transform2.position; if (data.sinceAddedCold < 3f) { return false; } float num2 = counter.Invoke(__instance) + Time.deltaTime; if (num2 < __instance.rate) { counter.Invoke(__instance) = num2; return false; } counter.Invoke(__instance) = 0f; if (!(radius > 0f)) { return false; } Vector3 position = transform.position; float heatAmount = __instance.heatAmount; bool ownerShortCircuitProven = _ownerShortCircuitProven; FieldRef<CharacterAfflictions, Character> afflictionsCharacter = _afflictionsCharacter; for (int i = 0; i < allCharacters.Count; i++) { Character val3 = allCharacters[i]; if ((Object)(object)val3 == (Object)null) { continue; } Vector3 val4 = position - val3.Center; if (((Vector3)(ref val4)).sqrMagnitude < num) { CharacterAfflictions val5 = val3.refs?.afflictions; if (!((Object)(object)val5 == (Object)null) && (!ownerShortCircuitProven || afflictionsCharacter == null || !((Object)(object)afflictionsCharacter.Invoke(val5) == (Object)(object)val3) || ((MonoBehaviourPun)val3).photonView.IsMine)) { val5.SubtractStatus((STATUSTYPE)2, heatAmount, false, false); } } } return false; } } internal sealed class IsLookedAtScanModule : IPatchModule { public void Register(PatchModuleContext context) { context.Register(PatchId.IsLookedAtScan, () => new PatchDefinition(PatchId.IsLookedAtScan, IsLookedAtScanPatch.Initialize, IsLookedAtScanPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(IsLookedAtScanPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, IsLookedAtScanPatch.Reset)); } } internal static class IsLookedAtScanPatch { private static FieldRef<IsLookedAt