Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of NoBackgroundHover v1.0.0
BepInEx/plugins/NoBackgroundHover/NoBackgroundHover.dll
Decompiled 5 hours agousing System; using System.Diagnostics; 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.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Zenoyui")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Zenoyui")] [assembly: AssemblyDescription("Stops REPO menu hover input while the game window is not focused.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("NoBackgroundHover")] [assembly: AssemblyTitle("NoBackgroundHover")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace NoBackgroundHover { [BepInPlugin("ru.zenoyui.NoBackgroundHover", "No Background Hover", "1.0.0")] public sealed class NoBackgroundHoverPlugin : BaseUnityPlugin { private static class UiMouseHoverPatch { public static bool Prefix(ref bool __result) { if (FocusGate.UiInputAllowed) { return true; } __result = false; return false; } } private static class AllowOnlyFocusedPatch { public static bool Prefix() { return FocusGate.UiInputAllowed; } } private sealed class FocusLoop : MonoBehaviour { private bool _wasAllowed = true; private float _nextClear; private void Update() { bool uiInputAllowed = FocusGate.UiInputAllowed; if (!uiInputAllowed && (_wasAllowed || Time.unscaledTime >= _nextClear)) { _nextClear = Time.unscaledTime + 0.25f; ClearHoverState(); } _wasAllowed = uiInputAllowed; } private void OnApplicationFocus(bool focus) { FocusGate.Invalidate(); if (!focus) { ClearHoverState(); } } private void OnApplicationPause(bool pause) { FocusGate.Invalidate(); if (pause) { ClearHoverState(); } } } private static class FocusGate { private static readonly uint CurrentProcessId = (uint)Process.GetCurrentProcess().Id; private static int _cachedFrame = -1; private static bool _cachedAllowed = true; public static bool UiInputAllowed { get { int frameCount = Time.frameCount; if (_cachedFrame == frameCount) { return _cachedAllowed; } _cachedFrame = frameCount; _cachedAllowed = ReadFocusState(); return _cachedAllowed; } } public static void Invalidate() { _cachedFrame = -1; } private static bool ReadFocusState() { if (!Application.isFocused) { return false; } if (!IsWindowsPlayer()) { return true; } if (!TryGetForegroundProcessId(out var processId)) { return true; } return processId == CurrentProcessId; } private static bool IsWindowsPlayer() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 RuntimePlatform platform = Application.platform; if ((int)platform != 2) { return (int)platform == 7; } return true; } private static bool TryGetForegroundProcessId(out uint processId) { processId = 0u; try { IntPtr foregroundWindow = GetForegroundWindow(); if (foregroundWindow == IntPtr.Zero) { return false; } GetWindowThreadProcessId(foregroundWindow, out processId); return processId != 0; } catch { processId = 0u; return false; } } [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); } private const string PluginGuid = "ru.zenoyui.NoBackgroundHover"; private const string PluginName = "No Background Hover"; private const string PluginVersion = "1.0.0"; private static ManualLogSource Log; private static Harmony _harmony; private static Type? _menuManagerType; private static Type? _menuButtonType; private static Type? _menuElementHoverType; private static Type? _menuSliderType; private static Type? _menuSelectionBoxType; private static FieldInfo? _menuManagerInstanceField; private static FieldInfo? _currentMenuIdField; private static FieldInfo? _mouseHoldPositionField; private static FieldInfo? _menuHoverField; private static FieldInfo? _menuButtonHoveringField; private static FieldInfo? _menuButtonHoverTimerField; private static FieldInfo? _menuButtonClickedField; private static FieldInfo? _menuButtonClickTimerField; private static FieldInfo? _menuButtonStateField; private static FieldInfo? _menuElementIsHoveringField; private static FieldInfo? _menuSliderHoveringField; private static FieldInfo? _selectionBoxActiveTargetTimerField; private static FieldInfo? _selectionBoxClickTimerField; private static MethodInfo? _menuButtonPointerExitMethod; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("ru.zenoyui.NoBackgroundHover"); CacheGameFields(); PatchGameHover(); PatchUnityEventSystem(); GameObject val = new GameObject("NoBackgroundHover.FocusLoop"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<FocusLoop>(); Log.LogInfo((object)"mod: init (id=ru.zenoyui.NoBackgroundHover, ver=1.0.0)"); } private static void CacheGameFields() { _menuManagerType = AccessTools.TypeByName("MenuManager"); _menuButtonType = AccessTools.TypeByName("MenuButton"); _menuElementHoverType = AccessTools.TypeByName("MenuElementHover"); _menuSliderType = AccessTools.TypeByName("MenuSlider"); _menuSelectionBoxType = AccessTools.TypeByName("MenuSelectionBox"); _menuManagerInstanceField = Field(_menuManagerType, "instance"); _currentMenuIdField = Field(_menuManagerType, "currentMenuID"); _mouseHoldPositionField = Field(_menuManagerType, "mouseHoldPosition"); _menuHoverField = Field(_menuManagerType, "menuHover"); _menuButtonHoveringField = Field(_menuButtonType, "hovering"); _menuButtonHoverTimerField = Field(_menuButtonType, "hoverTimer"); _menuButtonClickedField = Field(_menuButtonType, "clicked"); _menuButtonClickTimerField = Field(_menuButtonType, "clickTimer"); _menuButtonStateField = Field(_menuButtonType, "buttonState"); _menuButtonPointerExitMethod = Method(_menuButtonType, "OnPointerExit", typeof(PointerEventData)); _menuElementIsHoveringField = Field(_menuElementHoverType, "isHovering"); _menuSliderHoveringField = Field(_menuSliderType, "hovering"); _selectionBoxActiveTargetTimerField = Field(_menuSelectionBoxType, "activeTargetTimer"); _selectionBoxClickTimerField = Field(_menuSelectionBoxType, "clickTimer"); } private static FieldInfo? Field(Type? type, string name) { if (!(type == null)) { return AccessTools.Field(type, name); } return null; } private static MethodInfo? Method(Type? type, string name, params Type[] args) { if (!(type == null)) { return AccessTools.Method(type, name, args, (Type[])null); } return null; } private static void PatchGameHover() { Type type = AccessTools.TypeByName("SemiFunc"); Type type2 = AccessTools.TypeByName("MenuPage"); MethodInfo methodInfo = null; if (type != null && type2 != null) { methodInfo = AccessTools.Method(type, "UIMouseHover", new Type[5] { type2, typeof(RectTransform), typeof(string), typeof(float), typeof(float) }, (Type[])null); } if (methodInfo == null) { methodInfo = Method(type, "UIMouseHover"); } PatchPrefix(methodInfo, typeof(UiMouseHoverPatch), "Prefix", "SemiFunc.UIMouseHover", required: true); PatchPrefix(Method(type, "MenuSelectionBoxTargetSet"), typeof(AllowOnlyFocusedPatch), "Prefix", "SemiFunc.MenuSelectionBoxTargetSet", required: false); PatchPrefix(Method(_menuManagerType, "MenuEffectHover"), typeof(AllowOnlyFocusedPatch), "Prefix", "MenuManager.MenuEffectHover", required: false); PatchPrefix(Method(_menuButtonType, "OnPointerEnter", typeof(PointerEventData)), typeof(AllowOnlyFocusedPatch), "Prefix", "MenuButton.OnPointerEnter", required: false); PatchPrefix(Method(_menuButtonType, "OnPointerClick", typeof(PointerEventData)), typeof(AllowOnlyFocusedPatch), "Prefix", "MenuButton.OnPointerClick", required: false); } private static void PatchUnityEventSystem() { PatchProcess("UnityEngine.EventSystems.StandaloneInputModule"); PatchProcess("UnityEngine.EventSystems.TouchInputModule"); PatchProcess("UnityEngine.InputSystem.UI.InputSystemUIInputModule"); } private static void PatchProcess(string typeName) { PatchPrefix(Method(AccessTools.TypeByName(typeName), "Process"), typeof(AllowOnlyFocusedPatch), "Prefix", typeName + ".Process", required: false); } private static void PatchPrefix(MethodInfo? original, Type patchType, string patchName, string label, bool required) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(patchType, patchName, (Type[])null, (Type[])null); if (original == null || methodInfo == null) { if (required) { Log.LogWarning((object)("patch: missing (target=" + label + ")")); } else { Log.LogInfo((object)("patch: skip (target=" + label + ")")); } } else { _harmony.Patch((MethodBase)original, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)("patch: ok (target=" + label + ")")); } } catch (Exception ex) { Log.LogWarning((object)("patch: fail (target=" + label + ", err=" + ex.GetType().Name + ", msg=" + ex.Message + ")")); } } private static void ClearHoverState() { ClearEventSystem(); ClearMenuManager(); ClearObjects(_menuButtonType, ClearMenuButton); ClearObjects(_menuElementHoverType, ClearMenuElementHover); ClearObjects(_menuSliderType, ClearMenuSlider); ClearObjects(_menuSelectionBoxType, ClearMenuSelectionBox); } private static void ClearEventSystem() { try { EventSystem current = EventSystem.current; if ((Object)(object)current != (Object)null) { current.SetSelectedGameObject((GameObject)null); } } catch { } } private static void ClearMenuManager() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) try { object obj = _menuManagerInstanceField?.GetValue(null); if (obj != null) { _currentMenuIdField?.SetValue(obj, ""); _mouseHoldPositionField?.SetValue(obj, Vector2.zero); _menuHoverField?.SetValue(obj, 0f); } } catch { } } private static void ClearObjects(Type? type, Action<object> clear) { if (type == null) { return; } Object[] array; try { array = Resources.FindObjectsOfTypeAll(type); } catch { return; } Object[] array2 = array; foreach (Object val in array2) { if (val != (Object)null && IsSceneObject(val)) { try { clear(val); } catch { } } } } private static bool IsSceneObject(Object obj) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Component val = (Component)(object)((obj is Component) ? obj : null); if (val != null) { Scene scene = val.gameObject.scene; return ((Scene)(ref scene)).IsValid(); } GameObject val2 = (GameObject)(object)((obj is GameObject) ? obj : null); if (val2 != null) { Scene scene2 = val2.scene; return ((Scene)(ref scene2)).IsValid(); } return false; } private static void ClearMenuButton(object obj) { _menuButtonPointerExitMethod?.Invoke(obj, new object[1]); _menuButtonHoveringField?.SetValue(obj, false); _menuButtonHoverTimerField?.SetValue(obj, 0f); _menuButtonClickedField?.SetValue(obj, false); _menuButtonClickTimerField?.SetValue(obj, 0f); _menuButtonStateField?.SetValue(obj, 2); } private static void ClearMenuElementHover(object obj) { _menuElementIsHoveringField?.SetValue(obj, false); } private static void ClearMenuSlider(object obj) { _menuSliderHoveringField?.SetValue(obj, false); } private static void ClearMenuSelectionBox(object obj) { _selectionBoxActiveTargetTimerField?.SetValue(obj, 0f); _selectionBoxClickTimerField?.SetValue(obj, 0f); } } }