Decompiled source of HandUnstuck v1.2.2

Mods/HandUnstuck.dll

Decompiled 4 hours ago
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using HandUnstuck;
using Il2CppSLZ.Marrow;
using MelonLoader;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Mod), "Hand Unstuck", "1.2.1", "andre", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("HandUnstuck")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HandUnstuck")]
[assembly: AssemblyTitle("HandUnstuck")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HandUnstuck;

public class Mod : MelonMod
{
	private const float StuckSeconds = 1.5f;

	private float _leftSince = -1f;

	private float _rightSince = -1f;

	public override void OnApplicationQuit()
	{
		TimelineNoBreaks.Restore();
	}

	public override void OnUpdate()
	{
		TimelineNoBreaks.Update();
		if (Player.HandsExist)
		{
			Check(Player.LeftHand, ref _leftSince);
			Check(Player.RightHand, ref _rightSince);
		}
	}

	private void Check(Hand hand, ref float since)
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)hand == (Object)null)
		{
			since = -1f;
		}
		else if ((Object)(object)hand.m_CurrentAttachedGO != (Object)null || !hand.GrabLock)
		{
			since = -1f;
		}
		else if (since < 0f)
		{
			since = Time.time;
		}
		else if (!(Time.time - since < 1.5f))
		{
			since = -1f;
			((MelonBase)this).LoggerInstance.Msg($"{hand.handedness} hand was stuck (grab lock with nothing held), releasing it");
			hand.GrabLock = false;
			if (hand.hoverLocked)
			{
				hand.HoverUnlock();
			}
		}
	}
}
internal static class TimelineNoBreaks
{
	private static readonly (string cat, string id, bool followsGoreOff)[] Keys = new(string, string, bool)[3]
	{
		("TimelineClones", "BreakBones", false),
		("PlayerGore", "BreakMine", true),
		("PlayerGore", "BreakPlayers", true)
	};

	private static FieldInfo _playing;

	private static FieldInfo _recording;

	private static bool _lookedUp;

	private static readonly bool[] _forced = new bool[Keys.Length];

	private static bool TimelineInUse()
	{
		if (!_lookedUp)
		{
			_lookedUp = true;
			Type? type = (from a in AppDomain.CurrentDomain.GetAssemblies()
				select a.GetType("Timeline.WorldRecording.WorldPlayer", throwOnError: false)).FirstOrDefault((Type x) => x != null);
			_playing = type?.GetField("playing", BindingFlags.Static | BindingFlags.Public);
			_recording = type?.GetField("recording", BindingFlags.Static | BindingFlags.Public);
			MelonLogger.Msg((type == null) ? "[NoBreaks] Timeline not found" : "[NoBreaks] Timeline found");
		}
		if (_playing == null)
		{
			return false;
		}
		if (!(bool)_playing.GetValue(null))
		{
			return (bool)(_recording?.GetValue(null) ?? ((object)false));
		}
		return true;
	}

	internal static void Update()
	{
		bool flag = TimelineInUse();
		MelonPreferences_Entry<bool> entry = MelonPreferences.GetEntry<bool>("PlayerGore", "On");
		bool flag2 = entry != null && !entry.Value;
		for (int i = 0; i < Keys.Length; i++)
		{
			MelonPreferences_Entry<bool> entry2 = MelonPreferences.GetEntry<bool>(Keys[i].cat, Keys[i].id);
			if (entry2 != null)
			{
				bool flag3 = flag || (flag2 && Keys[i].followsGoreOff);
				string value = (flag ? "Timeline in use" : "Player Gore is off");
				if (flag3 && entry2.Value)
				{
					entry2.Value = false;
					_forced[i] = true;
					MelonLogger.Msg($"[NoBreaks] {value}: {Keys[i].cat}.{Keys[i].id} off");
				}
				else if (!flag3 && _forced[i])
				{
					Put(i, entry2);
				}
			}
		}
	}

	internal static void Restore()
	{
		for (int i = 0; i < Keys.Length; i++)
		{
			if (_forced[i])
			{
				Put(i, MelonPreferences.GetEntry<bool>(Keys[i].cat, Keys[i].id));
			}
		}
	}

	private static void Put(int i, MelonPreferences_Entry<bool> e)
	{
		_forced[i] = false;
		if (e != null)
		{
			e.Value = true;
			MelonLogger.Msg($"[NoBreaks] {Keys[i].cat}.{Keys[i].id} back on");
		}
	}
}