Decompiled source of ClickFix v1.0.3

ClickFix.dll

Decompiled 4 hours 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 BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using ClickFix.Patches;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
namespace ClickFix
{
	internal enum ClickTarget
	{
		CellMenuTimedButton,
		WorldTimedInteraction,
		Other
	}
	internal readonly struct TimedButtonSettings
	{
		internal int ClickType { get; }

		internal float HoldDuration { get; }

		internal TimedButtonSettings(int clickType, float holdDuration)
		{
			ClickType = clickType;
			HoldDuration = holdDuration;
		}
	}
	internal static class ClickPolicy
	{
		internal const int Instant = 0;

		internal const int ShortHold = 1;

		internal const int MediumHold = 2;

		internal const int LongHold = 3;

		internal const float ImmediateSkipSeconds = 0.001f;

		internal static bool HasSupportedMenuClickModes(int instant, int shortHold, int mediumHold, int longHold)
		{
			if (instant == 0 && shortHold == 1 && mediumHold == 2)
			{
				return longHold == 3;
			}
			return false;
		}

		internal static TimedButtonSettings ApplyTimedButtonSettings(int currentClickType, float currentHoldDuration, ClickTarget target)
		{
			if (target != ClickTarget.CellMenuTimedButton)
			{
				return new TimedButtonSettings(currentClickType, currentHoldDuration);
			}
			if (currentClickType < 0 || currentClickType > 3)
			{
				return new TimedButtonSettings(currentClickType, currentHoldDuration);
			}
			return new TimedButtonSettings(0, 0f);
		}

		internal static float ApplySkipHoldDuration(float currentDuration)
		{
			if (!float.IsFinite(currentDuration) || currentDuration <= 0f)
			{
				return 0.001f;
			}
			return Math.Min(currentDuration, 0.001f);
		}
	}
	internal sealed class SkipOnceGate
	{
		private readonly object _sync = new object();

		private readonly HashSet<IntPtr> _completed = new HashSet<IntPtr>();

		internal bool HasCompleted(IntPtr instance)
		{
			lock (_sync)
			{
				return _completed.Contains(instance);
			}
		}

		internal bool TryInvoke(IntPtr instance, Action callback)
		{
			if (instance == IntPtr.Zero || callback == null)
			{
				return false;
			}
			lock (_sync)
			{
				if (!_completed.Add(instance))
				{
					return false;
				}
			}
			callback();
			return true;
		}

		internal void Reset(IntPtr instance)
		{
			if (instance == IntPtr.Zero)
			{
				return;
			}
			lock (_sync)
			{
				_completed.Remove(instance);
			}
		}

		internal void Clear()
		{
			lock (_sync)
			{
				_completed.Clear();
			}
		}
	}
	[BepInPlugin("HawChow.ClickFix", "ClickFix", "1.0.3")]
	internal sealed class EntryPoint : BasePlugin
	{
		private Harmony _harmony;

		public override void Load()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			bool flag = default(bool);
			if (!ClickPolicy.HasSupportedMenuClickModes(0, 1, 2, 3))
			{
				ManualLogSource log = ((BasePlugin)this).Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(78, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("ClickFix");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.3");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" skipped patches: unexpected eTimedButtonClickType values in this GTFO build.");
				}
				log.LogError(val);
				return;
			}
			_harmony = new Harmony("HawChow.ClickFix");
			try
			{
				_harmony.PatchAll(typeof(EntryPoint).Assembly);
			}
			catch (Exception ex)
			{
				_harmony.UnpatchSelf();
				ManualLogSource log2 = ((BasePlugin)this).Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(27, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("ClickFix");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.3");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" failed to apply patches: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log2.LogError(val);
				throw;
			}
			ManualLogSource log3 = ((BasePlugin)this).Log;
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(156, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("ClickFix");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.3");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded; menu timed buttons use Instant with zero hold duration; skip callback threshold=");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(0.001f, "0.000");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s and one-shot gate; other world timed interactions are unchanged.");
			}
			log3.LogInfo(val2);
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			SkipTextPatch.Clear();
			return true;
		}
	}
	internal static class PluginInfo
	{
		internal const string Guid = "HawChow.ClickFix";

		internal const string Name = "ClickFix";

		internal const string Version = "1.0.3";

		internal const string AssemblyVersion = "1.0.3.0";

		internal const string HarmonyId = "HawChow.ClickFix";
	}
}
namespace ClickFix.Patches
{
	[HarmonyPatch(typeof(CM_TimedButton), "SetupCMItem", new Type[] { })]
	internal static class TimedButtonSetupPatch
	{
		[HarmonyPrefix]
		private static void Prefix(CM_TimedButton __instance)
		{
			ApplyInstantMode(__instance);
		}

