using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Rewired;
using Rewired.Config;
using Rewired.Demos;
using Rewired.Interfaces;
using Rewired.Platforms;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityStandardAssets.Characters.FirstPerson;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SOD.InputSoftlockFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1")]
[assembly: AssemblyProduct("SOD.InputSoftlockFix")]
[assembly: AssemblyTitle("SOD.InputSoftlockFix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SODInputSoftlockFix
{
internal static class Guard
{
private static readonly bool Portuguese = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "pt";
private static Hotkey hotkey;
private static bool hotkeyWasDown;
private static bool hotkeyKeyWasDown;
private static float lastHotkeyAt = -999f;
private static IntPtr forceFlagClearedOn = IntPtr.Zero;
private static float steamLockSince = -1f;
private static int steamLockCount;
private static bool steamCauseLogged;
private static float staleSince = -1f;
private static int staleFrames;
private static float textFlagSince = -1f;
private static float enableInputOffSince = -1f;
private static float popupStillSince = -1f;
private static float popupLastProgress = float.NaN;
private static float remapOrphanSince = -1f;
private static float nextRewiredCheck;
private static bool startupLogged;
private static readonly List<ControllerMap> keyboardMaps = new List<ControllerMap>();
private static readonly List<ControllerMap> mouseMaps = new List<ControllerMap>();
private static readonly int[] WatchVk = new int[13]
{
87, 65, 83, 68, 32, 27, 69, 9, 81, 70,
67, 77, 82
};
private static readonly KeyCode[] WatchKc;
private static readonly bool[] osWasDown;
private static readonly bool[] rewiredSawPress;
private static readonly bool[] unitySawPress;
private static readonly bool[] pressCounted;
private static readonly float[] pressStart;
private static int missedPresses;
private static float lastMissAt;
private static bool unityInputUsable;
private static float lastHardReset;
private static int refreshAfterResetFrames;
private static bool escWasDown;
private static float escDownSince;
private static bool escHoldFired;
private static float lastEscLog;
private static string message;
private static float messageUntil;
private static bool guiUsable;
private static GUIStyle messageStyle;
private static readonly Dictionary<string, float> errorThrottle;
private static ManualLogSource Log => Plugin.Logger;
public static void Init()
{
hotkey = Hotkey.Parse(Plugin.EmergencyHotkey.Value);
}
public static void Update()
{
float now = Time.unscaledTime;
Safe("startup", delegate
{
LogStartupOnce();
});
Safe("hotkey", delegate
{
CheckHotkey(now);
});
if (Plugin.WatchKeyboardDevice.Value)
{
Safe("watchdog", delegate
{
WatchKeyboard(now);
});
}
Safe("esc", delegate
{
WatchEscape(now);
});
if (refreshAfterResetFrames >= 0)
{
Safe("refresh", RefreshAfterReset);
}
}
public static void LateUpdate()
{
float now = Time.unscaledTime;
if (Plugin.PreventSteamKeyboardLock.Value)
{
Safe("steamflag", PreventSteamKeyboardLock);
}
if (Plugin.FixSteamKeyboardLock.Value)
{
Safe("steamkb", delegate
{
FixSteamKeyboardLock(now, force: false);
});
}
if (Plugin.FixStaleTextField.Value)
{
Safe("textfield", delegate
{
FixStaleTextField(now, force: false);
});
}
if (Plugin.FixTextInputFlag.Value)
{
Safe("textflag", delegate
{
FixTextInputFlag(now, force: false);
});
}
if (Plugin.FixGameGates.Value)
{
Safe("gates", delegate
{
FixGameGates(now, force: false);
});
}
if (Plugin.FixRewiredState.Value && now >= nextRewiredCheck)
{
nextRewiredCheck = now + 0.5f;
Safe("rewired", delegate
{
FixRewired(force: false);
});
}
}
public static void OnGUI()
{
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
if (!guiUsable || message == null || Time.unscaledTime > messageUntil)
{
return;
}
try
{
if (messageStyle == null)
{
messageStyle = new GUIStyle(GUI.skin.label);
messageStyle.fontSize = 18;
messageStyle.wordWrap = true;
}
float num = Mathf.Min(760f, (float)Screen.width - 40f);
Rect val = default(Rect);
((Rect)(ref val))..ctor(((float)Screen.width - num) / 2f, 30f, num, 64f);
GUI.Box(val, "");
GUI.Box(val, "");
GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 8f, ((Rect)(ref val)).width - 24f, ((Rect)(ref val)).height - 16f), message, messageStyle);
}
catch (Exception ex)
{
guiUsable = false;
Log.LogWarning((object)("On-screen messages disabled (IMGUI unavailable): " + ex.Message));
}
}
private static void PreventSteamKeyboardLock()
{
VirtualKeyboardController instance = VirtualKeyboardController.Instance;
if (!((Object)(object)instance == (Object)null) && instance.forceSteamInput)
{
instance.forceSteamInput = false;
if (!(((Il2CppObjectBase)instance).Pointer == forceFlagClearedOn))
{
forceFlagClearedOn = ((Il2CppObjectBase)instance).Pointer;
Log.LogInfo((object)"[Fix] VirtualKeyboardController.forceSteamInput was enabled. Turned it off so text fields no longer open Steam's floating keyboard and disable input on PC (a real Steam Deck still gets it).");
}
}
}
private static void FixSteamKeyboardLock(float now, bool force)
{
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
InputController instance = InputController.Instance;
VirtualKeyboardController instance2 = VirtualKeyboardController.Instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || instance.enableInput || !instance2.steamKeyboardLaunched)
{
steamLockSince = -1f;
return;
}
if (steamLockSince < 0f)
{
steamLockSince = now;
LogSteamKeyboardCauseOnce(instance2);
}
float num = (Native.IsWine ? 60f : 0.25f);
if (force || !(now - steamLockSince < num))
{
instance2.steamKeyboardLaunched = false;
instance.enableInput = true;
PopupMessageController instance3 = PopupMessageController.Instance;
if ((Object)(object)instance3 != (Object)null && instance3.active)
{
instance3.SelectDefault();
}
steamLockSince = -1f;
steamLockCount++;
ManualLogSource log = Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(122, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Fix] The game disabled input waiting for Steam's floating keyboard to close. Input re-enabled ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(occurrence ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(steamLockCount);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" this session).");
}
log.LogInfo(val);
if (steamLockCount == 1 || force)
{
Notify(T("Input destravado: o jogo esperava o teclado da Steam (Steam Deck).", "Input unlocked: the game was waiting for Steam's floating keyboard (Steam Deck)."));
}
}
}
private static void LogSteamKeyboardCauseOnce(VirtualKeyboardController vk)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
if (!steamCauseLogged)
{
steamCauseLogged = true;
bool flag = default(bool);
string text;
try
{
flag = SteamUtils.IsSteamRunningOnSteamDeck();
text = flag.ToString();
}
catch (Exception ex)
{
text = "<error: " + ex.GetType().Name + ">";
}
string text2;
try
{
flag = SteamUtils.IsSteamInBigPictureMode();
text2 = flag.ToString();
}
catch (Exception ex2)
{
text2 = "<error: " + ex2.GetType().Name + ">";
}
ManualLogSource log = Log;
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(137, 4, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Diagnostics] Steam keyboard lock cause: forceSteamInput=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(vk.forceSteamInput);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("SteamUtils.IsSteamRunningOnSteamDeck=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", IsSteamInBigPictureMode=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", Proton/Wine=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Native.IsWine);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
log.LogWarning(val);
}
}
private static void FixStaleTextField(float now, bool force)
{
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Expected O, but got Unknown
InputController instance = InputController.Instance;
if ((Object)(object)instance == (Object)null || (!instance.mouseInputMode && !force))
{
staleSince = -1f;
return;
}
EventSystem current = EventSystem.current;
if ((Object)(object)current == (Object)null)
{
staleSince = -1f;
return;
}
GameObject currentSelectedGameObject = current.currentSelectedGameObject;
if ((Object)(object)currentSelectedGameObject == (Object)null)
{
staleSince = -1f;
return;
}
TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
if ((Object)(object)component == (Object)null)
{
staleSince = -1f;
return;
}
bool flag = currentSelectedGameObject.activeInHierarchy && ((Behaviour)component).enabled;
if (flag && component.isFocused && !force)
{
staleSince = -1f;
return;
}
if (staleSince < 0f)
{
staleSince = now;
staleFrames = 0;
}
staleFrames++;
if (force || !flag || (staleFrames >= 10 && now - staleSince >= 0.3f))
{
ManualLogSource log = Log;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(119, 3, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Fix] Text field '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(PathOf(currentSelectedGameObject));
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' was selected without focus ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(active=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(flag);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", focused=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(component.isFocused);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); the game was dropping every key. Selection cleared.");
}
log.LogInfo(val);
current.SetSelectedGameObject((GameObject)null);
staleSince = -1f;
Notify(T("Input destravado: campo de texto preso foi liberado.", "Input unlocked: a stuck text field was released."));
}
}
private static bool IsTypingInTextField()
{
EventSystem current = EventSystem.current;
if ((Object)(object)current == (Object)null)
{
return false;
}
GameObject currentSelectedGameObject = current.currentSelectedGameObject;
if ((Object)(object)currentSelectedGameObject == (Object)null || !currentSelectedGameObject.activeInHierarchy)
{
return false;
}
TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled)
{
return component.isFocused;
}
return false;
}
private static void FixTextInputFlag(float now, bool force)
{
InterfaceController instance = InterfaceController.Instance;
if ((Object)(object)instance == (Object)null || !instance.playerTextInputActive)
{
textFlagSince = -1f;
return;
}
if (IsTypingInTextField())
{
textFlagSince = -1f;
return;
}
if (!force)
{
PopupMessageController instance2 = PopupMessageController.Instance;
InteractionController instance3 = InteractionController.Instance;
MainMenuController instance4 = MainMenuController.Instance;
if (((Object)(object)instance2 != (Object)null && instance2.active) || instance.desktopMode || ((Object)(object)instance3 != (Object)null && instance3.lockedInInteraction != null) || ((Object)(object)instance4 != (Object)null && instance4.mainMenuActive))
{
textFlagSince = -1f;
return;
}
}
if (textFlagSince < 0f)
{
textFlagSince = now;
}
if (force || now - textFlagSince >= 1f)
{
Log.LogInfo((object)"[Fix] InterfaceController.playerTextInputActive was stuck on with no text field open (it blocks interactions). Turned off.");
instance.playerTextInputActive = false;
textFlagSince = -1f;
Notify(T("Input destravado: modo de digitação preso foi desligado.", "Input unlocked: stuck typing mode was turned off."));
}
}
private static void FixGameGates(float now, bool force)
{
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Expected O, but got Unknown
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_021a: Expected O, but got Unknown
InputController instance = InputController.Instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
VirtualKeyboardController instance2 = VirtualKeyboardController.Instance;
bool flag = (Object)(object)instance2 != (Object)null && instance2.steamKeyboardLaunched;
bool flag2 = default(bool);
if (!instance.enableInput && (!flag || force))
{
if (enableInputOffSince < 0f)
{
enableInputOffSince = now;
}
if (force || now - enableInputOffSince >= 1.5f)
{
ManualLogSource log = Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(79, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Fix] InputController.enableInput was false (Steam keyboard open=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(flag);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("). Re-enabled.");
}
log.LogInfo(val);
instance.enableInput = true;
if ((Object)(object)instance2 != (Object)null)
{
instance2.steamKeyboardLaunched = false;
}
enableInputOffSince = -1f;
Notify(T("Input destravado: InputController reativado.", "Input unlocked: InputController re-enabled."));
}
}
else
{
enableInputOffSince = -1f;
}
InteractionController instance3 = InteractionController.Instance;
if ((Object)(object)instance3 != (Object)null && (instance3.inputCooldown > 1f || (force && instance3.inputCooldown > 0f)))
{
ManualLogSource log2 = Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(59, 1, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Fix] InteractionController.inputCooldown was ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(instance3.inputCooldown, "0.00");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(". Reset to 0.");
}
log2.LogInfo(val);
instance3.inputCooldown = 0f;
}
PopupMessageController instance4 = PopupMessageController.Instance;
if ((Object)(object)instance4 != (Object)null)
{
float appearProgress = instance4.appearProgress;
bool active = instance4.active;
if ((!active || !(appearProgress < 1f)) && (active || !(appearProgress > 0f)))
{
popupStillSince = -1f;
}
else if (float.IsNaN(popupLastProgress) || Mathf.Abs(appearProgress - popupLastProgress) > 0.0001f)
{
popupStillSince = now;
}
else if (force || (popupStillSince >= 0f && now - popupStillSince >= 3f))
{
ManualLogSource log3 = Log;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(69, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Fix] Popup animation frozen (active=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(active);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", appearProgress=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(appearProgress, "0.000");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("). Finished it.");
}
log3.LogInfo(val);
instance4.appearProgress = (active ? 1f : 0f);
popupStillSince = -1f;
Notify(T("Input destravado: popup congelado foi finalizado.", "Input unlocked: a frozen popup was finished."));
}
popupLastProgress = instance4.appearProgress;
}
SimpleControlRemappingSOD instance5 = SimpleControlRemappingSOD.Instance;
if ((Object)(object)instance5 != (Object)null && instance5.listeningForRemap && (force || !((Component)instance5).gameObject.activeInHierarchy))
{
if (remapOrphanSince < 0f)
{
remapOrphanSince = now;
}
if (force || now - remapOrphanSince >= 1f)
{
Log.LogInfo((object)"[Fix] Key remapper was still listening without the controls screen open. Stopped.");
instance5.StopMapping(true);
remapOrphanSince = -1f;
}
}
else
{
remapOrphanSince = -1f;
}
}
private static void FixRewired(bool force)
{
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Expected O, but got Unknown
if (!ReInput.isReady)
{
return;
}
Player player = ReInput.players.GetPlayer(0);
if (player == null)
{
return;
}
ControllerHelper controllers = player.controllers;
if (!controllers.hasKeyboard)
{
Log.LogWarning((object)"[Fix] The keyboard was no longer assigned to the player in Rewired. Reassigned.");
controllers.hasKeyboard = true;
Notify(T("Input destravado: teclado reatribuído ao jogador.", "Input unlocked: keyboard reassigned to the player."));
}
if (!controllers.hasMouse)
{
Log.LogWarning((object)"[Fix] The mouse was no longer assigned to the player in Rewired. Reassigned.");
controllers.hasMouse = true;
}
MapHelper maps = controllers.maps;
bool flag2 = default(bool);
for (int i = 0; i < 32; i++)
{
keyboardMaps.Clear();
maps.GetMapsInCategory((ControllerType)0, 0, i, keyboardMaps);
if (keyboardMaps.Count == 0)
{
continue;
}
mouseMaps.Clear();
maps.GetMapsInCategory((ControllerType)1, 0, i, mouseMaps);
bool flag = false;
for (int j = 0; j < mouseMaps.Count; j++)
{
if (mouseMaps[j].enabled)
{
flag = true;
}
}
if (!flag && !force)
{
continue;
}
for (int k = 0; k < keyboardMaps.Count; k++)
{
ControllerMap val = keyboardMaps[k];
if (!val.enabled)
{
ManualLogSource log = Log;
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(68, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Fix] Keyboard map for category ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(i);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (layout ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.layoutId);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") was disabled. Re-enabled.");
}
log.LogWarning(val2);
val.enabled = true;
Notify(T("Input destravado: mapa de teclado religado.", "Input unlocked: keyboard map re-enabled."));
}
}
}
InputController instance = InputController.Instance;
if ((Object)(object)instance != (Object)null && instance.player != null && ((Il2CppObjectBase)instance.player).Pointer != ((Il2CppObjectBase)player).Pointer)
{
Log.LogWarning((object)"[Fix] InputController was using an old Rewired Player. Updated.");
instance.player = player;
}
}
private static void WatchKeyboard(float now)
{
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Expected O, but got Unknown
if (!ReInput.isReady)
{
return;
}
Keyboard val = ((Application.isFocused && Native.IsGameForeground()) ? ReInput.controllers.Keyboard : null);
if (val == null)
{
for (int i = 0; i < WatchVk.Length; i++)
{
osWasDown[i] = false;
}
return;
}
bool flag5 = default(bool);
for (int j = 0; j < WatchVk.Length; j++)
{
bool flag = Native.IsDown(WatchVk[j]);
bool key = val.GetKey(WatchKc[j]);
bool flag2 = UnityKey(WatchKc[j]);
if (flag && !osWasDown[j])
{
pressStart[j] = now;
rewiredSawPress[j] = key;
unitySawPress[j] = flag2;
pressCounted[j] = false;
}
else if (flag)
{
rewiredSawPress[j] |= key;
unitySawPress[j] |= flag2;
}
bool flag3 = !flag && osWasDown[j];
bool flag4 = flag && now - pressStart[j] >= 1f;
if ((flag3 || flag4) && !pressCounted[j])
{
float num = now - pressStart[j];
if (rewiredSawPress[j])
{
if (flag3)
{
missedPresses = 0;
pressCounted[j] = true;
}
}
else if (num >= 0.1f)
{
pressCounted[j] = true;
if (now - lastMissAt > 15f)
{
missedPresses = 0;
}
missedPresses++;
lastMissAt = now;
ManualLogSource log = Log;
BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(87, 4, ref flag5);
if (flag5)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Watchdog] Key ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KeyCode>(WatchKc[j]);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" held for ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(num, "0.00");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s: Windows saw it, ");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Unity ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(unitySawPress[j] ? "saw it" : "did NOT see it");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", Rewired did NOT see it (");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(missedPresses);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" in a row).");
}
log.LogWarning(val2);
if (missedPresses == 2)
{
Log.LogWarning((object)("[Watchdog] Rewired stopped receiving the keyboard.\n" + Snapshot()));
Notify(T("Teclado perdido pelo jogo. Segure ESC ou aperte " + hotkey.Text + " para reparar.", "The game lost the keyboard. Hold ESC or press " + hotkey.Text + " to repair."), 8f);
}
}
}
osWasDown[j] = flag;
}
if (missedPresses >= 3 && Plugin.AutoResetDeadKeyboard.Value && now - lastHardReset > 20f)
{
HardResetKeyboard("automatic: 3 presses in a row ignored by Rewired");
}
}
private static bool UnityKey(KeyCode key)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
if (!unityInputUsable)
{
return false;
}
try
{
return Input.GetKey(key);
}
catch
{
unityInputUsable = false;
return false;
}
}
private static void HardResetKeyboard(string reason)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected O, but got Unknown
lastHardReset = Time.unscaledTime;
missedPresses = 0;
ConfigHelper configuration = ReInput.configuration;
bool nativeKeyboardSupport = configuration.nativeKeyboardSupport;
ManualLogSource log = Log;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(56, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Fix] Reinitializing Rewired (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(reason);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("). nativeKeyboardSupport=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(nativeKeyboardSupport);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
log.LogWarning(val);
if (nativeKeyboardSupport)
{
configuration.nativeKeyboardSupport = false;
}
else
{
ReInput.Reset();
}
refreshAfterResetFrames = 2;
Notify(T("Teclado do Rewired reinicializado.", "Rewired keyboard reinitialized."), 5f);
}
private static void RefreshAfterReset()
{
if (refreshAfterResetFrames-- > 0)
{
return;
}
if (!ReInput.isReady)
{
refreshAfterResetFrames = 1;
return;
}
refreshAfterResetFrames = -1;
Player player = ReInput.players.GetPlayer(0);
if (player == null)
{
return;
}
try
{
IUserDataStore userDataStore = ReInput.userDataStore;
if (userDataStore != null)
{
userDataStore.Load();
}
}
catch (Exception ex)
{
Log.LogWarning((object)("Failed to reload saved controls: " + ex.Message));
}
InputController instance = InputController.Instance;
if ((Object)(object)instance != (Object)null)
{
instance.player = player;
}
VirtualKeyboardController instance2 = VirtualKeyboardController.Instance;
if ((Object)(object)instance2 != (Object)null)
{
instance2._player = player;
}
ControlDetectController instance3 = ControlDetectController.Instance;
if ((Object)(object)instance3 != (Object)null)
{
instance3.player = player;
}
player.controllers.hasKeyboard = true;
player.controllers.hasMouse = true;
FixRewired(force: false);
Log.LogInfo((object)("[Fix] Rewired Player references updated and saved controls reloaded.\n" + Snapshot()));
}
private static void WatchEscape(float now)
{
bool flag = Native.IsDown(27) && Native.IsGameForeground();
bool num = flag && !escWasDown;
escWasDown = flag;
if (num)
{
escDownSince = now;
escHoldFired = false;
}
float value = Plugin.EscapeHoldSeconds.Value;
if (flag && !escHoldFired && value > 0f && now - escDownSince >= value)
{
escHoldFired = true;
EmergencyRepair($"ESC held for {value:0.#}s", forceKeyboardReset: false);
}
if (num && Plugin.LogBlockedEscape.Value && !(now - lastEscLog < 2f))
{
List<string> list = ActiveGates();
if (list.Count != 0)
{
lastEscLog = now;
Log.LogWarning((object)("[Diagnostics] ESC pressed, but the game will drop it because of: " + string.Join("; ", list) + "\n" + Snapshot()));
}
}
}
private static List<string> ActiveGates()
{
List<string> list = new List<string>();
InputController instance = InputController.Instance;
if ((Object)(object)instance == (Object)null)
{
return list;
}
if (!instance.enableInput)
{
VirtualKeyboardController instance2 = VirtualKeyboardController.Instance;
list.Add(((Object)(object)instance2 != (Object)null && instance2.steamKeyboardLaunched) ? "InputController.enableInput=false (waiting for Steam's floating keyboard)" : "InputController.enableInput=false");
}
if (!ReInput.isReady)
{
list.Add("Rewired not ready");
}
PopupMessageController instance3 = PopupMessageController.Instance;
if ((Object)(object)instance3 != (Object)null && ((instance3.active && instance3.appearProgress < 1f) || (!instance3.active && instance3.appearProgress > 0f)))
{
list.Add($"popup animating (active={instance3.active}, appearProgress={instance3.appearProgress:0.000})");
}
InteractionController instance4 = InteractionController.Instance;
if ((Object)(object)instance4 != (Object)null && instance4.inputCooldown > 0f)
{
list.Add($"inputCooldown={instance4.inputCooldown:0.000}");
}
SimpleControlRemappingSOD instance5 = SimpleControlRemappingSOD.Instance;
if ((Object)(object)instance5 != (Object)null && instance5.listeningForRemap)
{
list.Add("key remapper listening");
}
if (instance.player == null)
{
list.Add("InputController.player=null");
}
if (instance.mouseInputMode)
{
EventSystem current = EventSystem.current;
GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null);
TMP_InputField val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<TMP_InputField>() : null);
if ((Object)(object)val2 != (Object)null)
{
list.Add($"text field selected '{PathOf(val)}' (focused={val2.isFocused})");
}
}
return list;
}
private static void CheckHotkey(float now)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Expected O, but got Unknown
if (!Native.IsGameForeground())
{
hotkeyWasDown = (hotkeyKeyWasDown = false);
return;
}
bool keyDown = hotkey.KeyDown;
bool flag = hotkey.IsPressed();
if (keyDown && !hotkeyKeyWasDown && !flag && (Native.CtrlDown || Native.ShiftDown || Native.AltDown))
{
ManualLogSource log = Log;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(81, 4, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Emergency] Main key of ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(hotkey.Text);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" detected, but modifiers incomplete: ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ctrl=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Native.CtrlDown);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", shift=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Native.ShiftDown);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", alt=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Native.AltDown);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
}
log.LogInfo(val);
}
hotkeyKeyWasDown = keyDown;
bool num = flag && !hotkeyWasDown;
hotkeyWasDown = flag;
if (num)
{
bool forceKeyboardReset = now - lastHotkeyAt <= 4f;
lastHotkeyAt = now;
EmergencyRepair(hotkey.Text, forceKeyboardReset);
}
}
private static void EmergencyRepair(string source, bool forceKeyboardReset)
{
float now = Time.unscaledTime;
Log.LogInfo((object)("[Emergency] " + source + ". State BEFORE repair:\n" + Snapshot()));
Safe("em-steamflag", PreventSteamKeyboardLock);
Safe("em-steamkb", delegate
{
FixSteamKeyboardLock(now, force: true);
});
Safe("em-textfield", delegate
{
FixStaleTextField(now, force: true);
});
Safe("em-textflag", delegate
{
FixTextInputFlag(now, force: true);
});
Safe("em-gates", delegate
{
FixGameGates(now, force: true);
});
Safe("em-rewired", delegate
{
FixRewired(force: true);
});
Safe("em-mode", ForceMouseModeWithoutJoysticks);
Safe("em-vkb", CloseVirtualKeyboardInMouseMode);
bool keyboardDead = missedPresses > 0 && now - lastMissAt < 60f;
if (keyboardDead || forceKeyboardReset)
{
Safe("em-reset", delegate
{
HardResetKeyboard(keyboardDead ? (source + ": keyboard detected as dead") : (source + " pressed twice"));
});
}
else
{
Notify(T("Reparo de input aplicado. Se o teclado continuar sem responder, aperte " + hotkey.Text + " duas vezes.", "Input repair applied. If the keyboard still does not respond, press " + hotkey.Text + " twice."), 6f);
}
Log.LogInfo((object)("[Emergency] State AFTER repair:\n" + Snapshot()));
}
private static void ForceMouseModeWithoutJoysticks()
{
InputController instance = InputController.Instance;
if (!((Object)(object)instance == (Object)null) && !instance.mouseInputMode && ReInput.isReady && ReInput.controllers.joystickCount <= 0)
{
Log.LogInfo((object)"[Fix] Game was in controller mode with no controller connected. Switched back to keyboard/mouse.");
instance.SetMouseInputMode(true, true);
}
}
private static void CloseVirtualKeyboardInMouseMode()
{
InputController instance = InputController.Instance;
VirtualKeyboardController instance2 = VirtualKeyboardController.Instance;
if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance2 == (Object)null) && instance.mouseInputMode && instance2.isActive)
{
Log.LogInfo((object)"[Fix] On-screen (controller) keyboard was open in keyboard/mouse mode. Closed.");
instance2.DeactivateVirtualKeyboard();
}
}
private static void LogStartupOnce()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
if (!startupLogged && ReInput.isReady)
{
startupLogged = true;
ConfigHelper configuration = ReInput.configuration;
ManualLogSource log = Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(123, 6, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Rewired ready: nativeKeyboardSupport=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(configuration.nativeKeyboardSupport);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", nativeMouseSupport=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(configuration.nativeMouseSupport);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ignoreInputWhenAppNotInFocus=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(configuration.ignoreInputWhenAppNotInFocus);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", source=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<WindowsStandalonePrimaryInputSource>(configuration.windowsStandalonePrimaryInputSource);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("updateLoop=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<UpdateLoopSetting>(configuration.updateLoop);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", joysticks=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(ReInput.controllers.joystickCount);
}
log.LogInfo(val);
}
}
private static string Snapshot()
{
StringBuilder sb = new StringBuilder();
Add("window focused (Windows/Unity)", () => $"{Native.IsGameForeground()} / {Application.isFocused}");
Add("InputController", () => (!((Object)(object)InputController.Instance == (Object)null)) ? $"enableInput={InputController.Instance.enableInput}, mouseInputMode={InputController.Instance.mouseInputMode}, player={((InputController.Instance.player == null) ? "null" : "ok")}" : "null");
Add("UI selection", delegate
{
EventSystem current = EventSystem.current;
if ((Object)(object)current == (Object)null)
{
return "no EventSystem";
}
GameObject currentSelectedGameObject = current.currentSelectedGameObject;
if ((Object)(object)currentSelectedGameObject == (Object)null)
{
return "none";
}
TMP_InputField component = currentSelectedGameObject.GetComponent<TMP_InputField>();
return $"'{PathOf(currentSelectedGameObject)}' active={currentSelectedGameObject.activeInHierarchy}" + (((Object)(object)component != (Object)null) ? $" TMP_InputField focused={component.isFocused}" : "");
});
Add("active gates", delegate
{
List<string> list = ActiveGates();
return (list.Count != 0) ? string.Join("; ", list) : "none";
});
Add("InterfaceController", () => (!((Object)(object)InterfaceController.Instance == (Object)null)) ? $"playerTextInputActive={InterfaceController.Instance.playerTextInputActive}, desktopMode={InterfaceController.Instance.desktopMode}" : "null");
Add("SessionData.play", delegate
{
SessionData instance = SessionData.Instance;
return (instance != null) ? new bool?(instance.play) : ((bool?)null);
});
Add("MainMenuController.mainMenuActive", delegate
{
MainMenuController instance = MainMenuController.Instance;
return (instance != null) ? new bool?(instance.mainMenuActive) : ((bool?)null);
});
Add("CutSceneController.cutSceneActive", delegate
{
CutSceneController instance = CutSceneController.Instance;
return (instance != null) ? new bool?(instance.cutSceneActive) : ((bool?)null);
});
Add("Popup", () => (!((Object)(object)PopupMessageController.Instance == (Object)null)) ? $"active={PopupMessageController.Instance.active}, appearProgress={PopupMessageController.Instance.appearProgress:0.000}" : "null");
Add("InteractionController", () => (!((Object)(object)InteractionController.Instance == (Object)null)) ? $"inputCooldown={InteractionController.Instance.inputCooldown:0.000}, lockedIn={InteractionController.Instance.lockedInInteraction != null}" : "null");
Add("Player", delegate
{
Player instance = Player.Instance;
if ((Object)(object)instance == (Object)null)
{
return "null";
}
FirstPersonController fps = instance.fps;
return $"transitionActive={instance.transitionActive}, " + (((Object)(object)fps == (Object)null) ? "fps=null" : $"enableMovement={fps.enableMovement}, enableLook={fps.enableLook}");
});
Add("VirtualKeyboard", () => (!((Object)(object)VirtualKeyboardController.Instance == (Object)null)) ? $"isActive={VirtualKeyboardController.Instance.isActive}, steamKeyboardLaunched={VirtualKeyboardController.Instance.steamKeyboardLaunched}, forceSteamInput={VirtualKeyboardController.Instance.forceSteamInput}" : "null");
Add("Remapper listening", delegate
{
SimpleControlRemappingSOD instance = SimpleControlRemappingSOD.Instance;
return (instance != null) ? new bool?(instance.listeningForRemap) : ((bool?)null);
});
Add("Cursor", () => $"lock={Cursor.lockState}, visible={Cursor.visible}");
Add("Rewired", delegate
{
if (ReInput.isReady)
{
Player player = ReInput.players.GetPlayer(0);
ConfigHelper configuration = ReInput.configuration;
InputController instance = InputController.Instance;
bool value = (Object)(object)instance == (Object)null || instance.player == null || ((Il2CppObjectBase)instance.player).Pointer == ((Il2CppObjectBase)player).Pointer;
return $"hasKeyboard={player.controllers.hasKeyboard}, hasMouse={player.controllers.hasMouse}, keyboard.GetAnyButton={((Controller)ReInput.controllers.Keyboard).GetAnyButton()}, player.GetAnyButton={player.GetAnyButton()}, gameUsesCurrentPlayer={value}, nativeKeyboard={configuration.nativeKeyboardSupport}, joysticks={ReInput.controllers.joystickCount}";
}
return "not ready";
});
Add("keyboard maps", delegate
{
if (!ReInput.isReady)
{
return "-";
}
MapHelper maps = ReInput.players.GetPlayer(0).controllers.maps;
List<string> list = new List<string>();
for (int i = 0; i < 32; i++)
{
keyboardMaps.Clear();
maps.GetMapsInCategory((ControllerType)0, 0, i, keyboardMaps);
for (int j = 0; j < keyboardMaps.Count; j++)
{
list.Add($"cat{i}/lay{keyboardMaps[j].layoutId}={(keyboardMaps[j].enabled ? "on" : "OFF")}");
}
}
return (list.Count != 0) ? string.Join(", ", list) : "none";
});
Add("keyboard watchdog", () => $"ignored presses in a row={missedPresses}");
return sb.ToString().TrimEnd('\n');
void Add(string name, Func<object> value)
{
string value2;
try
{
value2 = value()?.ToString() ?? "null";
}
catch (Exception ex)
{
value2 = "<error: " + ex.GetType().Name + ">";
}
sb.Append(" ").Append(name).Append(" = ")
.Append(value2)
.Append('\n');
}
}
private static string PathOf(GameObject go)
{
if ((Object)(object)go == (Object)null)
{
return "null";
}
string text = ((Object)go).name;
Transform parent = go.transform.parent;
int num = 0;
while ((Object)(object)parent != (Object)null && num < 3)
{
text = ((Object)parent).name + "/" + text;
num++;
parent = parent.parent;
}
return text;
}
private static string T(string portuguese, string english)
{
if (!Portuguese)
{
return english;
}
return portuguese;
}
private static void Notify(string text, float seconds = 4f)
{
if (Plugin.ShowMessages.Value)
{
message = text;
messageUntil = Time.unscaledTime + seconds;
}
}
private static void Safe(string key, Action action)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
try
{
action();
}
catch (Exception ex)
{
float unscaledTime = Time.unscaledTime;
if (!errorThrottle.TryGetValue(key, out var value) || !(unscaledTime - value < 30f))
{
errorThrottle[key] = unscaledTime;
ManualLogSource log = Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(3, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(key);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
}
static Guard()
{
KeyCode[] array = new KeyCode[13];
RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
WatchKc = (KeyCode[])(object)array;
osWasDown = new bool[WatchVk.Length];
rewiredSawPress = new bool[WatchVk.Length];
unitySawPress = new bool[WatchVk.Length];
pressCounted = new bool[WatchVk.Length];
pressStart = new float[WatchVk.Length];
lastMissAt = -999f;
unityInputUsable = true;
lastHardReset = -999f;
refreshAfterResetFrames = -1;
escDownSince = -1f;
lastEscLog = -999f;
guiUsable = true;
errorThrottle = new Dictionary<string, float>();
}
}
public class GuardBehaviour : MonoBehaviour
{
public GuardBehaviour(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
Guard.Update();
}
private void LateUpdate()
{
Guard.LateUpdate();
}
private void OnGUI()
{
Guard.OnGUI();
}
}
internal static class Native
{
private static readonly uint OwnPid = (uint)Environment.ProcessId;
public static readonly bool IsWine = DetectWine();
public static bool CtrlDown
{
get
{
if (!IsDown(17) && !IsDown(162))
{
return IsDown(163);
}
return true;
}
}
public static bool ShiftDown
{
get
{
if (!IsDown(16) && !IsDown(160))
{
return IsDown(161);
}
return true;
}
}
public static bool AltDown
{
get
{
if (!IsDown(18) && !IsDown(164))
{
return IsDown(165);
}
return true;
}
}
[DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr GetModuleHandle(string moduleName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr module, string procName);
private static bool DetectWine()
{
try
{
IntPtr moduleHandle = GetModuleHandle("ntdll.dll");
return moduleHandle != IntPtr.Zero && GetProcAddress(moduleHandle, "wine_get_version") != IntPtr.Zero;
}
catch
{
return false;
}
}
public static bool IsDown(int vk)
{
return (GetAsyncKeyState(vk) & 0x8000) != 0;
}
public static bool IsGameForeground()
{
IntPtr foregroundWindow = GetForegroundWindow();
if (foregroundWindow == IntPtr.Zero)
{
return false;
}
GetWindowThreadProcessId(foregroundWindow, out var processId);
return processId == OwnPid;
}
}
internal sealed class Hotkey
{
public readonly bool Ctrl;
public readonly bool Shift;
public readonly bool Alt;
public readonly int Vk;
public readonly string Text;
public bool KeyDown => Native.IsDown(Vk);
private Hotkey(bool ctrl, bool shift, bool alt, int vk, string text)
{
Ctrl = ctrl;
Shift = shift;
Alt = alt;
Vk = vk;
Text = text;
}
public bool IsPressed()
{
if (KeyDown && (!Ctrl || Native.CtrlDown) && (!Shift || Native.ShiftDown))
{
if (Alt)
{
return Native.AltDown;
}
return true;
}
return false;
}
public static Hotkey Parse(string s)
{
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Expected O, but got Unknown
bool ctrl = false;
bool shift = false;
bool alt = false;
int num = 0;
string[] array = (s ?? "").Split('+');
for (int i = 0; i < array.Length; i++)
{
string text = array[i].Trim().ToUpperInvariant();
if (text.Length != 0)
{
switch (text)
{
case "CTRL":
case "CONTROL":
ctrl = true;
break;
case "SHIFT":
shift = true;
break;
case "ALT":
alt = true;
break;
default:
num = KeyToVk(text);
break;
}
}
}
if (num == 0)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Invalid hotkey '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(s);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("', using Ctrl+Shift+K.");
}
logger.LogWarning(val);
return new Hotkey(ctrl: true, shift: true, alt: false, 75, "Ctrl+Shift+K");
}
return new Hotkey(ctrl, shift, alt, num, s.Trim());
}
private static int KeyToVk(string p)
{
if (p.Length == 1 && ((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= '0' && p[0] <= '9')))
{
return p[0];
}
if (p.Length >= 2 && p[0] == 'F' && int.TryParse(p.Substring(1), out var result) && result >= 1 && result <= 24)
{
return 112 + result - 1;
}
return p switch
{
"HOME" => 36,
"END" => 35,
"INSERT" => 45,
"DELETE" => 46,
"PAGEUP" => 33,
"PAGEDOWN" => 34,
"PAUSE" => 19,
"BACKSPACE" => 8,
_ => 0,
};
}
}
[BepInPlugin("sod.inputsoftlockfix", "Input Softlock Fix", "1.2.1")]
public class Plugin : BasePlugin
{
public const string Guid = "sod.inputsoftlockfix";
public const string Name = "Input Softlock Fix";
public const string Version = "1.2.1";
internal static ManualLogSource Logger;
internal static ConfigEntry<string> EmergencyHotkey;
internal static ConfigEntry<float> EscapeHoldSeconds;
internal static ConfigEntry<bool> PreventSteamKeyboardLock;
internal static ConfigEntry<bool> FixSteamKeyboardLock;
internal static ConfigEntry<bool> FixStaleTextField;
internal static ConfigEntry<bool> FixTextInputFlag;
internal static ConfigEntry<bool> FixGameGates;
internal static ConfigEntry<bool> FixRewiredState;
internal static ConfigEntry<bool> WatchKeyboardDevice;
internal static ConfigEntry<bool> AutoResetDeadKeyboard;
internal static ConfigEntry<bool> ShowMessages;
internal static ConfigEntry<bool> LogBlockedEscape;
public override void Load()
{
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Expected O, but got Unknown
Logger = ((BasePlugin)this).Log;
EmergencyHotkey = ((BasePlugin)this).Config.Bind<string>("General", "EmergencyHotkey", "Ctrl+Shift+K", "Emergency hotkey, read directly from Windows (works even when the game ignores the keyboard). Forces every known input repair. Pressing it twice within 4s also reinitializes Rewired's keyboard. Format: [Ctrl+][Shift+][Alt+]Key (A-Z, 0-9, F1-F24, Home, End, Insert, Delete, PageUp, PageDown, Pause, Backspace).");
EscapeHoldSeconds = ((BasePlugin)this).Config.Bind<float>("General", "EscapeHoldSeconds", 2f, "Holding ESC for this many seconds runs the same repair as the emergency hotkey. Read directly from Windows. 0 disables.");
PreventSteamKeyboardLock = ((BasePlugin)this).Config.Bind<bool>("Fixes", "PreventSteamKeyboardLock", true, "Main fix. The game ships with VirtualKeyboardController.forceSteamInput enabled, so on PC every text field opens Steam's floating keyboard (a Steam Deck feature), disables all keyboard input and waits for Steam to report the keyboard was closed. If that report never arrives, the keyboard stays dead. This turns the flag off; a real Steam Deck keeps using Steam's keyboard because the game checks for it separately.");
FixSteamKeyboardLock = ((BasePlugin)this).Config.Bind<bool>("Fixes", "FixSteamKeyboardLock", true, "Safety net for the same lock: if input is disabled waiting for Steam's floating keyboard, turn it back on after 0.25s on Windows, or after 60s on Proton/Steam Deck.");
FixStaleTextField = ((BasePlugin)this).Config.Bind<bool>("Fixes", "FixStaleTextField", true, "In keyboard/mouse mode the game drops every key while the selected UI object has a text field, without checking whether you are still typing. Clears the selection when the text field is no longer focused.");
FixTextInputFlag = ((BasePlugin)this).Config.Bind<bool>("Fixes", "FixTextInputFlag", true, "Clears InterfaceController.playerTextInputActive when it is stuck on with no text field open (it blocks every interaction with objects).");
FixGameGates = ((BasePlugin)this).Config.Bind<bool>("Fixes", "FixGameGates", true, "Repairs other states that make the game drop input: InputController.enableInput stuck off for another reason, stuck interaction cooldown, frozen popup animation, key remapper still listening after its screen closed.");
FixRewiredState = ((BasePlugin)this).Config.Bind<bool>("Fixes", "FixRewiredState", true, "Keeps the keyboard and mouse assigned to the player in Rewired, keyboard maps enabled, and the game pointing at Rewired's current Player object.");
WatchKeyboardDevice = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "WatchKeyboardDevice", true, "Compares the keys Windows sees with the keys Rewired sees. If Rewired stops receiving the keyboard, logs it and shows an on-screen hint.");
AutoResetDeadKeyboard = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "AutoResetDeadKeyboard", false, "If true, reinitializes Rewired's keyboard automatically when it is detected as dead (3 presses in a row ignored). If false, only warns; the reset stays on the emergency hotkey.");
ShowMessages = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "ShowMessages", true, "Show short on-screen messages when a repair is applied.");
LogBlockedEscape = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "LogBlockedEscape", true, "When ESC is pressed but the game is about to drop it, write a full input-state snapshot to the log.");
if (!ClassInjector.IsTypeRegisteredInIl2Cpp<GuardBehaviour>())
{
ClassInjector.RegisterTypeInIl2Cpp<GuardBehaviour>();
}
((BasePlugin)this).AddComponent<GuardBehaviour>();
Guard.Init();
ManualLogSource log = ((BasePlugin)this).Log;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(53, 5, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Input Softlock Fix");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.2.1");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded. Emergency: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(EmergencyHotkey.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" or hold ESC for ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(EscapeHoldSeconds.Value, "0.#");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("s. Proton/Wine=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Native.IsWine);
}
log.LogInfo(val);
}
}
}