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();
}
}
}
}