Decompiled source of PeakSafeOptimizer v1.4.1
plugins/PeakSafeOptimizer.dll
Decompiled a month 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 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.4.1.0")] [assembly: AssemblyInformationalVersion("1.4.1+d70691babbbc382c9a92da9dbe9dab5507a0403d")] [assembly: AssemblyProduct("PeakSafeOptimizer")] [assembly: AssemblyTitle("PeakSafeOptimizer")] [assembly: AssemblyVersion("1.4.1.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 _wrote; private bool _wroteValue; 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) { _originalValue = Physics.reuseCollisionCallbacks; _hasOriginalValue = true; Physics.reuseCollisionCallbacks = true; _wroteValue = true; _wrote = 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"); } } internal void SuspendForPatchChange() { if (_applied) { Restore("patch set changing"); } } private void Restore(string reason) { _applied = false; if (!_hasOriginalValue) { return; } try { if (_wrote && Physics.reuseCollisionCallbacks == _wroteValue) { Physics.reuseCollisionCallbacks = _originalValue; ManualLogSource log = _log; if (log != null) { log.LogInfo((object)$"PeakSafeOptimizer | Physics.reuseCollisionCallbacks restored to {_originalValue} ({reason})."); } } else { ManualLogSource log2 = _log; if (log2 != null) { log2.LogInfo((object)("PeakSafeOptimizer | Physics.reuseCollisionCallbacks left as is (" + reason + "); its current value is not the one this lane wrote.")); } } _wrote = false; _hasOriginalValue = false; } catch (Exception ex) { ManualLogSource log3 = _log; if (log3 != null) { log3.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.4.1")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.peak.safeoptimizer"; public const string PluginName = "PeakSafeOptimizer"; public const string PluginVersion = "1.4.1"; 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); _installer.SetGroupResolver(_settings.GetGroupMembers); 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)); } ShutdownGlobalLanes(); if (UninstallAll("Startup rollback")) { 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 could not account for every patch: one or more records remain, either with Harmony methods still attached or detached but with their Reset still failing. Their state was retained rather than reset underneath a possibly live Harmony method."); } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { try { if (((args != null) ? args.ChangedSetting : null) != null && _settings != null && _settings.TryGetPatchIds(args.ChangedSetting, out var ids) && ids.Count != 0) { PatchId patchId = ids[0]; if (Thread.CurrentThread.ManagedThreadId != _mainThreadId) { _pendingSettingChanges.Enqueue(patchId); } else { ApplySettingChange(patchId); } } } 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); _collisionReuse?.SuspendForPatchChange(); PatchStatus patchStatus = _installer.Toggle(id, flag); _collisionReuse?.Evaluate(_installer); PatchStatusEntry patchStatusEntry = ((patchStatus.Entries.Count > 0) ? patchStatus.Entries[0] : null); if (patchStatusEntry == null) { return; } 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; } for (int i = 1; i < patchStatus.Entries.Count; i++) { PatchStatusEntry patchStatusEntry2 = patchStatus.Entries[i]; if (patchStatusEntry2.Outcome == PatchOutcome.Failed) { ((BaseUnityPlugin)this).Logger.LogError((object)$"HotReload: {patchStatusEntry2.Name} {patchStatusEntry2.Result}: {patchStatusEntry2.Reason}"); } else { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"HotReload: {patchStatusEntry2.Name} {patchStatusEntry2.Result}: {patchStatusEntry2.Reason}"); } } } 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 could not account for every patch: one or more records remain, either with Harmony methods still attached or detached but with their Reset still failing. Their 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 static class BinocularSunGuardPatch { internal static void Initialize() { ResolveAndValidateTarget(); StabilityPatchValidation.RequireInstanceMethod(typeof(MapHandler), "GetCurrentBiome", typeof(BiomeType), Type.EmptyTypes); if (!Enum.IsDefined(typeof(BiomeType), (object)(BiomeType)6)) { throw new InvalidOperationException("Biome.BiomeType.Mesa is no longer defined"); } FieldInfo field = typeof(DayNightManager).GetField("instance", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); if (field == null || !field.IsStatic || field.DeclaringType != typeof(DayNightManager) || field.FieldType != typeof(DayNightManager)) { throw new InvalidOperationException("DayNightManager.instance failed structural self-check"); } StabilityPatchValidation.RequireInstanceField(typeof(DayNightManager), "sun", typeof(Light)); FieldInfo field2 = typeof(MainCamera).GetField("instance", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); if (field2 == null || !field2.IsStatic || field2.DeclaringType != typeof(MainCamera) || field2.FieldType != typeof(MainCamera)) { throw new InvalidOperationException("MainCamera.instance failed structural self-check"); } StabilityPatchValidation.RequireInstanceMethod(typeof(AchievementManager), "ThrowAchievement", typeof(void), new Type[1] { typeof(ACHIEVEMENTTYPE) }, requirePublic: false); FieldInfo field3 = typeof(Character).GetField("localCharacter", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); if (field3 == null || !field3.IsStatic || field3.DeclaringType != typeof(Character) || field3.FieldType != typeof(Character)) { throw new InvalidOperationException("Character.localCharacter failed structural self-check"); } StabilityPatchValidation.RequireInstanceProperty(typeof(Character), "Center", typeof(Vector3)); StabilityPatchValidation.RequireInstanceField(typeof(Character), "refs", typeof(CharacterRefs)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "ragdoll", typeof(CharacterRagdoll)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRagdoll), "partDict", typeof(Dictionary<BodypartType, Bodypart>)); PropertyInfo property = typeof(Bodypart).GetProperty("transform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo = property?.GetGetMethod(nonPublic: true); if (property == null || property.PropertyType != typeof(Transform) || property.GetIndexParameters().Length != 0 || methodInfo == null || methodInfo.IsStatic) { throw new InvalidOperationException("Bodypart.transform failed structural self-check"); } if (!Enum.IsDefined(typeof(BodypartType), (object)(BodypartType)2)) { throw new InvalidOperationException("BodypartType.Torso is no longer defined"); } } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(Action_ShowBinocularOverlay), "TestLookAtSun", typeof(void), Type.EmptyTypes, requirePublic: false); } internal static void Reset() { } internal static bool Prefix() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0049: Invalid comparison between Unknown and I4 Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return true; } MapHandler instance = Singleton<MapHandler>.Instance; if (!Object.op_Implicit((Object)(object)instance)) { RateLimitedDiagnostics.Hit("BinocularSunGuard.mapHandler-unavailable"); return false; } BiomeType currentBiome; try { currentBiome = instance.GetCurrentBiome(); } catch (Exception) { RateLimitedDiagnostics.Hit("BinocularSunGuard.biome-query-failed"); return false; } if ((int)currentBiome != 6) { return true; } DayNightManager instance2 = DayNightManager.instance; if (!Object.op_Implicit((Object)(object)instance2)) { RateLimitedDiagnostics.Hit("BinocularSunGuard.dayNightManager-unavailable"); return false; } Light sun = instance2.sun; if (!Object.op_Implicit((Object)(object)sun)) { RateLimitedDiagnostics.Hit("BinocularSunGuard.sun-unavailable"); return false; } if (sun.intensity < 5f) { return true; } if (!Object.op_Implicit((Object)(object)MainCamera.instance)) { RateLimitedDiagnostics.Hit("BinocularSunGuard.mainCamera-unavailable"); return false; } if (!TorsoIsAvailable(localCharacter)) { RateLimitedDiagnostics.Hit("BinocularSunGuard.center-unavailable"); return false; } if (!Object.op_Implicit((Object)(object)Singleton<AchievementManager>.Instance)) { RateLimitedDiagnostics.Hit("BinocularSunGuard.achievementManager-unavailable"); return false; } return true; } private static bool TorsoIsAvailable(Character local) { CharacterRagdoll val = local.refs?.ragdoll; if (!Object.op_Implicit((Object)(object)val)) { return false; } Dictionary<BodypartType, Bodypart> partDict = val.partDict; if (partDict == null || !partDict.TryGetValue((BodypartType)2, out var value) || !Object.op_Implicit((Object)(object)value)) { return false; } return Object.op_Implicit((Object)(object)value.transform); } } 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.DeclaredOnly | BindingFlags.Static | BindingFlags.Public); if (field == null || !field.IsStatic || field.DeclaringType != typeof(Character) || 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)); StabilityPatchValidation.RequireInstanceField(typeof(Character), "input", typeof(CharacterInput)); StabilityPatchValidation.RequireInstanceProperty(typeof(CharacterData), "dead", typeof(bool)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterStats), "won", typeof(bool)); StabilityPatchValidation.RequireInstanceProperty(typeof(GUIManager), "canEmote", typeof(bool), requirePublicGetter: false); StabilityPatchValidation.RequireInstanceField(typeof(CharacterInput), "emoteIsPressed", typeof(bool)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterData), "usingEmoteWheel", typeof(bool)); } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(GUIManager), "UpdateEmoteWheel", typeof(void), Type.EmptyTypes, requirePublic: false); } internal static void Reset() { } internal static bool Prefix() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { RateLimitedDiagnostics.Hit("EmoteWheelGuard.localCharacter-unavailable"); return false; } CharacterData data = localCharacter.data; if (data == null) { RateLimitedDiagnostics.Hit("EmoteWheelGuard.data-unavailable"); return false; } bool flag; if (data.dead) { flag = false; } else { CharacterRefs refs = localCharacter.refs; if (refs == null) { RateLimitedDiagnostics.Hit("EmoteWheelGuard.refs-unavailable"); return false; } CharacterStats stats = refs.stats; if (stats == null) { RateLimitedDiagnostics.Hit("EmoteWheelGuard.stats-unavailable"); return false; } flag = !stats.won; } if (flag && localCharacter.input == null) { RateLimitedDiagnostics.Hit("EmoteWheelGuard.input-unavailable"); return false; } return true; } } 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; private static Func<CharacterItems, Item, Vector3> _getItemPosLeft; private static Func<CharacterItems, Item, Quaternion> _getItemRotLeft; 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)); MethodInfo methodInfo = StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterItems), "GetItemPosLeft", typeof(Vector3), new Type[1] { typeof(Item) }, requirePublic: false); MethodInfo methodInfo2 = StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterItems), "GetItemRotLeft", typeof(Quaternion), new Type[1] { typeof(Item) }, requirePublic: false); StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterItems), "GetItemPosRight", typeof(Vector3), new Type[1] { typeof(Item) }, requirePublic: false); StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterItems), "GetItemRotRight", typeof(Quaternion), new Type[1] { typeof(Item) }, requirePublic: false); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "items", typeof(CharacterItems)); StabilityPatchValidation.RequireInstanceField(typeof(CharacterRefs), "animationItemTransform", typeof(Transform)); PropertyInfo property = typeof(Item).GetProperty("transform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo3 = property?.GetGetMethod(nonPublic: true); if (property == null || property.PropertyType != typeof(Transform) || property.GetIndexParameters().Length != 0 || methodInfo3 == null || methodInfo3.IsStatic) { throw new InvalidOperationException("Item.transform failed structural self-check"); } FieldRef<CharacterAnimations, Character> obj = AccessTools.FieldRefAccess<CharacterAnimations, Character>(fieldInfo); Func<CharacterItems, Item, Vector3> func = (Func<CharacterItems, Item, Vector3>)methodInfo.CreateDelegate(typeof(Func<CharacterItems, Item, Vector3>)); Func<CharacterItems, Item, Quaternion> func2 = (Func<CharacterItems, Item, Quaternion>)methodInfo2.CreateDelegate(typeof(Func<CharacterItems, Item, Quaternion>)); if (obj == null || func == null || func2 == null) { throw new InvalidOperationException("IKItemGuard accessor creation failed"); } _character = obj; _getItemPosLeft = func; _getItemRotLeft = func2; } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireInstanceMethod(typeof(CharacterAnimations), "ConfigureIK", typeof(void), Type.EmptyTypes); } internal static void Reset() { _character = null; _getItemPosLeft = null; _getItemRotLeft = 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; } if ((Object)(object)currentItem.transform.Find("Hand_L") == (Object)null) { RateLimitedDiagnostics.Hit("IKItemGuard.left-hand-node-missing"); return false; } if ((Object)(object)currentItem.transform.Find("Hand_R") == (Object)null) { return ReproduceLeftHandWrites(val, currentItem); } return true; } private static bool ReproduceLeftHandWrites(Character character, Item item) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Func<CharacterItems, Item, Vector3> getItemPosLeft = _getItemPosLeft; Func<CharacterItems, Item, Quaternion> getItemRotLeft = _getItemRotLeft; Transform iKHandTargetLeft = character.refs.IKHandTargetLeft; CharacterItems items = character.refs.items; Transform animationItemTransform = character.refs.animationItemTransform; if (getItemPosLeft == null || getItemRotLeft == null || (Object)(object)iKHandTargetLeft == (Object)null || (Object)(object)items == (Object)null || (Object)(object)animationItemTransform == (Object)null) { RateLimitedDiagnostics.Hit("IKItemGuard.left-hand-write-unavailable"); return false; } try { Vector3 val = getItemPosLeft(items, item); Quaternion val2 = (iKHandTargetLeft.rotation = getItemRotLeft(items, item)); iKHandTargetLeft.SetPositionAndRotation(val, val2); } catch (Exception) { RateLimitedDiagnostics.Hit("IKItemGuard.left-hand-write-failed"); return false; } RateLimitedDiagnostics.Hit("IKItemGuard.right-hand-node-missing"); return false; } } internal static class ItemOptimizerDeregisterGuardPatch { internal static void Initialize() { ResolveAndValidateTarget(); FieldInfo field = typeof(ItemOptimizationManager).GetField("ITEM_DATA_LIST", BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic); if (field == null || !field.IsStatic || !field.FieldType.IsGenericType || field.FieldType.GetGenericTypeDefinition() != typeof(Dictionary<, >) || field.FieldType.GetGenericArguments()[0] != typeof(Item)) { throw new InvalidOperationException("ItemOptimizationManager.ITEM_DATA_LIST is no longer a Dictionary keyed by Item"); } StabilityPatchValidation.RequireInstanceField(typeof(ItemOptimizer), "item", typeof(Item)); } internal static MethodInfo ResolveAndValidateTarget() { return StabilityPatchValidation.RequireStaticMethod(typeof(ItemOptimizationManager), "DeregisterItem", typeof(void), new Type[1] { typeof(Item) }); } internal static void Reset() { } internal static bool Prefix(Item item) { if (item == null) { RateLimitedDiagnostics.Hit("ItemOptimizerDeregisterGuard.item-null"); 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(); ValidateEngineMembers(); 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, bool __runOriginal) { if (!__runOriginal) { return false; } FieldRef<CharacterData, Character> character = _character; if (character == null) { RateLimitedDiagnostics.Hit("Parachute.accessors-unavailable"); return true; } 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; try { player = val.player; } catch (Exception) { RateLimitedDiagnostics.Hit("Parachute.player-lookup-failed"); return false; } if (player == null) { if (!val.isBot) { 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; } FieldRef<CharacterBackpackHandler, Character> handlerCharacter = _handlerCharacter; if (handlerCharacter == null) { RateLimitedDiagnostics.Hit("Parachute.accessors-unavailable"); return true; } 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), "isBot", 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)); StabilityPatchValidation.RequireInstanceField(typeof(BackpackSlot), "backpackType", typeof(BackpackType)); 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"); } } private static void ValidateEngineMembers() { PropertyInfo property = typeof(Item).GetProperty("gameObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo = property?.GetGetMethod(nonPublic: true); if (property == null || property.PropertyType != typeof(GameObject) || property.GetIndexParameters().Length != 0 || methodInfo == null || methodInfo.IsStatic) { throw new InvalidOperationException("Item.gameObject failed structural self-check"); } MethodInfo method = typeof(GameObject).GetMethod("CompareTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (method == null || method.IsStatic || method.ReturnType != typeof(bool)) { throw new InvalidOperationException("GameObject.CompareTag failed structural self-check"); } MethodInfo method2 = typeof(Item).GetMethod("CompareTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (method2 == null || method2.IsStatic || method2.ReturnType != typeof(bool)) { throw new InvalidOperationException("Item.CompareTag failed structural self-check"); } } } 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"); } StabilityPatchValidation.RequireInstanceProperty(typeof(AchievementManager), "runBasedValueData", typeFromHandle); 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)); context.Register(PatchId.BinocularSunGuard, () => new PatchDefinition(PatchId.BinocularSunGuard, BinocularSunGuardPatch.Initialize, BinocularSunGuardPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(BinocularSunGuardPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, BinocularSunGuardPatch.Reset)); context.Register(PatchId.ItemOptimizerDeregisterGuard, () => new PatchDefinition(PatchId.ItemOptimizerDeregisterGuard, ItemOptimizerDeregisterGuardPatch.Initialize, ItemOptimizerDeregisterGuardPatch.ResolveAndValidateTarget, () => new HarmonyMethod(typeof(ItemOptimizerDeregisterGuardPatch), "Prefix", (Type[])null), null, null, null, requireCurrentMvid: true, ItemOptimizerDeregisterGuardPatch.Reset)); } } internal static class StabilityPatchValidation { private const BindingFlags DeclaredInstance = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags DeclaredStatic = BindingFlags.DeclaredOnly | BindingFlags.Static | 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; } internal static MethodInfo RequireStaticMethod(Type declaringType, string name, Type returnType, Type[] parameterTypes, bool requirePublic = true) { MethodInfo method = declaringType.GetMethod(name, BindingFlags.DeclaredOnly | BindingFlags.Static | 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 static 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; private static int _useTalkSpritesId; private static int _talkSpriteId; 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"); } ScaleValidation.RequireStaticMethod(typeof(Shader), "PropertyToID", typeof(int), new Type[1] { typeof(string) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(Material), "GetInt", typeof(int), new Type[1] { typeof(int) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(Material), "SetInt", typeof(void), new Type[2] { typeof(int), typeof(int) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(Material), "GetTexture", typeof(Texture), new Type[1] { typeof(int) }, requirePublic: true); ScaleValidation.RequireInstanceMethod(typeof(Material), "SetTexture", typeof(void), new Type[2] { typeof(int), typeof(Texture) }, requirePublic: true); 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>(); _useTalkSpritesId = Shader.PropertyToID("_UseTalkSprites"); _talkSpriteId = Shader.PropertyToID("_TalkSprite"); } 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; _useTalkSpritesId = 0; _talkSpriteId = 0; } 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Invalid comparison between Unknown and I4 //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014b: 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; } if (getAudioSource(__instance) == (Object)null) { return false; } 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 (character == null) { return true; } if (!__instance.isGhost && (Object)(object)character != (Object)null && (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(_useTalkSpritesId) != num5) { material.SetInt(_useTalkSpritesId, 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(_talkSpriteId) != (Object)(object)val2) { material.SetTexture(_talkSpriteId, (Texture)(object)val2); value.LastAmplitudeIndex = num6; } return false; } } 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)); ScaleValidation.RequireStaticMethod(typeof(Mathf), "Approximately", typeof(bool), new Type[2] { typeof(float), typeof(float) }, requirePublic: true); ScaleValidation.RequireStaticMethod(typeof(Mathf), "Lerp", typeof(float), new Type[3] { typeof(float), typeof(float), typeof(float) }, requirePublic: true); ScaleValidation.RequireStaticMethod(typeof(Mathf), "Min", typeof(float), new Type[2] { typeof(float), typeof(float) }, requirePublic: true); _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; float size = __instance.size; int num = BitConverter.SingleToInt32Bits(width); if (size == 0f) { return num != 0; } if (Mathf.Approximately(width, size)) { return num != BitConverter.SingleToInt32Bits(size); } float value = Mathf.Lerp(width, size, Mathf.Min(Time.deltaTime * 10f, 0.1f)); return num != BitConverter.SingleToInt32Bits(value); } } 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 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