Decompiled source of Sprint Toggle v1.0.3

BepInEx\plugins\CyranIndustries\ToggleSprint.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ToggleSprint.Utils;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("com.cyranindustries.toggle_sprint")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Toggle Sprint")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("com.cyranindustries.toggle_sprint")]
[assembly: AssemblyTitle("com.cyranindustries.toggle_sprint")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ToggleSprint
{
	[HarmonyPatch(typeof(PlayerControllerB))]
	public static class ToggleSprintPatch
	{
		private static readonly CodeSearch v45patch = new CodeSearch(new CodeSearchDescriptor((CodeInstruction i) => i.opcode == OpCodes.Call && i.operand.ToString().Contains("IngamePlayerSettings")), new CodeSearchDescriptor((CodeInstruction i) => i.opcode == OpCodes.Stloc_0), new CodeSearchDescriptor[3]
		{
			new CodeSearchDescriptor((CodeInstruction i) => i.opcode == OpCodes.Ldstr && i.operand.ToString().Contains("Sprint")),
			new CodeSearchDescriptor((CodeInstruction i) => i.opcode == OpCodes.Callvirt && i.operand.ToString().Contains("FindAction")),
			new CodeSearchDescriptor((CodeInstruction i) => i.opcode == OpCodes.Callvirt && i.operand.ToString().Contains("ReadValue"))
		});

		private static readonly MethodInfo m_MyExtraMethod = SymbolExtensions.GetMethodInfo<PlayerControllerB, float>((Expression<Func<PlayerControllerB, float>>)((PlayerControllerB instance) => IsSprinting(instance)));

		public static bool __is_sprint_toggled = false;

		public static bool __was_pressed_last_frame = false;

		public static float IsSprinting(PlayerControllerB instance)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.toggleSprintEnabled.Value || !__is_sprint_toggled)
			{
				MovementActions movement = instance.playerActions.Movement;
				return ((MovementActions)(ref movement)).Sprint.ReadValue<float>();
			}
			return 1f;
		}

		public static bool SprintIsTogglable(PlayerControllerB __instance)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = IngamePlayerSettings.Instance.playerInput.actions.FindAction("Move", false).ReadValue<Vector2>();
			if (!Plugin.alwaysToggleEnabled.Value)
			{
				return ((Vector2)(ref val)).sqrMagnitude >= 0.05f;
			}
			return true;
		}

		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		public static bool UpdatePrefix(PlayerControllerB __instance)
		{
			if (!Plugin.toggleSprintEnabled.Value)
			{
				return true;
			}
			if (!SprintIsTogglable(__instance))
			{
				if (__is_sprint_toggled)
				{
					__is_sprint_toggled = false;
					__was_pressed_last_frame = false;
					Plugin.StaticLogger.LogDebug((object)$"Sprint toggled by game state: {__is_sprint_toggled}");
				}
			}
			else if ((double)IngamePlayerSettings.Instance.playerInput.actions.FindAction("Sprint", false).ReadValue<float>() > 0.3)
			{
				if (!__was_pressed_last_frame)
				{
					__is_sprint_toggled = !__is_sprint_toggled;
					Plugin.StaticLogger.LogDebug((object)$"Sprint toggled by player input: {__is_sprint_toggled}");
					__was_pressed_last_frame = true;
				}
			}
			else
			{
				__was_pressed_last_frame = false;
			}
			return true;
		}

		[HarmonyPatch("Update")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> UpdateTranspile(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			Plugin.StaticLogger.LogInfo((object)"Transpiling Update");
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			Tuple<int, int> tuple = v45patch.FindPatch(list);
			Plugin.StaticLogger.LogDebug((object)"found v45 call");
			if (tuple != null)
			{
				Plugin.StaticLogger.LogDebug((object)$"Found sprint call at {tuple.Item1} and {tuple.Item2}");
				for (int i = tuple.Item1; i < tuple.Item2; i++)
				{
					Plugin.StaticLogger.LogDebug((object)$"Replacing {list[i].opcode} {list[i].operand} with Nop");
					list[i].opcode = OpCodes.Nop;
				}
				list[tuple.Item2 - 2] = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
				list[tuple.Item2 - 1] = new CodeInstruction(OpCodes.Call, (object)m_MyExtraMethod);
				Plugin.StaticLogger.LogInfo((object)"Successfully patched sprint lookup call");
			}
			return list;
		}
	}
	[BepInPlugin("com.cyranindustries.toggle_sprint", "com.cyranindustries.toggle_sprint", "1.0.2")]
	public class Plugin : BaseUnityPlugin
	{
		public static ConfigEntry<bool> toggleSprintEnabled;

		public static ConfigEntry<bool> alwaysToggleEnabled;

		public static ConfigEntry<bool> uiEnabled;

		public static ManualLogSource StaticLogger;

		public static Texture2D sprintToggleUITexture;

		public static int versionDetected = -1;

		private static Texture2D LoadFromManifest(string resourceName)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0033: Expected O, but got Unknown
			Stream? manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
			byte[] array = new byte[manifestResourceStream.Length];
			manifestResourceStream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			return val;
		}

		private void Awake()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			StaticLogger = ((BaseUnityPlugin)this).Logger;
			toggleSprintEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Whether or not toggle sprint is enabled.");
			alwaysToggleEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AlwaysToggleSprint", false, "Whether or not to always toggle the sprint, even if not moving");
			uiEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Enabled", true, "Whether or not toggle sprint icon is enabled in the UI when you're sprinting");
			Harmony val = new Harmony("com.cyranindustries.toggle_sprint");
			sprintToggleUITexture = LoadFromManifest("ToggleSprint.images.running.png");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.cyranindustries.toggle_sprint is loaded!");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"com.cyranindustries.toggle_sprint Patched all!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.cyranindustries.toggle_sprint";

		public const string PLUGIN_NAME = "com.cyranindustries.toggle_sprint";

		public const string PLUGIN_VERSION = "1.0.2";
	}
}
namespace ToggleSprint.Utils
{
	internal class CodeSearchDescriptor
	{
		private readonly Func<CodeInstruction, bool> matchFunction;

