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 RefocusGuard v0.1.3
plugins\RefocusGuard\RefocusGuard.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("RefocusGuard")] [assembly: AssemblyDescription("Consumes mouse input used to refocus Valheim after Alt-Tab")] [assembly: AssemblyFileVersion("0.1.3.0")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyCompany("Daishi11")] [assembly: AssemblyProduct("RefocusGuard")] [assembly: AssemblyVersion("0.1.3.0")] namespace Daishi11.RefocusGuard; [BepInPlugin("daishi11.valheim.refocusguard", "Refocus Guard", "0.1.3")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "Update")] private static class PlayerUpdateFocusPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Player __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } if (!Application.isFocused) { if (!sawFocusLoss) { sawFocusLoss = true; ResetGuard(); } } else if (sawFocusLoss && !guardActive) { BeginGuard(); } } } [HarmonyPatch] private static class PlayerAttackInputPatch { private static IEnumerable<MethodBase> TargetMethods() { return FindInstanceMethods(typeof(Player), "PlayerAttackInput"); } [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Player __instance) { if (!IsLocalPlayer(__instance) || !IsGuardingGameplay()) { return true; } return false; } } [HarmonyPatch] private static class PlayerUpdatePlacementPatch { private static IEnumerable<MethodBase> TargetMethods() { return FindInstanceMethods(typeof(Player), "UpdatePlacement"); } [HarmonyPriority(800)] [HarmonyPrefix] private static bool Prefix(Player __instance) { if (!IsLocalPlayer(__instance) || !IsGuardingGameplay()) { return true; } return false; } } [HarmonyPatch] private static class HumanoidStartAttackPatch { private static IEnumerable<MethodBase> TargetMethods() { return FindInstanceMethods(typeof(Humanoid), "StartAttack"); } [HarmonyPriority(800)] [HarmonyPrefix] private static bool Prefix(Humanoid __instance) { Player player = (Player)(object)((__instance is Player) ? __instance : null); if (!IsLocalPlayer(player) || !IsGuardingGameplay()) { return true; } return false; } } [HarmonyPatch(typeof(ZInput), "GetButton", new Type[] { typeof(string) })] private static class ZInputGetButtonPatch { private static bool Prefix(string name, ref bool __result) { if (!ShouldBlockAction(name)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZInput), "GetButtonDown", new Type[] { typeof(string) })] private static class ZInputGetButtonDownPatch { private static bool Prefix(string name, ref bool __result) { if (!ShouldBlockAction(name)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZInput), "GetButtonUp", new Type[] { typeof(string) })] private static class ZInputGetButtonUpPatch { private static bool Prefix(string name, ref bool __result) { if (!ShouldBlockAction(name)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZInput), "GetMouseButton", new Type[] { typeof(int) })] private static class ZInputGetMouseButtonPatch { private static bool Prefix(int button, ref bool __result) { if (!ShouldBlockMouseButton(button)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZInput), "GetMouseButtonDown", new Type[] { typeof(int) })] private static class ZInputGetMouseButtonDownPatch { private static bool Prefix(int button, ref bool __result) { if (!ShouldBlockMouseButton(button)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(ZInput), "GetMouseButtonUp", new Type[] { typeof(int) })] private static class ZInputGetMouseButtonUpPatch { private static bool Prefix(int button, ref bool __result) { if (!ShouldBlockMouseButton(button)) { return true; } __result = false; return false; } } public const string PluginGuid = "daishi11.valheim.refocusguard"; public const string PluginName = "Refocus Guard"; public const string PluginVersion = "0.1.3"; private const int LeftMouseMask = 1; private const int RightMouseMask = 2; private const int MiddleMouseMask = 4; private const int GuardedMouseMask = 7; private const float FocusSafetyWindow = 0.15f; private Harmony harmony; private static bool sawFocusLoss; private static bool guardActive; private static float guardUntilUnscaledTime; private static int heldMouseMask; private static int releaseMouseMask; private void Awake() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown sawFocusLoss = !Application.isFocused; harmony = new Harmony("daishi11.valheim.refocusguard"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Refocus Guard active. Mouse clicks used to refocus Valheim will be consumed until the pressed button is released."); } private void OnDestroy() { ResetGuard(); if (harmony != null) { harmony.UnpatchSelf(); } } private void OnApplicationFocus(bool hasFocus) { if (!hasFocus) { sawFocusLoss = true; ResetGuard(); } else if (sawFocusLoss) { BeginGuard(); } } private static void BeginGuard() { sawFocusLoss = false; guardActive = true; guardUntilUnscaledTime = Time.unscaledTime + 0.15f; heldMouseMask = ReadRawMouseMask(); releaseMouseMask = 0; } private static void ResetGuard() { guardActive = false; guardUntilUnscaledTime = 0f; heldMouseMask = 0; releaseMouseMask = 0; } private void Update() { if (!Application.isFocused) { if (!sawFocusLoss) { sawFocusLoss = true; ResetGuard(); } return; } if (sawFocusLoss && !guardActive) { BeginGuard(); } if (guardActive) { int num = ReadRawMouseMask(); if (Time.unscaledTime <= guardUntilUnscaledTime) { heldMouseMask |= num; } int num2 = heldMouseMask & ~num; if (num2 != 0) { releaseMouseMask |= num2; } heldMouseMask &= num; if (Time.unscaledTime > guardUntilUnscaledTime && heldMouseMask == 0) { guardActive = false; } } } private void LateUpdate() { releaseMouseMask = 0; } private static int ReadRawMouseMask() { int num = 0; if (Input.GetMouseButton(0)) { num |= 1; } if (Input.GetMouseButton(1)) { num |= 2; } if (Input.GetMouseButton(2)) { num |= 4; } return num; } private static bool ShouldBlockMouseButton(int button) { if (!guardActive || button < 0 || button > 2) { return false; } int num = 1 << button; if (Time.unscaledTime <= guardUntilUnscaledTime && (7 & num) != 0) { return true; } if ((heldMouseMask & num) == 0) { return (releaseMouseMask & num) != 0; } return true; } private static bool TryGetActionMouseButton(string action, out int button) { button = -1; if (string.IsNullOrEmpty(action)) { return false; } switch (action) { case "Attack": button = 0; return true; case "Block": case "BuildMenu": button = 1; return true; case "SecondaryAttack": case "Remove": button = 2; return true; default: return false; } } private static bool ShouldBlockAction(string action) { if (TryGetActionMouseButton(action, out var button)) { return ShouldBlockMouseButton(button); } return false; } private static bool IsGuardingGameplay() { if (!sawFocusLoss && !guardActive) { return !Application.isFocused; } return true; } private static bool IsLocalPlayer(Player player) { if ((Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)Player.m_localPlayer; } return false; } private static IEnumerable<MethodBase> FindInstanceMethods(Type type, string name) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo candidate in methods) { if (candidate.Name == name) { yield return candidate; } } } }