		[HarmonyPostfix]
		private static void Postfix(CM_TimedButton __instance)
		{
			ApplyInstantMode(__instance);
		}

		internal static void ApplyInstantMode(CM_TimedButton instance)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected I4, but got Unknown
			if (!((Object)(object)instance == (Object)null))
			{
				TimedButtonSettings timedButtonSettings = ClickPolicy.ApplyTimedButtonSettings((int)instance.m_clickType, instance.m_holdButtonDuration, ClickTarget.CellMenuTimedButton);
				instance.m_clickType = (eTimedButtonClickType)timedButtonSettings.ClickType;
				instance.m_holdButtonDuration = timedButtonSettings.HoldDuration;
			}
		}
	}
	[HarmonyPatch(typeof(CM_TimedButton), "OnBtnPress", new Type[] { typeof(iCellMenuInputHandler) })]
	internal static class TimedButtonPressPatch
	{
		[HarmonyPrefix]
		private static void Prefix(CM_TimedButton __instance)
		{
			TimedButtonSetupPatch.ApplyInstantMode(__instance);
		}
	}
	[HarmonyPatch(typeof(PUI_SkipText), "Setup", new Type[] { typeof(Transform) })]
	internal static class SkipTextSetupPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PUI_SkipText __instance)
		{
			SkipTextPatch.Reset(__instance);
		}
	}
	[HarmonyPatch(typeof(PUI_SkipText), "UpdateSkipTimer", new Type[] { typeof(Action) })]
	internal static class SkipTextPatch
	{
		private sealed class CallbackCache
		{
			internal IntPtr SourcePointer { get; }

			internal Action Wrapped { get; }

			internal CallbackCache(IntPtr sourcePointer, Action wrapped)
			{
				SourcePointer = sourcePointer;
				Wrapped = wrapped;
			}
		}

		private static readonly object Sync = new object();

		private static readonly Dictionary<IntPtr, CallbackCache> Callbacks = new Dictionary<IntPtr, CallbackCache>();

		private static readonly SkipOnceGate Gate = new SkipOnceGate();

		[HarmonyPrefix]
		private static void Prefix(PUI_SkipText __instance, ref Action onSkip)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			__instance.m_holdDuration = ClickPolicy.ApplySkipHoldDuration(__instance.m_holdDuration);
			if ((Delegate)(object)onSkip == (Delegate)null)
			{
				return;
			}
			IntPtr instancePointer = ((Il2CppObjectBase)__instance).Pointer;
			IntPtr pointer = ((Il2CppObjectBase)onSkip).Pointer;
			lock (Sync)
			{
				if (!Callbacks.TryGetValue(instancePointer, out var value) || value.SourcePointer != pointer)
				{
					Action original = onSkip;
					Action wrapped = Action.op_Implicit((Action)delegate
					{
						Gate.TryInvoke(instancePointer, (Action)original.Invoke);
					});
					value = new CallbackCache(pointer, wrapped);
					Callbacks[instancePointer] = value;
				}
				onSkip = value.Wrapped;
			}
		}

		internal static void Reset(PUI_SkipText instance)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			IntPtr pointer = ((Il2CppObjectBase)instance).Pointer;
			Gate.Reset(pointer);
			lock (Sync)
			{
				Callbacks.Remove(pointer);
			}
		}

		internal static void Clear()
		{
			Gate.Clear();
			lock (Sync)
			{
				Callbacks.Clear();
			}
		}
	}
}