using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
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 FastText;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;
using _E;
using _m;
using ifapp.Game.Input;
using ifapp.Game.Scenes;
using ifapp.Game.Scenes.Game;
using ifapp.Game.UI.Common;
using ifapp.Game.UI.Settings;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MouseKeyBindings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("让六轨操作键位支持 Unity Input System 报告的全部鼠标按钮。")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("MouseKeyBindings")]
[assembly: AssemblyTitle("MouseKeyBindings")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 InFalsusMod
{
[HarmonyPatch(typeof(InputManager), "OnInputSystemEvent")]
internal static class MouseInputEventPatch
{
[HarmonyPrefix]
private static void Prefix(InputManager __instance, InputEventPtr __0, InputDevice __1)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
MouseInputEvents.Observe(__instance, __0, __1);
}
}
[HarmonyPatch(typeof(InputManager), "Update")]
internal static class MouseInputUpdatePatch
{
[HarmonyPostfix]
private static void Postfix(InputManager __instance)
{
try
{
MouseBindingRuntime.Process(__instance);
}
catch (Exception exception)
{
MouseBindingRuntime.Disable(exception);
}
}
}
[HarmonyPatch(typeof(KeyPressedIndicator), "_wl")]
internal static class MouseKeyIndicatorPatch
{
[HarmonyPrefix]
private static bool Prefix(KeyPressedIndicator __instance, Key __0)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
if (!MouseKeyCodec.TryDecode(__0, out var button))
{
return true;
}
if (__instance._ip == __0)
{
return false;
}
__instance._ip = __0;
FastText text = __instance.text;
if (text != null)
{
text.SetTextNonLocalized($"Mouse{button}", (UpdateType)0);
}
return false;
}
}
[HarmonyPatch(typeof(LaneKeyBindSettingsContainer), "_gE")]
internal static class MouseBindingSettingsPatch
{
[HarmonyPostfix]
private static void Postfix(LaneKeyBindSettingsContainer __instance)
{
try
{
MouseBindingRuntime.RegisterSettings(__instance);
}
catch (Exception exception)
{
MouseBindingRuntime.Disable(exception);
}
}
}
[HarmonyPatch(typeof(LaneKeyBindSettingsContainer), "_GE")]
internal static class MouseBindingRefreshPatch
{
[HarmonyPrefix]
private static bool Prefix(LaneKeyBindSettingsContainer __instance)
{
try
{
return !MouseBindingRuntime.RefreshBindingView(__instance);
}
catch (Exception exception)
{
MouseBindingRuntime.Disable(exception);
return true;
}
}
}
internal static class MouseBindingRuntime
{
private readonly record struct ActiveMousePress(IntPtr Device, GameScene Receiver, Key Key, CurrentKeyboardModifiersState Modifiers)
{
[CompilerGenerated]
public void Deconstruct(out IntPtr Device, out GameScene Receiver, out Key Key, out CurrentKeyboardModifiersState Modifiers)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected I4, but got Unknown
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
Device = this.Device;
Receiver = this.Receiver;
Key = (Key)(int)this.Key;
Modifiers = this.Modifiers;
}
}
private static readonly List<MouseTransition> Transitions = new List<MouseTransition>();
private static readonly Dictionary<int, ActiveMousePress> ActivePresses = new Dictionary<int, ActiveMousePress>();
private static LaneKeyBindSettingsContainer? settingsContainer;
private static int waitingLane = -1;
private static long captureAfterSequence;
private static bool disabled;
private static bool gameplayForwardLogged;
private static bool gameplayReleaseLogged;
internal static void RegisterSettings(LaneKeyBindSettingsContainer container)
{
if (!disabled)
{
settingsContainer = container;
waitingLane = container._Hh;
captureAfterSequence = MouseInputEvents.CurrentSequence;
RefreshLabels(container);
Plugin.Logger.LogDebug((object)"已接管六轨鼠标按键绑定界面。");
}
}
internal static void Process(InputManager manager)
{
if (disabled)
{
return;
}
MouseInputEvents.EnsureDevice(Mouse.current);
ObserveBindingSlot();
if (MouseInputEvents.Drain(Transitions) || (ActivePresses.Count > 0 && (Object)(object)GetPlayableGameScene(manager) == (Object)null))
{
ReleaseAll(InputState.currentTime);
}
foreach (MouseTransition transition in Transitions)
{
if (!TryCaptureBinding(transition))
{
ForwardToGame(manager, transition);
}
}
ReleasePhysicallyReleasedButtons(InputState.currentTime);
if ((Object)(object)settingsContainer != (Object)null)
{
RefreshLabels(settingsContainer);
}
}
internal static void Disable(Exception exception)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
if (!disabled)
{
disabled = true;
ActivePresses.Clear();
Transitions.Clear();
settingsContainer = null;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(13, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("鼠标轨道绑定运行层已停用:");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(exception);
}
logger.LogError(val);
}
}
private static void ObserveBindingSlot()
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
if ((Object)(object)settingsContainer == (Object)null)
{
return;
}
if (!((Behaviour)settingsContainer).isActiveAndEnabled)
{
settingsContainer = null;
waitingLane = -1;
captureAfterSequence = MouseInputEvents.CurrentSequence;
return;
}
int hh = settingsContainer._Hh;
if (hh == waitingLane)
{
return;
}
waitingLane = hh;
captureAfterSequence = MouseInputEvents.CurrentSequence;
if (hh >= 0)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(13, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("轨道 ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(hh + 1);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" 正在等待鼠标按键。");
}
logger.LogDebug(val);
}
}
private static bool TryCaptureBinding(MouseTransition transition)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: 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)
//IL_0112: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected O, but got Unknown
if (!transition.Pressed || (Object)(object)settingsContainer == (Object)null || waitingLane < 0 || transition.Sequence <= captureAfterSequence)
{
return false;
}
int num = waitingLane;
Key val = MouseKeyCodec.Encode(transition.Button);
CurrentKeyboardModifiersState val2 = default(CurrentKeyboardModifiersState);
settingsContainer._iE(val, transition.Time, ref val2);
Il2CppStructArray<Key> hh = settingsContainer._hh;
bool num2 = hh != null && num < ((Il2CppArrayBase<Key>)(object)hh).Length && ((Il2CppArrayBase<Key>)(object)hh)[num] == val;
waitingLane = settingsContainer._Hh;
captureAfterSequence = MouseInputEvents.CurrentSequence;
RefreshLabels(settingsContainer);
bool flag = default(bool);
if (num2)
{
ManualLogSource logger = Plugin.Logger;
BepInExDebugLogInterpolatedStringHandler val3 = new BepInExDebugLogInterpolatedStringHandler(14, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("轨道 ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num + 1);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" 已绑定 Mouse");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(transition.Button);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("。");
}
logger.LogDebug(val3);
}
else
{
ManualLogSource logger2 = Plugin.Logger;
BepInExDebugLogInterpolatedStringHandler val3 = new BepInExDebugLogInterpolatedStringHandler(27, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Mouse");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(transition.Button);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" 未写入轨道 ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num + 1);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(",原版绑定检查已拒绝本次设置。");
}
logger2.LogDebug(val3);
}
return true;
}
private static void ForwardToGame(InputManager manager, MouseTransition transition)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: 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_0060: 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_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
if (!transition.Pressed)
{
Release(transition.Button, transition.Time);
}
else
{
if (ActivePresses.ContainsKey(transition.Button))
{
return;
}
Key val = MouseKeyCodec.Encode(transition.Button);
GameScene playableGameScene = GetPlayableGameScene(manager);
if ((Object)(object)playableGameScene == (Object)null || !IsLaneBinding(val))
{
return;
}
CurrentKeyboardModifiersState modifiers = transition.Modifiers;
((InputReceiver)playableGameScene)._OvA(val, transition.Time, ref modifiers);
ActivePresses.Add(transition.Button, new ActiveMousePress(transition.Device, playableGameScene, val, modifiers));
if (!gameplayForwardLogged)
{
gameplayForwardLogged = true;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Mouse");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(transition.Button);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" 已进入原版六轨按下路径。");
}
logger.LogDebug(val2);
}
}
}
private static GameScene? GetPlayableGameScene(InputManager manager)
{
if (!manager.IsAllInputEnabled())
{
return null;
}
GameScene xn = GameScene._xn;
if ((Object)(object)xn == (Object)null || !((Behaviour)xn).isActiveAndEnabled)
{
return null;
}
GamePauseLayer pauseLayer = xn.pauseLayer;
if ((Object)(object)pauseLayer != (Object)null && pauseLayer._Dz())
{
return null;
}
Il2CppReferenceArray<InputOwnershipPair> inputAlwaysReceivedStack = manager.inputAlwaysReceivedStack;
if (inputAlwaysReceivedStack == null)
{
return null;
}
int num = Math.Min(manager.inputAlwaysReceivedStackCount, ((Il2CppArrayBase<InputOwnershipPair>)(object)inputAlwaysReceivedStack).Length);
for (int i = 0; i < num; i++)
{
InputOwnershipPair obj = ((Il2CppArrayBase<InputOwnershipPair>)(object)inputAlwaysReceivedStack)[i];
InputReceiver val = ((obj != null) ? obj.Owner : null);
if ((Object)(object)val != (Object)null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)xn).Pointer)
{
return xn;
}
}
return null;
}
private static bool IsLaneBinding(Key key)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
Il2CppStructArray<Key> jfA = _YD._JfA;
if (jfA == null)
{
return false;
}
int num = Math.Min(6, ((Il2CppArrayBase<Key>)(object)jfA).Length);
for (int i = 0; i < num; i++)
{
if (((Il2CppArrayBase<Key>)(object)jfA)[i] == key)
{
return true;
}
}
return false;
}
private static void ReleasePhysicallyReleasedButtons(double time)
{
bool pressed;
int[] array = (from pair in ActivePresses
where MouseInputEvents.TryGetCurrentButtonState(pair.Value.Device, pair.Key, out pressed) && !pressed
select pair.Key).ToArray();
for (int num = 0; num < array.Length; num++)
{
Release(array[num], time);
}
}
private static void Release(int button, double time)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Expected O, but got Unknown
if (!ActivePresses.Remove(button, out var value) || (Object)(object)value.Receiver == (Object)null)
{
return;
}
CurrentKeyboardModifiersState modifiers = value.Modifiers;
((InputReceiver)value.Receiver)._fwA(value.Key, time, ref modifiers);
if (!gameplayReleaseLogged)
{
gameplayReleaseLogged = true;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(18, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mouse");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(button);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" 已进入原版六轨释放路径。");
}
logger.LogDebug(val);
}
}
private static void ReleaseAll(double time)
{
int[] array = ActivePresses.Keys.ToArray();
for (int i = 0; i < array.Length; i++)
{
Release(array[i], time);
}
}
internal unsafe static bool RefreshBindingView(LaneKeyBindSettingsContainer container)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
Il2CppStructArray<Key> hh = container._hh;
Il2CppReferenceArray<UIButton> laneButtons = container.laneButtons;
Il2CppReferenceArray<FastText> laneButtonTexts = container.laneButtonTexts;
if (hh == null || laneButtons == null || laneButtonTexts == null || ((Il2CppArrayBase<UIButton>)(object)laneButtons).Length == 0)
{
return false;
}
bool flag = false;
for (int i = 0; i < ((Il2CppArrayBase<Key>)(object)hh).Length; i++)
{
flag |= MouseKeyCodec.TryDecode(((Il2CppArrayBase<Key>)(object)hh)[i], out var _);
}
if (!flag)
{
return false;
}
Keyboard current = Keyboard.current;
int num = ((Il2CppArrayBase<FastText>)(object)laneButtonTexts).Length / ((Il2CppArrayBase<UIButton>)(object)laneButtons).Length;
for (int j = 0; j < ((Il2CppArrayBase<FastText>)(object)laneButtonTexts).Length / Math.Max(1, num) && j < ((Il2CppArrayBase<Key>)(object)hh).Length; j++)
{
Key val = ((Il2CppArrayBase<Key>)(object)hh)[j];
object obj;
if (!MouseKeyCodec.TryDecode(val, out var button2))
{
if (current == null)
{
obj = null;
}
else
{
KeyControl obj2 = current[val];
obj = ((obj2 != null) ? ((InputControl)obj2).displayName : null);
}
if (obj == null)
{
obj = ((object)(*(Key*)(&val))/*cast due to .constrained prefix*/).ToString();
}
}
else
{
obj = $"Mouse{button2}";
}
string text = (string)obj;
for (int k = 0; k < num; k++)
{
FastText obj3 = ((Il2CppArrayBase<FastText>)(object)laneButtonTexts)[j * num + k];
if (obj3 != null)
{
obj3.SetTextNonLocalized(text, (UpdateType)0);
}
}
}
Il2CppStructArray<Key> jfA = _YD._JfA;
bool flag2 = false;
for (int l = 0; l < ((Il2CppArrayBase<UIButton>)(object)laneButtons).Length && l < ((Il2CppArrayBase<Key>)(object)hh).Length; l++)
{
bool flag3 = jfA == null || l >= ((Il2CppArrayBase<Key>)(object)jfA).Length || ((Il2CppArrayBase<Key>)(object)jfA)[l] != ((Il2CppArrayBase<Key>)(object)hh)[l];
flag2 = flag2 || flag3;
UIButton obj4 = ((Il2CppArrayBase<UIButton>)(object)laneButtons)[l];
if (obj4 != null)
{
obj4._dSA((_dI)((!flag3) ? 1 : 2));
}
}
UIButton applyButton = container.applyButton;
if (applyButton != null)
{
applyButton._dSA((_dI)(flag2 ? 1 : 0));
}
return true;
}
private static void RefreshLabels(LaneKeyBindSettingsContainer container)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
Il2CppStructArray<Key> hh = container._hh;
Il2CppReferenceArray<FastText> laneButtonTexts = container.laneButtonTexts;
if (hh == null || laneButtonTexts == null || ((Il2CppArrayBase<Key>)(object)hh).Length == 0 || ((Il2CppArrayBase<FastText>)(object)laneButtonTexts).Length % ((Il2CppArrayBase<Key>)(object)hh).Length != 0)
{
return;
}
int num = ((Il2CppArrayBase<FastText>)(object)laneButtonTexts).Length / ((Il2CppArrayBase<Key>)(object)hh).Length;
for (int i = 0; i < ((Il2CppArrayBase<Key>)(object)hh).Length; i++)
{
if (!MouseKeyCodec.TryDecode(((Il2CppArrayBase<Key>)(object)hh)[i], out var button))
{
continue;
}
string text = $"Mouse{button}";
int num2 = i * num;
for (int j = 0; j < num; j++)
{
FastText val = ((Il2CppArrayBase<FastText>)(object)laneButtonTexts)[num2 + j];
if ((Object)(object)val != (Object)null && !string.Equals(val.GetText(), text, StringComparison.Ordinal))
{
val.SetTextNonLocalized(text, (UpdateType)0);
}
}
}
}
}
internal readonly record struct MouseTransition(IntPtr Device, int Button, bool Pressed, double Time, long Sequence, CurrentKeyboardModifiersState Modifiers);
internal static class MouseInputEvents
{
private sealed class MouseDeviceState
{
internal int ButtonOffset { get; }
internal uint StateFormat { get; }
internal IReadOnlyList<StandardButtonState> StandardButtons { get; }
internal IReadOnlyList<ExtraButtonState> ExtraButtons { get; }
internal ushort Buttons { get; set; }
internal MouseDeviceState(int buttonOffset, uint stateFormat, ushort buttons, IReadOnlyList<StandardButtonState> standardButtons, IReadOnlyList<ExtraButtonState> extraButtons)
{
ButtonOffset = buttonOffset;
StateFormat = stateFormat;
Buttons = buttons;
StandardButtons = standardButtons;
ExtraButtons = extraButtons;
}
}
private sealed class StandardButtonState
{
internal ButtonControl Control { get; }
internal int Number { get; }
internal StandardButtonState(ButtonControl control, int number)
{
Control = control;
Number = number;
}
}
private readonly record struct ButtonCandidate(ButtonControl Control, ulong StartBit, uint SizeInBits, string Path);
private sealed class ExtraButtonState
{
internal ButtonControl Control { get; }
internal int Number { get; }
internal bool Pressed { get; set; }
internal ExtraButtonState(ButtonControl control, int number, bool pressed)
{
Control = control;
Number = number;
Pressed = pressed;
}
}
private const uint StateEventCode = 1413567571u;
private const uint DeltaStateEventCode = 1096043588u;
private const int RawMouseButtonCount = 16;
private const int StateEventHeaderSize = 24;
private const int DeltaStateEventHeaderSize = 28;
private const int MaximumPendingTransitions = 256;
private static readonly object Sync = new object();
private static readonly Dictionary<IntPtr, MouseDeviceState> Devices = new Dictionary<IntPtr, MouseDeviceState>();
private static readonly Queue<MouseTransition> Pending = new Queue<MouseTransition>();
private static long lastSequence;
private static bool resetRequested;
private static bool disabled;
internal static long CurrentSequence
{
get
{
lock (Sync)
{
return lastSequence;
}
}
}
internal static void EnsureDevice(Mouse? mouse)
{
if (disabled || mouse == null)
{
return;
}
try
{
lock (Sync)
{
GetOrCreateDevice(mouse);
}
}
catch (Exception exception)
{
Disable(exception);
}
}
internal unsafe static void Observe(InputManager manager, InputEventPtr eventPtr, InputDevice? device)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0239: Unknown result type (might be due to invalid IL or missing references)
if (disabled || device == null || eventPtr.m_EventPtr == IntPtr.Zero)
{
return;
}
try
{
Mouse val = ((Il2CppObjectBase)device).TryCast<Mouse>();
if (val == null)
{
return;
}
lock (Sync)
{
MouseDeviceState orCreateDevice = GetOrCreateDevice(val);
byte* eventData = (byte*)(void*)eventPtr.m_EventPtr;
bool contextRead = false;
double time = 0.0;
CurrentKeyboardModifiersState modifiers = default(CurrentKeyboardModifiersState);
ushort num = 0;
float num2 = default(float);
foreach (StandardButtonState standardButton in orCreateDevice.StandardButtons)
{
if (InputControlExtensions.ReadValueFromEvent<float>((InputControl<float>)(object)standardButton.Control, eventPtr, ref num2))
{
ushort num3 = (ushort)(1 << standardButton.Number);
num |= num3;
bool flag = (orCreateDevice.Buttons & num3) != 0;
float num4 = (flag ? (standardButton.Control.pressPointOrDefault * ButtonControl.s_GlobalDefaultButtonReleaseThreshold) : standardButton.Control.pressPointOrDefault);
bool flag2 = num2 >= num4;
if (flag2 != flag)
{
orCreateDevice.Buttons = (flag2 ? ((ushort)(orCreateDevice.Buttons | num3)) : ((ushort)(orCreateDevice.Buttons & ~num3)));
QueueTransition(manager, eventPtr, ((Il2CppObjectBase)val).Pointer, standardButton.Number, flag2, ref contextRead, ref time, ref modifiers);
}
}
}
if (TryReadButtons(eventData, orCreateDevice, out var buttons))
{
ushort num5 = (ushort)(~num);
ushort num6 = (ushort)((buttons ^ orCreateDevice.Buttons) & num5);
orCreateDevice.Buttons = (ushort)((orCreateDevice.Buttons & num) | (buttons & num5));
for (int i = 0; i < 16; i++)
{
ushort num7 = (ushort)(1 << i);
if ((num6 & num7) != 0)
{
QueueTransition(manager, eventPtr, ((Il2CppObjectBase)val).Pointer, i, (buttons & num7) != 0, ref contextRead, ref time, ref modifiers);
}
}
}
float num8 = default(float);
foreach (ExtraButtonState extraButton in orCreateDevice.ExtraButtons)
{
if (InputControlExtensions.ReadValueFromEvent<float>((InputControl<float>)(object)extraButton.Control, eventPtr, ref num8))
{
float num9 = (extraButton.Pressed ? (extraButton.Control.pressPointOrDefault * ButtonControl.s_GlobalDefaultButtonReleaseThreshold) : extraButton.Control.pressPointOrDefault);
bool flag3 = num8 >= num9;
if (flag3 != extraButton.Pressed)
{
extraButton.Pressed = flag3;
QueueTransition(manager, eventPtr, ((Il2CppObjectBase)val).Pointer, extraButton.Number, flag3, ref contextRead, ref time, ref modifiers);
}
}
}
}
}
catch (Exception exception)
{
Disable(exception);
}
}
internal static bool Drain(List<MouseTransition> destination)
{
lock (Sync)
{
destination.Clear();
while (Pending.Count > 0)
{
destination.Add(Pending.Dequeue());
}
bool result = resetRequested;
resetRequested = false;
return result;
}
}
private static MouseDeviceState GetOrCreateDevice(Mouse mouse)
{
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
if (Devices.TryGetValue(((Il2CppObjectBase)mouse).Pointer, out MouseDeviceState value))
{
return value;
}
StandardButtonState[] array = new StandardButtonState[5]
{
new StandardButtonState(mouse.leftButton, 0),
new StandardButtonState(mouse.rightButton, 1),
new StandardButtonState(mouse.middleButton, 2),
new StandardButtonState(mouse.forwardButton, 3),
new StandardButtonState(mouse.backButton, 4)
};
ushort num = 0;
StandardButtonState[] array2 = array;
foreach (StandardButtonState standardButtonState in array2)
{
if (standardButtonState.Control.isPressed)
{
num |= (ushort)(1 << standardButtonState.Number);
}
}
InputStateBlock stateBlock = ((InputControl)mouse).stateBlock;
InputStateBlock stateBlock2 = ((InputControl)mouse.leftButton).stateBlock;
int buttonOffset = -1;
ulong? rawButtonBaseBit = null;
if (((InputStateBlock)(ref stateBlock2)).bitOffset == 0 && ((InputStateBlock)(ref stateBlock2)).sizeInBits == 1 && ((InputStateBlock)(ref stateBlock2)).byteOffset >= ((InputStateBlock)(ref stateBlock)).byteOffset)
{
uint num2 = ((InputStateBlock)(ref stateBlock2)).byteOffset - ((InputStateBlock)(ref stateBlock)).byteOffset;
if (num2 <= int.MaxValue)
{
buttonOffset = (int)num2;
rawButtonBaseBit = (ulong)num2 * 8uL;
}
}
uint code = (uint)((InputStateBlock)(ref stateBlock)).format.m_Code;
List<ExtraButtonState> extraButtons = DiscoverExtraButtons(mouse, ((InputStateBlock)(ref stateBlock)).byteOffset, rawButtonBaseBit, array);
MouseDeviceState mouseDeviceState = new MouseDeviceState(buttonOffset, code, num, array, extraButtons);
Devices.Add(((Il2CppObjectBase)mouse).Pointer, mouseDeviceState);
return mouseDeviceState;
}
private static List<ExtraButtonState> DiscoverExtraButtons(Mouse mouse, uint deviceByteOffset, ulong? rawButtonBaseBit, IReadOnlyList<StandardButtonState> standardButtons)
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
HashSet<IntPtr> hashSet = standardButtons.Select((StandardButtonState button) => ((Il2CppObjectBase)button.Control).Pointer).ToHashSet();
List<ButtonCandidate> list = new List<ButtonCandidate>();
ReadOnlyArray<InputControl> allControls = ((InputDevice)mouse).allControls;
for (int num = 0; num < allControls.Count; num++)
{
InputControl obj = allControls[num];
ButtonControl val = ((obj != null) ? ((Il2CppObjectBase)obj).TryCast<ButtonControl>() : null);
if (val == null || hashSet.Contains(((Il2CppObjectBase)val).Pointer))
{
continue;
}
InputStateBlock stateBlock = ((InputControl)val).stateBlock;
if (((InputStateBlock)(ref stateBlock)).byteOffset != uint.MaxValue && ((InputStateBlock)(ref stateBlock)).sizeInBits != 0 && ((InputStateBlock)(ref stateBlock)).byteOffset >= deviceByteOffset)
{
ulong num2 = (ulong)(((long)((InputStateBlock)(ref stateBlock)).byteOffset - (long)deviceByteOffset) * 8 + ((InputStateBlock)(ref stateBlock)).bitOffset);
if (!rawButtonBaseBit.HasValue || num2 < rawButtonBaseBit.Value || num2 >= rawButtonBaseBit.Value + 16)
{
list.Add(new ButtonCandidate(val, num2, ((InputStateBlock)(ref stateBlock)).sizeInBits, ((InputControl)val).path ?? string.Empty));
}
}
}
list.Sort(delegate(ButtonCandidate left, ButtonCandidate right)
{
int num4 = left.StartBit.CompareTo(right.StartBit);
if (num4 != 0)
{
return num4;
}
int num5 = left.SizeInBits.CompareTo(right.SizeInBits);
return (num5 == 0) ? string.CompareOrdinal(left.Path, right.Path) : num5;
});
List<ButtonCandidate> list2 = new List<ButtonCandidate>();
HashSet<(ulong, uint)> hashSet2 = new HashSet<(ulong, uint)>();
foreach (ButtonCandidate item in list)
{
if (hashSet2.Add((item.StartBit, item.SizeInBits)))
{
list2.Add(item);
}
}
List<ExtraButtonState> list3 = new List<ExtraButtonState>(list2.Count);
HashSet<int> hashSet3 = new HashSet<int>(Enumerable.Range(0, 16));
HashSet<IntPtr> hashSet4 = new HashSet<IntPtr>();
foreach (ButtonCandidate item2 in list2)
{
if (rawButtonBaseBit.HasValue && TryGetNaturalNumber(item2, rawButtonBaseBit.Value, out var number) && hashSet3.Add(number))
{
list3.Add(new ExtraButtonState(item2.Control, number, item2.Control.isPressed));
hashSet4.Add(((Il2CppObjectBase)item2.Control).Pointer);
}
}
int num3 = 16;
foreach (ButtonCandidate item3 in list2)
{
if (!hashSet4.Contains(((Il2CppObjectBase)item3.Control).Pointer))
{
for (; hashSet3.Contains(num3); num3++)
{
}
if (num3 > 2147482647)
{
throw new NotSupportedException("当前 Mouse 布局公开的按钮数量超出可持久化范围。");
}
hashSet3.Add(num3);
list3.Add(new ExtraButtonState(item3.Control, num3, item3.Control.isPressed));
num3++;
}
}
list3.Sort((ExtraButtonState left, ExtraButtonState right) => left.Number.CompareTo(right.Number));
return list3;
}
private static bool TryGetNaturalNumber(ButtonCandidate candidate, ulong rawButtonBaseBit, out int number)
{
number = -1;
if (candidate.SizeInBits != 1 || candidate.StartBit < rawButtonBaseBit)
{
return false;
}
ulong num = candidate.StartBit - rawButtonBaseBit;
if (num > 2147482647)
{
return false;
}
number = (int)num;
return true;
}
private unsafe static bool TryReadButtons(byte* eventData, MouseDeviceState state, out ushort buttons)
{
buttons = state.Buttons;
if (state.ButtonOffset < 0)
{
return false;
}
uint num = *(uint*)eventData;
int num2 = ((ushort*)eventData)[2];
if (num2 < 24 || (num != 1413567571 && num != 1096043588) || ((uint*)eventData)[5] != state.StateFormat)
{
return false;
}
if (num == 1413567571)
{
int num3 = num2 - 24;
if (state.ButtonOffset < 0 || state.ButtonOffset + 2 > num3)
{
return false;
}
byte* ptr = eventData + 24 + state.ButtonOffset;
buttons = (ushort)(*ptr | (ptr[1] << 8));
return true;
}
if (num2 < 28)
{
return false;
}
uint num4 = ((uint*)eventData)[6];
int num5 = num2 - 28;
bool result = false;
for (int i = 0; i < 2; i++)
{
uint num6 = (uint)(state.ButtonOffset + i);
if (num6 >= num4 && num6 - num4 < num5)
{
byte b = eventData[28 + num6 - num4];
int num7 = i * 8;
buttons = (ushort)((buttons & ~(255 << num7)) | (b << num7));
result = true;
}
}
return result;
}
internal static bool TryGetCurrentButtonState(IntPtr device, int button, out bool pressed)
{
lock (Sync)
{
pressed = false;
if (!Devices.TryGetValue(device, out MouseDeviceState value))
{
return false;
}
foreach (StandardButtonState standardButton in value.StandardButtons)
{
if (standardButton.Number == button)
{
pressed = standardButton.Control.isPressed;
ushort num = (ushort)(1 << button);
value.Buttons = (pressed ? ((ushort)(value.Buttons | num)) : ((ushort)(value.Buttons & ~num)));
return true;
}
}
foreach (ExtraButtonState extraButton in value.ExtraButtons)
{
if (extraButton.Number == button)
{
pressed = extraButton.Control.isPressed;
extraButton.Pressed = pressed;
return true;
}
}
if ((uint)button >= 16u)
{
return false;
}
pressed = (value.Buttons & (1 << button)) != 0;
return true;
}
}
private static void QueueTransition(InputManager manager, InputEventPtr eventPtr, IntPtr device, int button, bool pressed, ref bool contextRead, ref double time, ref CurrentKeyboardModifiersState modifiers)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if (!contextRead)
{
time = ((InputEventPtr)(ref eventPtr)).time;
modifiers = ReadModifiers(manager);
contextRead = true;
}
Enqueue(new MouseTransition(device, button, pressed, time, ++lastSequence, modifiers));
}
private static CurrentKeyboardModifiersState ReadModifiers(InputManager manager)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
UnityKeyboardState currentKeyboardState = manager.currentKeyboardState;
CurrentKeyboardModifiersState result = default(CurrentKeyboardModifiersState);
((CurrentKeyboardModifiersState)(ref result)).IsCtrlPressed = ((UnityKeyboardState)(ref currentKeyboardState)).IsPressed((Key)55) || ((UnityKeyboardState)(ref currentKeyboardState)).IsPressed((Key)56);
((CurrentKeyboardModifiersState)(ref result)).IsAltPressed = ((UnityKeyboardState)(ref currentKeyboardState)).IsPressed((Key)53) || ((UnityKeyboardState)(ref currentKeyboardState)).IsPressed((Key)54);
((CurrentKeyboardModifiersState)(ref result)).IsShiftPressed = ((UnityKeyboardState)(ref currentKeyboardState)).IsPressed((Key)51) || ((UnityKeyboardState)(ref currentKeyboardState)).IsPressed((Key)52);
return result;
}
private static void Enqueue(MouseTransition transition)
{
if (Pending.Count >= 256)
{
Pending.Clear();
resetRequested = true;
}
Pending.Enqueue(transition);
}
private static void Disable(Exception exception)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
lock (Sync)
{
disabled = true;
}
ManualLogSource logger = Plugin.Logger;
bool flag;
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(12, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("鼠标按钮事件提取已停用:");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(exception);
}
logger.LogError(val);
}
}
internal static class MouseKeyCodec
{
private const int FirstMouseKey = 1000;
internal const int MaximumMouseButton = 2147482647;
internal static Key Encode(int button)
{
if (button < 0 || button > 2147482647)
{
throw new ArgumentOutOfRangeException("button");
}
return (Key)(1000 + button);
}
internal static bool TryDecode(Key key, out int button)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Expected I4, but got Unknown
int num = (int)key;
if (num < 1000)
{
button = -1;
return false;
}
button = num - 1000;
return true;
}
}
[BepInPlugin("menglei.infalsus.mousekeybindings", "In Falsus Mouse Key Bindings", "1.0.1")]
[BepInProcess("infalsus.exe")]
public sealed class Plugin : BasePlugin
{
internal const string PluginGuid = "menglei.infalsus.mousekeybindings";
internal const string PluginVersion = "1.0.1";
private Harmony? harmony;
internal static ManualLogSource Logger { get; private set; }
public override void Load()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
WindowsConsoleEncoding.EnsureUtf8(((BasePlugin)this).Log);
harmony = new Harmony("menglei.infalsus.mousekeybindings");
harmony.PatchAll(typeof(Plugin).Assembly);
((BasePlugin)this).Log.LogInfo((object)"加载完成。");
}
}
internal static class WindowsConsoleEncoding
{
private const uint Utf8CodePage = 65001u;
internal static void EnsureUtf8(ManualLogSource logger)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Expected O, but got Unknown
if (!OperatingSystem.IsWindows() || !ConsoleManager.ConsoleActive || GetConsoleOutputCP() == 65001)
{
return;
}
bool flag = default(bool);
if (!SetConsoleOutputCP(65001u))
{
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(75, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to set the BepInEx console output code page to UTF-8 (Win32 error ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Marshal.GetLastWin32Error());
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger.LogError(val);
return;
}
uint consoleOutputCP = GetConsoleOutputCP();
if (consoleOutputCP != 65001)
{
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(54, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("BepInEx console output code page remained ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<uint>(consoleOutputCP);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; expected ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<uint>(65001u);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
logger.LogError(val);
}
}
[DllImport("kernel32.dll")]
private static extern uint GetConsoleOutputCP();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetConsoleOutputCP(uint codePage);
}
}