using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BetterPhysics;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
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), "Better Physics", "1.2.0", "imebruhh", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BetterPhysics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetterPhysics")]
[assembly: AssemblyTitle("BetterPhysics")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace BetterPhysics
{
public enum PhysicsQuality
{
High,
Ultra,
Insane
}
public class Core : MelonMod
{
private struct Entry
{
public Rigidbody rb;
public int origSolver;
public int origVelocity;
public float origMaxAngular;
public CollisionDetectionMode origMode;
public bool physicsApplied;
public bool modeApplied;
}
public static volatile bool PhysicsEnabled;
public static volatile bool CollisionEnabled;
public static volatile bool BodyCollisionEnabled;
public static volatile bool FingerFixEnabled;
public static PhysicsQuality Quality = PhysicsQuality.Ultra;
private const float MaxAngularSpeed = 40f;
private const float SweepInterval = 2f;
private static float _nextSweep;
private static MelonPreferences_Category _prefs;
private static MelonPreferences_Entry<bool> _physicsPref;
private static MelonPreferences_Entry<bool> _collisionPref;
private static MelonPreferences_Entry<bool> _bodyPref;
private static MelonPreferences_Entry<bool> _fingerPref;
private static MelonPreferences_Entry<int> _qualityPref;
private static bool _defaultsCaptured;
private static int _defaultIterations;
private static int _defaultVelocityIterations;
private static float _defaultMaxAngularSpeed;
private static readonly Dictionary<int, Entry> Tracked = new Dictionary<int, Entry>();
private static readonly HashSet<int> HeldNow = new HashSet<int>();
private static readonly HashSet<int> HeldPrev = new HashSet<int>();
private static readonly HashSet<int> FingerOverrideActive = new HashSet<int>();
private static int SolverIterations => Quality switch
{
PhysicsQuality.High => 12,
PhysicsQuality.Ultra => 16,
_ => 24,
};
private static int SolverVelocityIterations => Quality switch
{
PhysicsQuality.High => 4,
PhysicsQuality.Ultra => 6,
_ => 10,
};
public override void OnInitializeMelon()
{
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: 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_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
_prefs = MelonPreferences.CreateCategory("BetterPhysics");
_physicsPref = _prefs.CreateEntry<bool>("BetterPhysics", true, "Better physics enabled", (string)null, false, false, (ValueValidator)null, (string)null);
_collisionPref = _prefs.CreateEntry<bool>("BetterCollision", true, "Better collision enabled", (string)null, false, false, (ValueValidator)null, (string)null);
_bodyPref = _prefs.CreateEntry<bool>("BodyCollision", false, "Body collision enabled", (string)null, false, false, (ValueValidator)null, (string)null);
_fingerPref = _prefs.CreateEntry<bool>("FingerFix", true, "Finger anti-clip enabled", (string)null, false, false, (ValueValidator)null, (string)null);
_qualityPref = _prefs.CreateEntry<int>("Quality", 1, "Physics quality level", (string)null, false, false, (ValueValidator)null, (string)null);
PhysicsEnabled = _physicsPref.Value;
CollisionEnabled = _collisionPref.Value;
BodyCollisionEnabled = _bodyPref.Value;
FingerFixEnabled = _fingerPref.Value;
if (_qualityPref.Value >= 0 && _qualityPref.Value <= 2)
{
Quality = (PhysicsQuality)_qualityPref.Value;
}
Page obj = Page.Root.CreatePage("Better Physics", new Color(0.4f, 0.8f, 1f), 0, true);
obj.CreateBool("Better Physics", Color.green, PhysicsEnabled, (Action<bool>)delegate(bool value)
{
PhysicsEnabled = value;
_physicsPref.Value = value;
MelonPreferences.Save();
ApplyGlobals();
if (value)
{
_nextSweep = 0f;
}
else
{
RestoreAll(restorePhysics: true, restoreModes: false);
}
});
obj.CreateBool("Better Collision", Color.cyan, CollisionEnabled, (Action<bool>)delegate(bool value)
{
CollisionEnabled = value;
_collisionPref.Value = value;
MelonPreferences.Save();
if (value)
{
_nextSweep = 0f;
}
else
{
RestoreAll(restorePhysics: false, restoreModes: true);
}
});
obj.CreateBool("Better Body Collision", Color.magenta, BodyCollisionEnabled, (Action<bool>)delegate(bool value)
{
BodyCollisionEnabled = value;
_bodyPref.Value = value;
MelonPreferences.Save();
if (value)
{
_nextSweep = 0f;
}
else
{
RestoreAll(restorePhysics: false, restoreModes: true);
}
});
obj.CreateBool("Finger Fix", Color.white, FingerFixEnabled, (Action<bool>)delegate(bool value)
{
FingerFixEnabled = value;
_fingerPref.Value = value;
MelonPreferences.Save();
});
obj.CreateEnum("Quality", Color.yellow, (Enum)Quality, (Action<Enum>)delegate(Enum value)
{
if (value is PhysicsQuality physicsQuality)
{
Quality = physicsQuality;
_qualityPref.Value = (int)physicsQuality;
MelonPreferences.Save();
ApplyGlobals();
if (PhysicsEnabled)
{
_nextSweep = 0f;
}
}
});
Hooking.OnLevelLoaded += OnLevelLoaded;
Hooking.OnLevelUnloaded += OnLevelUnloaded;
((MelonBase)this).LoggerInstance.Msg($"Better Physics v1.2 loaded. Physics {(PhysicsEnabled ? "ON" : "OFF")}, collision {(CollisionEnabled ? "ON" : "OFF")}, body {(BodyCollisionEnabled ? "ON" : "OFF")}, fingers {(FingerFixEnabled ? "ON" : "OFF")}, quality {Quality}.");
}
private static void OnLevelLoaded(LevelInfo info)
{
Tracked.Clear();
HeldPrev.Clear();
HeldNow.Clear();
FingerOverrideActive.Clear();
ApplyGlobals();
_nextSweep = Time.unscaledTime + 1f;
}
private static void OnLevelUnloaded()
{
Tracked.Clear();
HeldPrev.Clear();
HeldNow.Clear();
FingerOverrideActive.Clear();
}
public override void OnUpdate()
{
if (CollisionEnabled)
{
UpdateHeldObjects();
}
UpdateFingerFix();
if ((PhysicsEnabled || CollisionEnabled) && Time.unscaledTime >= _nextSweep)
{
_nextSweep = Time.unscaledTime + 2f;
Sweep();
}
}
private static void ApplyGlobals()
{
try
{
if (!_defaultsCaptured)
{
_defaultIterations = Physics.defaultSolverIterations;
_defaultVelocityIterations = Physics.defaultSolverVelocityIterations;
_defaultMaxAngularSpeed = Physics.defaultMaxAngularSpeed;
_defaultsCaptured = true;
}
if (PhysicsEnabled)
{
Physics.defaultSolverIterations = SolverIterations;
Physics.defaultSolverVelocityIterations = SolverVelocityIterations;
Physics.defaultMaxAngularSpeed = 40f;
}
else
{
Physics.defaultSolverIterations = _defaultIterations;
Physics.defaultSolverVelocityIterations = _defaultVelocityIterations;
Physics.defaultMaxAngularSpeed = _defaultMaxAngularSpeed;
}
}
catch
{
}
}
private static void Sweep()
{
try
{
Il2CppArrayBase<Rigidbody> val = Object.FindObjectsOfType<Rigidbody>();
for (int i = 0; i < val.Length; i++)
{
Rigidbody val2 = val[i];
if (!((Object)(object)val2 == (Object)null))
{
ApplyToBody(val2, HeldPrev.Contains(((Object)val2).GetInstanceID()));
}
}
if (Tracked.Count > 1024)
{
PruneDead();
}
}
catch
{
}
ApplyToHands();
if (BodyCollisionEnabled)
{
ApplyToPlayerBody();
}
}
private static void ApplyToBody(Rigidbody rb, bool held)
{
//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_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)((Component)rb).GetComponentInParent<RigManager>() != (Object)null)
{
return;
}
int instanceID = ((Object)rb).GetInstanceID();
if (!Tracked.TryGetValue(instanceID, out var value))
{
value = new Entry
{
rb = rb,
origSolver = rb.solverIterations,
origVelocity = rb.solverVelocityIterations,
origMaxAngular = rb.maxAngularVelocity,
origMode = rb.collisionDetectionMode
};
}
if (PhysicsEnabled)
{
rb.solverIterations = SolverIterations;
rb.solverVelocityIterations = SolverVelocityIterations;
if (rb.maxAngularVelocity < 40f)
{
rb.maxAngularVelocity = 40f;
}
value.physicsApplied = true;
if (!held && !rb.isKinematic && !rb.useGravity && (Object)(object)((Component)rb).GetComponent<InteractableHost>() != (Object)null)
{
rb.useGravity = true;
}
}
if (CollisionEnabled && !rb.isKinematic)
{
CollisionDetectionMode val = (held ? ((CollisionDetectionMode)2) : (((int)value.origMode != 0) ? value.origMode : ((CollisionDetectionMode)3)));
if (rb.collisionDetectionMode != val)
{
rb.collisionDetectionMode = val;
}
value.modeApplied = true;
}
Tracked[instanceID] = value;
}
catch
{
}
}
private static void RestoreAll(bool restorePhysics, bool restoreModes)
{
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
List<int> list = new List<int>(Tracked.Keys);
for (int i = 0; i < list.Count; i++)
{
Entry value = Tracked[list[i]];
try
{
if ((Object)(object)value.rb == (Object)null)
{
Tracked.Remove(list[i]);
continue;
}
if (restorePhysics && value.physicsApplied)
{
value.rb.solverIterations = value.origSolver;
value.rb.solverVelocityIterations = value.origVelocity;
value.rb.maxAngularVelocity = value.origMaxAngular;
value.physicsApplied = false;
}
if (restoreModes && value.modeApplied)
{
if (!value.rb.isKinematic)
{
value.rb.collisionDetectionMode = value.origMode;
}
value.modeApplied = false;
}
if (!value.physicsApplied && !value.modeApplied)
{
Tracked.Remove(list[i]);
}
else
{
Tracked[list[i]] = value;
}
}
catch
{
Tracked.Remove(list[i]);
}
}
}
private static void PruneDead()
{
List<int> list = new List<int>();
foreach (KeyValuePair<int, Entry> item in Tracked)
{
try
{
if ((Object)(object)item.Value.rb == (Object)null)
{
list.Add(item.Key);
}
}
catch
{
list.Add(item.Key);
}
}
for (int i = 0; i < list.Count; i++)
{
Tracked.Remove(list[i]);
}
}
private static void ApplyToHands()
{
ApplyToRigBody(((Object)(object)Player.LeftHand != (Object)null) ? Player.LeftHand.rb : null, capSpin: false);
ApplyToRigBody(((Object)(object)Player.RightHand != (Object)null) ? Player.RightHand.rb : null, capSpin: false);
}
private static void ApplyToPlayerBody()
{
try
{
PhysicsRig physicsRig = Player.PhysicsRig;
if (!((Object)(object)physicsRig == (Object)null))
{
Il2CppArrayBase<Rigidbody> componentsInChildren = ((Component)physicsRig).GetComponentsInChildren<Rigidbody>(false);
for (int i = 0; i < componentsInChildren.Length; i++)
{
ApplyToRigBody(componentsInChildren[i], capSpin: false);
}
}
}
catch
{
}
}
private static void ApplyToRigBody(Rigidbody rb, bool capSpin)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Invalid comparison between Unknown and I4
try
{
if ((Object)(object)rb == (Object)null)
{
return;
}
int instanceID = ((Object)rb).GetInstanceID();
if (!Tracked.TryGetValue(instanceID, out var value))
{
value = new Entry
{
rb = rb,
origSolver = rb.solverIterations,
origVelocity = rb.solverVelocityIterations,
origMaxAngular = rb.maxAngularVelocity,
origMode = rb.collisionDetectionMode
};
}
if (PhysicsEnabled)
{
rb.solverIterations = SolverIterations;
rb.solverVelocityIterations = SolverVelocityIterations;
value.physicsApplied = true;
}
if (CollisionEnabled && !rb.isKinematic)
{
if ((int)rb.collisionDetectionMode != 2)
{
rb.collisionDetectionMode = (CollisionDetectionMode)2;
}
value.modeApplied = true;
}
Tracked[instanceID] = value;
}
catch
{
}
}
private static void UpdateHeldObjects()
{
HeldNow.Clear();
CollectHeld(Player.LeftHand);
CollectHeld(Player.RightHand);
foreach (int item in HeldPrev)
{
if (HeldNow.Contains(item) || !Tracked.TryGetValue(item, out var value))
{
continue;
}
try
{
if ((Object)(object)value.rb != (Object)null)
{
ApplyToBody(value.rb, held: false);
}
}
catch
{
}
}
HeldPrev.Clear();
foreach (int item2 in HeldNow)
{
HeldPrev.Add(item2);
}
}
private static void CollectHeld(Hand hand)
{
try
{
if ((Object)(object)hand == (Object)null)
{
return;
}
ConfigurableJoint joint = hand.joint;
if ((Object)(object)joint != (Object)null)
{
MarkHeld(((Joint)joint).connectedBody);
}
GameObject currentAttachedGO = hand.m_CurrentAttachedGO;
if ((Object)(object)currentAttachedGO != (Object)null)
{
InteractableHost componentInParent = currentAttachedGO.GetComponentInParent<InteractableHost>();
if ((Object)(object)componentInParent != (Object)null && componentInParent.HasRigidbody)
{
MarkHeld(componentInParent.Rb);
}
}
}
catch
{
}
}
private static void MarkHeld(Rigidbody rb)
{
try
{
if ((Object)(object)rb == (Object)null)
{
return;
}
int instanceID = ((Object)rb).GetInstanceID();
if (!HeldNow.Contains(instanceID))
{
HeldNow.Add(instanceID);
if (!HeldPrev.Contains(instanceID))
{
ApplyToBody(rb, held: true);
}
}
}
catch
{
}
}
private static void UpdateFingerFix()
{
ApplyFingerFix(Player.LeftHand);
ApplyFingerFix(Player.RightHand);
}
private static void ApplyFingerFix(Hand hand)
{
try
{
if ((Object)(object)hand == (Object)null)
{
return;
}
HandPoseAnimator animator = hand.Animator;
if ((Object)(object)animator == (Object)null)
{
return;
}
int instanceID = ((Object)hand).GetInstanceID();
if (!FingerFixEnabled || hand.HasAttachedObject())
{
if (FingerOverrideActive.Remove(instanceID))
{
animator.CurlOverride(-1f, -1f, -1f, -1f, -1f);
}
return;
}
BaseController controller = hand.Controller;
float inputCurl = 0f;
float inputCurl2 = 0f;
float inputCurl3 = 0f;
float inputCurl4 = 0f;
if ((Object)(object)controller != (Object)null)
{
inputCurl = controller._processedIndex;
inputCurl2 = controller._processedMiddle;
inputCurl3 = controller._processedRing;
inputCurl4 = controller._processedPinky;
}
Transform myRig = null;
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager != (Object)null)
{
myRig = ((Component)rigManager).transform;
}
float num = FingerCurl(animator.index1, animator.index2, animator.index3, inputCurl, myRig);
float num2 = FingerCurl(animator.middle1, animator.middle2, animator.middle3, inputCurl2, myRig);
float num3 = FingerCurl(animator.ring1, animator.ring2, animator.ring3, inputCurl3, myRig);
float num4 = FingerCurl(animator.pinky1, animator.pinky2, animator.pinky3, inputCurl4, myRig);
if (num >= 0f || num2 >= 0f || num3 >= 0f || num4 >= 0f)
{
animator.CurlOverride(-1f, num, num2, num3, num4);
FingerOverrideActive.Add(instanceID);
}
else if (FingerOverrideActive.Remove(instanceID))
{
animator.CurlOverride(-1f, -1f, -1f, -1f, -1f);
}
}
catch
{
}
}
private static float FingerCurl(Transform proximal, Transform mid, Transform tip, float inputCurl, Transform myRig)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((Object)(object)proximal == (Object)null || (Object)(object)mid == (Object)null || (Object)(object)tip == (Object)null)
{
return -1f;
}
Vector3 position = proximal.position;
Vector3 val = mid.position - position;
float magnitude = ((Vector3)(ref val)).magnitude;
if (magnitude < 1E-05f)
{
return -1f;
}
val /= magnitude;
float num = magnitude + Vector3.Distance(tip.position, mid.position) * 1.8f;
Il2CppStructArray<RaycastHit> val2 = Physics.RaycastAll(position - val * 0.005f, val, num);
float num2 = float.MaxValue;
for (int i = 0; i < ((Il2CppArrayBase<RaycastHit>)(object)val2).Length; i++)
{
RaycastHit val3 = ((Il2CppArrayBase<RaycastHit>)(object)val2)[i];
Collider collider = ((RaycastHit)(ref val3)).collider;
if (!((Object)(object)collider == (Object)null) && !collider.isTrigger && (!((Object)(object)myRig != (Object)null) || !((Component)collider).transform.IsChildOf(myRig)))
{
val3 = ((Il2CppArrayBase<RaycastHit>)(object)val2)[i];
if (((RaycastHit)(ref val3)).distance < num2)
{
val3 = ((Il2CppArrayBase<RaycastHit>)(object)val2)[i];
num2 = ((RaycastHit)(ref val3)).distance;
}
}
}
if (num2 >= num)
{
return -1f;
}
float num3 = Mathf.Clamp01(1f - num2 / num) * 0.85f;
if (num3 <= inputCurl)
{
return -1f;
}
return Mathf.Clamp01(num3);
}
catch
{
return -1f;
}
}
}
}