		public CodeSearchDescriptor(Func<CodeInstruction, bool> matchFunction)
		{
			this.matchFunction = matchFunction ?? throw new ArgumentNullException("matchFunction");
		}

		public bool Matches(CodeInstruction instruction)
		{
			return matchFunction(instruction);
		}
	}
	internal class CodeSearch
	{
		private readonly CodeSearchDescriptor start;

		private readonly CodeSearchDescriptor end;

		private readonly IReadOnlyList<CodeSearchDescriptor> validators;

		public CodeSearch(CodeSearchDescriptor start, CodeSearchDescriptor end, IReadOnlyList<CodeSearchDescriptor> validators)
		{
			this.start = start ?? throw new ArgumentNullException("start");
			this.end = end ?? throw new ArgumentNullException("end");
			this.validators = validators;
		}

		public Tuple<int, int> FindPatch(List<CodeInstruction> instructions)
		{
			int? num = null;
			int? num2 = null;
			int num3 = 0;
			if (instructions == null)
			{
				return null;
			}
			for (int i = 0; i < instructions.Count; i++)
			{
				CodeInstruction val = instructions[i];
				if (val != null)
				{
					if (start.Matches(val))
					{
						num = i;
						num3 = 0;
					}
					if (start != null && validators != null && num3 < validators.Count && validators[num3].Matches(val))
					{
						num3++;
					}
					if (end.Matches(val) && num.HasValue && (validators == null || num3 >= validators.Count))
					{
						num2 = i;
						break;
					}
				}
			}
			if (num.HasValue && num2.HasValue)
			{
				return new Tuple<int, int>(num.Value, num2.Value);
			}
			return null;
		}
	}
}
namespace ToggleSprint.Patches
{
	[HarmonyPatch(typeof(HUDManager))]
	public class HudManagerPatch
	{
		public static GameObject SprintToggleUI;

		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		public static bool AwakePrefix(HUDManager __instance)
		{
			//IL_006a: 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_0098: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.uiEnabled.Value)
			{
				return true;
			}
			GameObject val = GameObject.Find("Self");
			if ((Object)(object)SprintToggleUI == (Object)null)
			{
				SprintToggleUI = Object.Instantiate<GameObject>(val);
				((Object)SprintToggleUI).name = "Sprint Toggle";
			}
			SprintToggleUI.transform.parent = val.transform.parent;
			SprintToggleUI.transform.localScale = val.transform.localScale;
			SprintToggleUI.transform.localPosition = val.transform.localPosition + new Vector3(-10f, -100f, 0f);
			Image component = SprintToggleUI.GetComponent<Image>();
			((Component)component).transform.parent = SprintToggleUI.transform;
			((Component)component).transform.localScale = new Vector3(0.33f, 0.33f, 1f);
			Plugin.StaticLogger.LogInfo((object)$"position = {((Component)component).transform.position}");
			component.sprite = Sprite.Create(Plugin.sprintToggleUITexture, new Rect(0f, 0f, (float)((Texture)Plugin.sprintToggleUITexture).width, (float)((Texture)Plugin.sprintToggleUITexture).height), new Vector2(0f, 0f));
			return true;
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void UpdatePostfix()
		{
			if (!((Object)(object)SprintToggleUI == (Object)null))
			{
				Image component = SprintToggleUI.GetComponent<Image>();
				if (!((Object)(object)component == (Object)null) && Plugin.uiEnabled.Value)
				{
					((Graphic)component).CrossFadeAlpha(ToggleSprintPatch.__is_sprint_toggled ? 1f : 0f, 0.05f, false);
				}
			}
		}
	}
}