Decompiled source of ClimbAnything v1.0.0

Mods/ClimbAnything.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using ClimbAnything;
using HarmonyLib;
using Il2CppHexabodyVR.PlayerController;
using Il2CppHurricaneVR.Framework.Core.Grabbers;
using Il2CppHurricaneVR.Framework.Core.Player;
using Il2CppHurricaneVR.Framework.Shared;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "ClimbAnything", "1.0.0", "geom2543", null)]
[assembly: MelonGame("Kubunautilus", "BrutalistickVR")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ClimbAnything")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5698a8e264bff225c921ec548117a34cb0f64c84")]
[assembly: AssemblyProduct("ClimbAnything")]
[assembly: AssemblyTitle("ClimbAnything")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 ClimbAnything
{
	public class Core : MelonMod
	{
		private class HandState
		{
			public HVRHexaBodyHands Hand;

			public bool WasDown;

			public int Wait = -1;

			public ConfigurableJoint Anchor;
		}

		private MelonPreferences_Category _cat;

		internal static MelonPreferences_Entry<bool> Enabled;

		private MelonPreferences_Entry<float> _radius;

		private MelonPreferences_Entry<bool> _allowDynamic;

		private MelonPreferences_Entry<float> _minDynamicMass;

		private MelonPreferences_Entry<float> _breakForce;

		private MelonPreferences_Entry<bool> _verbose;

		private static readonly Dictionary<IntPtr, HandState> Hands = new Dictionary<IntPtr, HandState>();

		private static HexaBodyPlayer4 _body;

		private static Transform _rig;

		internal static bool IsAnchored(HVRHexaBodyHands h)
		{
			if ((Object)(object)h != (Object)null && Hands.TryGetValue(((Il2CppObjectBase)h).Pointer, out var value))
			{
				return (Object)(object)value.Anchor != (Object)null;
			}
			return false;
		}

		public override void OnInitializeMelon()
		{
			_cat = MelonPreferences.CreateCategory("ClimbAnything");
			Enabled = _cat.CreateEntry<bool>("Enabled", true, "Enabled", (string)null, false, false, (ValueValidator)null, (string)null);
			_radius = _cat.CreateEntry<float>("GrabRadius", 0.12f, "Grab radius (m)", "How close the hand must be to a surface for grip to catch it", false, false, (ValueValidator)null, (string)null);
			_allowDynamic = _cat.CreateEntry<bool>("AllowDynamicObjects", false, "Climb loose objects", "Also catch on non-kinematic physics objects that have no grab handle", false, false, (ValueValidator)null, (string)null);
			_minDynamicMass = _cat.CreateEntry<float>("MinDynamicMass", 40f, "Min mass of loose objects (kg)", (string)null, false, false, (ValueValidator)null, (string)null);
			_breakForce = _cat.CreateEntry<float>("BreakForce", 0f, "Grip break force (N)", "0 = never slips", false, false, (ValueValidator)null, (string)null);
			_verbose = _cat.CreateEntry<bool>("Verbose", true, "Verbose log", (string)null, false, false, (ValueValidator)null, (string)null);
			((MelonBase)this).LoggerInstance.Msg("Loaded. Grip next to any wall, ledge or ceiling to hold on.");
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			Hands.Clear();
			_body = null;
			_rig = null;
		}

		private static bool FindBody()
		{
			if ((Object)(object)_body != (Object)null && !((Il2CppObjectBase)_body).WasCollected && Object.op_Implicit((Object)(object)_body))
			{
				return true;
			}
			_body = Object.FindObjectOfType<HexaBodyPlayer4>();
			if ((Object)(object)_body == (Object)null)
			{
				return false;
			}
			_rig = (((Object)(object)((Component)_body).transform.parent != (Object)null) ? ((Component)_body).transform.parent : ((Component)_body).transform);
			Hands.Clear();
			foreach (HVRHexaBodyHands componentsInChild in ((Component)_rig).GetComponentsInChildren<HVRHexaBodyHands>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null)
				{
					Hands[((Il2CppObjectBase)componentsInChild).Pointer] = new HandState
					{
						Hand = componentsInChild
					};
				}
			}
			return true;
		}

		public override void OnUpdate()
		{
			if (!Enabled.Value || !FindBody())
			{
				return;
			}
			foreach (HandState value in Hands.Values)
			{
				try
				{
					UpdateHand(value);
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Warning("Hand update: " + ex.Message);
				}
			}
		}

		private void UpdateHand(HandState s)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			HVRHexaBodyHands hand = s.Hand;
			if ((Object)(object)hand == (Object)null || ((Il2CppObjectBase)hand).WasCollected)
			{
				return;
			}
			HVRHandGrabber grabber = hand.Grabber;
			if ((Object)(object)grabber == (Object)null)
			{
				return;
			}
			HVRController controller = grabber.Controller;
			bool flag = (Object)(object)controller != (Object)null && controller.GripButtonState.Active;
			if (flag && !s.WasDown && (Object)(object)s.Anchor == (Object)null)
			{
				s.Wait = 2;
			}
			s.WasDown = flag;
			if (!flag)
			{
				Release(s, "grip released");
			}
			else if ((Object)(object)s.Anchor != (Object)null && ((HVRGrabberBase)grabber).IsGrabbing)
			{
				Release(s, "grabbed an item");
			}
			else if (s.Wait > 0)
			{
				s.Wait--;
			}
			else if (s.Wait == 0)
			{
				s.Wait = -1;
				if (!((HVRGrabberBase)grabber).IsGrabbing && (Object)(object)((HVRGrabberBase)grabber).HoverTarget == (Object)null)
				{
					TryAnchor(s, grabber.IsLeftHand ? "L" : "R");
				}
			}
		}

		private void TryAnchor(HandState s, string side)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody rigidBody = ((HexaHandsBase)s.Hand).RigidBody;
			if ((Object)(object)rigidBody == (Object)null)
			{
				return;
			}
			Vector3 worldCenterOfMass = rigidBody.worldCenterOfMass;
			float num = _radius.Value * Mathf.Max(0.01f, _rig.lossyScale.x);
			Collider val = null;
			float num2 = float.MaxValue;
			foreach (Collider item in (Il2CppArrayBase<Collider>)(object)Physics.OverlapSphere(worldCenterOfMass, num, -1, (QueryTriggerInteraction)1))
			{
				if ((Object)(object)item == (Object)null || item.isTrigger || ((Component)item).transform.IsChildOf(_rig))
				{
					continue;
				}
				Rigidbody attachedRigidbody = item.attachedRigidbody;
				if (!((Object)(object)attachedRigidbody != (Object)null) || attachedRigidbody.isKinematic || (_allowDynamic.Value && attachedRigidbody.mass >= _minDynamicMass.Value))
				{
					MeshCollider val2 = ((Il2CppObjectBase)item).TryCast<MeshCollider>();
					Vector3 val3;
					if (!((Object)(object)val2 != (Object)null) || val2.convex)
					{
						val3 = item.ClosestPoint(worldCenterOfMass);
					}
					else
					{
						Bounds bounds = item.bounds;
						val3 = ((Bounds)(ref bounds)).ClosestPoint(worldCenterOfMass);
					}
					Vector3 val4 = val3 - worldCenterOfMass;
					float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
					if (sqrMagnitude < num2)
					{
						num2 = sqrMagnitude;
						val = item;
					}
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				ConfigurableJoint val5 = ((Component)rigidBody).gameObject.AddComponent<ConfigurableJoint>();
				Rigidbody val6 = (((Joint)val5).connectedBody = val.attachedRigidbody);
				((Joint)val5).autoConfigureConnectedAnchor = true;
				((Joint)val5).anchor = Vector3.zero;
				ConfigurableJointMotion val7 = (ConfigurableJointMotion)0;
				val5.zMotion = (ConfigurableJointMotion)0;
				ConfigurableJointMotion xMotion = (val5.yMotion = val7);
				val5.xMotion = xMotion;
				val7 = (ConfigurableJointMotion)2;
				val5.angularZMotion = (ConfigurableJointMotion)2;
				xMotion = (val5.angularYMotion = val7);
				val5.angularXMotion = xMotion;
				((Joint)val5).enableCollision = false;
				((Joint)val5).enablePreprocessing = false;
				if (_breakForce.Value > 0f)
				{
					((Joint)val5).breakForce = _breakForce.Value;
				}
				s.Anchor = val5;
				if (_verbose.Value)
				{
					((MelonBase)this).LoggerInstance.Msg($"[{side}] holding '{((Object)val).name}' ({(((Object)(object)val6 == (Object)null) ? "static" : (val6.isKinematic ? "kinematic" : "dynamic"))}) at {Mathf.Sqrt(num2):F2} m");
				}
			}
		}

		private void Release(HandState s, string why)
		{
			if (!((Object)(object)s.Anchor == (Object)null))
			{
				Object.Destroy((Object)(object)s.Anchor);
				s.Anchor = null;
				if (_verbose.Value)
				{
					((MelonBase)this).LoggerInstance.Msg("Let go: " + why);
				}
			}
		}
	}
	[HarmonyPatch(typeof(HVRHexaBodyHands), "GetHandState")]
	internal static class HandStatePatch
	{
		private static void Postfix(HVRHexaBodyHands __instance, ref HandGrabState __result)
		{
			if (Core.Enabled.Value && Core.IsAnchored(__instance))
			{
				__result = (HandGrabState)3;
			}
		}
	}
}