Decompiled source of EpicLootVRFix v1.0.17

EpicLootVRFix.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("EpicLootVRFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EpicLootVRFix")]
[assembly: AssemblyTitle("EpicLootVRFix")]
[assembly: AssemblyVersion("1.0.0.0")]
public static class EpicLootVRControls
{
	private static Coroutine _inputCoroutine;

	private static Type _vrControlsType;

	private static PropertyInfo _instanceProperty;

	private static MethodInfo _getButtonDownMethod;

	private static Type _epicLootUiType;

	private static MethodInfo _isVisibleMethod;

	private static MethodInfo _hideMethod;

	private static PropertyInfo _epicLootInstanceProperty;

	private static FieldInfo _epicLootInstanceField;

	private static bool _reflectionCached = false;

	private static int _lastCloseFrame = -1;

	private static readonly object[] _menuArg = new object[1] { "JoyMenu" };

	private static readonly object[] _inventoryArg = new object[1] { "Inventory" };

	public static void Initialize(Canvas canvas)
	{
		Cleanup();
		if (!((Object)(object)canvas == (Object)null) && ((Component)canvas).gameObject.activeInHierarchy)
		{
			CacheReflection();
			_inputCoroutine = ((MonoBehaviour)UIVRPatch.Instance).StartCoroutine(WaitForVRInput(canvas));
			UIVRPatch.LogInfo("EpicLoot VR controls initialized");
		}
	}

	public static void Stop()
	{
		Cleanup();
	}

	private static void CacheReflection()
	{
		if (_reflectionCached)
		{
			return;
		}
		try
		{
			_vrControlsType = AccessTools.TypeByName("ValheimVRMod.VRCore.UI.VRControls");
			if (_vrControlsType != null)
			{
				_instanceProperty = AccessTools.Property(_vrControlsType, "instance");
				_getButtonDownMethod = AccessTools.Method(_vrControlsType, "GetButtonDown", (Type[])null, (Type[])null);
			}
			_epicLootUiType = AccessTools.TypeByName("EpicLoot_UnityLib.EnchantingTableUI");
			if (_epicLootUiType != null)
			{
				_isVisibleMethod = AccessTools.Method(_epicLootUiType, "IsVisible", (Type[])null, (Type[])null);
				_hideMethod = AccessTools.Method(_epicLootUiType, "Hide", (Type[])null, (Type[])null);
				_epicLootInstanceProperty = AccessTools.Property(_epicLootUiType, "instance");
				_epicLootInstanceField = AccessTools.Field(_epicLootUiType, "instance");
			}
			_reflectionCached = true;
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Error caching reflection: {arg}");
		}
	}

	private static IEnumerator WaitForVRInput(Canvas canvas)
	{
		while (true)
		{
			yield return null;
			if (!IsEpicLootUIVisible())
			{
				break;
			}
			try
			{
				if (IsVRMenuButtonPressed())
				{
					CloseEpicLootUI();
					yield break;
				}
			}
			catch (Exception arg)
			{
				UIVRPatch.LogError($"Error in VR input check: {arg}");
			}
		}
		Cleanup();
	}

	private static bool IsVRMenuButtonPressed()
	{
		if (!_reflectionCached || _vrControlsType == null)
		{
			return false;
		}
		try
		{
			object obj = _instanceProperty?.GetValue(null);
			if (obj != null)
			{
				bool num = (bool)_getButtonDownMethod.Invoke(obj, _menuArg);
				bool flag = (bool)_getButtonDownMethod.Invoke(obj, _inventoryArg);
				return num || flag;
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"VR input error: {arg}");
		}
		return false;
	}

	public static bool IsEpicLootUIVisible()
	{
		try
		{
			CacheReflection();
			object obj = _isVisibleMethod?.Invoke(null, null);
			if (obj is bool)
			{
				return (bool)obj;
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Error checking EpicLoot UI visibility: {arg}");
		}
		return false;
	}

	public static void PollGlobalCloseInput()
	{
		try
		{
			if (UIVRPatch.EnableVRFix.Value && IsEpicLootUIVisible() && IsVRMenuButtonPressed())
			{
				CloseEpicLootUI();
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Error polling EpicLoot global close input: {arg}");
		}
	}

	private static void CloseEpicLootUI()
	{
		if (_lastCloseFrame == Time.frameCount)
		{
			return;
		}
		_lastCloseFrame = Time.frameCount;
		try
		{
			CacheReflection();
			_ = _epicLootUiType;
			MethodInfo hideMethod = _hideMethod;
			if (hideMethod == null)
			{
				UIVRPatch.LogWarning("EpicLoot EnchantingTableUI.Hide() was not found");
				Cleanup();
				return;
			}
			object obj = null;
			if (!hideMethod.IsStatic)
			{
				obj = EpicLootVRUI.GetActiveEnchantingUI() ?? _epicLootInstanceField?.GetValue(null) ?? _epicLootInstanceProperty?.GetValue(null, null);
				if (obj == null)
				{
					UIVRPatch.LogWarning("EpicLoot EnchantingTableUI.Hide() is instance-based, but no active instance was available");
					Cleanup();
					return;
				}
			}
			hideMethod.Invoke(obj, null);
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Error closing EpicLoot UI: {arg}");
		}
		Cleanup();
	}

	private static void Cleanup()
	{
		if (_inputCoroutine != null)
		{
			((MonoBehaviour)UIVRPatch.Instance).StopCoroutine(_inputCoroutine);
			_inputCoroutine = null;
		}
	}
}
public static class EpicLootVRUI
{
	private static Type _uiType;

	private static Type _vrguiType;

	private static FieldInfo _guiCameraField;

	private static FieldInfo _guiCanvasesField;

	private static bool _cached;

	private static object _activeEnchantingUI;

	private static Coroutine _reopenCoroutine;

	private static void CacheReflection()
	{
		if (_cached)
		{
			return;
		}
		try
		{
			_uiType = AccessTools.TypeByName("EpicLoot_UnityLib.EnchantingTableUI");
			_vrguiType = AccessTools.TypeByName("ValheimVRMod.VRCore.UI.VRGUI");
			if (_vrguiType != null)
			{
				_guiCameraField = AccessTools.Field(_vrguiType, "_guiCamera");
				_guiCanvasesField = AccessTools.Field(_vrguiType, "_guiCanvases");
			}
			_cached = true;
			UIVRPatch.LogInfo("EpicLootVRUI reflection cached");
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Reflection cache failed: {arg}");
		}
	}

	public static bool IsEpicLootLoaded()
	{
		try
		{
			if (!_cached)
			{
				CacheReflection();
			}
			return _uiType != null;
		}
		catch
		{
			return false;
		}
	}

	public static void PatchEpicLootUI(Harmony harmony)
	{
		try
		{
			CacheReflection();
			if (!(_uiType == null))
			{
				PatchLifecycleMethod(harmony, "Awake", "OnUIOpened", "creation");
				PatchLifecycleMethod(harmony, "Show", "OnUIOpened", "show");
				PatchLifecycleMethod(harmony, "Hide", "OnUIClosed", "hide");
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Error patching EpicLoot: {arg}");
		}
	}

	private static void PatchLifecycleMethod(Harmony harmony, string methodName, string postfixName, string reason)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Expected O, but got Unknown
		MethodInfo method = _uiType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		if (method == null)
		{
			UIVRPatch.LogWarning("EpicLoot UI has no " + methodName + "() method to patch for VR " + reason);
			return;
		}
		string text = ((method.IsStatic && postfixName == "OnUIOpened") ? "OnUIOpenedStatic" : postfixName);
		harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(EpicLootVRUI), text, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		UIVRPatch.LogInfo("Patched EpicLoot UI " + methodName + "() for VR " + reason);
	}

	public static void OnUIOpenedStatic()
	{
		try
		{
			OnUIOpened(AccessTools.PropertyGetter(_uiType, "instance")?.Invoke(null, null) ?? AccessTools.Field(_uiType, "instance")?.GetValue(null));
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"OnUIOpenedStatic error: {arg}");
		}
	}

	public static void OnUIOpened(object __instance)
	{
		try
		{
			if (__instance != null)
			{
				_activeEnchantingUI = __instance;
				Component val = (Component)((__instance is Component) ? __instance : null);
				if (!((Object)(object)val == (Object)null))
				{
					ScheduleProcessWhenVisible(val);
				}
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"OnUIOpened error: {arg}");
		}
	}

	public static void OnUIClosed(object __instance)
	{
		try
		{
			if (_reopenCoroutine != null && (Object)(object)UIVRPatch.Instance != (Object)null)
			{
				((MonoBehaviour)UIVRPatch.Instance).StopCoroutine(_reopenCoroutine);
				_reopenCoroutine = null;
			}
			EpicLootVRControls.Stop();
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"OnUIClosed error: {arg}");
		}
	}

	public static object GetActiveEnchantingUI()
	{
		return _activeEnchantingUI;
	}

	private static void ScheduleProcessWhenVisible(Component component)
	{
		if (!((Object)(object)component == (Object)null) && !((Object)(object)UIVRPatch.Instance == (Object)null))
		{
			if (_reopenCoroutine != null)
			{
				((MonoBehaviour)UIVRPatch.Instance).StopCoroutine(_reopenCoroutine);
				_reopenCoroutine = null;
			}
			_reopenCoroutine = ((MonoBehaviour)UIVRPatch.Instance).StartCoroutine(ProcessWhenVisible(component));
		}
	}

	private static IEnumerator ProcessWhenVisible(Component component)
	{
		for (int attempt = 0; attempt < 45; attempt++)
		{
			if ((Object)(object)component == (Object)null)
			{
				break;
			}
			Canvas componentInChildren = component.GetComponentInChildren<Canvas>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				ProcessCanvas(componentInChildren);
				if (((Component)componentInChildren).gameObject.activeInHierarchy)
				{
					_reopenCoroutine = null;
					yield break;
				}
			}
			yield return null;
		}
		UIVRPatch.LogWarning("EpicLoot enchanting UI canvas was not active after reopen retry window");
		_reopenCoroutine = null;
	}

	private static void ProcessCanvas(Canvas canvas)
	{
		try
		{
			object vHVRVRGUI = GetVHVRVRGUI();
			if (vHVRVRGUI != null)
			{
				AddCanvasToVHVR(canvas, vHVRVRGUI);
				SetupCanvas(canvas, vHVRVRGUI);
				EpicLootVRControls.Initialize(canvas);
				UIVRPatch.LogInfo("EpicLoot UI processed (event-driven)");
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"ProcessCanvas error: {arg}");
		}
	}

	private static object GetVHVRVRGUI()
	{
		try
		{
			if (_vrguiType == null)
			{
				return null;
			}
			Object[] array = Object.FindObjectsByType(_vrguiType, (FindObjectsSortMode)0);
			return (array.Length != 0) ? array[0] : null;
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"Error getting VRGUI: {arg}");
			return null;
		}
	}

	private static void AddCanvasToVHVR(Canvas canvas, object vrguiInstance)
	{
		try
		{
			if (!(_guiCanvasesField == null) && _guiCanvasesField.GetValue(vrguiInstance) is IList list && !list.Contains(canvas))
			{
				list.Add(canvas);
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogWarning($"Error adding canvas: {arg}");
		}
	}

	private static void SetupCanvas(Canvas canvas, object vrguiInstance)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (_guiCameraField == null)
			{
				return;
			}
			object? value = _guiCameraField.GetValue(vrguiInstance);
			Camera val = (Camera)((value is Camera) ? value : null);
			if (!((Object)(object)val == (Object)null))
			{
				canvas.renderMode = (RenderMode)2;
				canvas.worldCamera = val;
				RectTransform component = ((Component)canvas).GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null)
				{
					((Transform)component).localScale = Vector3.one;
				}
			}
		}
		catch (Exception arg)
		{
			UIVRPatch.LogError($"SetupCanvas error: {arg}");
		}
	}
}
[BepInPlugin("EpicLootVRFix", "Epic Loot VR Fix", "1.0.17")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class UIVRPatch : BaseUnityPlugin
{
	public static ConfigEntry<bool> EnableVRFix;

	public static ConfigEntry<bool> DebugMode;

	public static UIVRPatch Instance;

	private Harmony _harmony;

	private bool _patched;

	public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

	private void Awake()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		Instance = this;
		EnableVRFix = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable VR Fix", true, "Enable VR UI fixes");
		DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Debug Mode", false, "Enable debug logging (for testing only)");
		if (EnableVRFix.Value)
		{
			_harmony = new Harmony("EpicLootVRFix");
			_harmony.PatchAll();
			((MonoBehaviour)this).StartCoroutine(WaitForEpicLootAndPatch());
		}
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private void Update()
	{
		ConfigEntry<bool> enableVRFix = EnableVRFix;
		if (enableVRFix != null && enableVRFix.Value)
		{
			EpicLootVRControls.PollGlobalCloseInput();
		}
	}

	private IEnumerator WaitForEpicLootAndPatch()
	{
		while (!EpicLootVRUI.IsEpicLootLoaded())
		{
			yield return (object)new WaitForSeconds(2f);
		}
		if (!_patched)
		{
			_patched = true;
			LogInfo("EpicLoot detected! Applying VR fixes...");
			EpicLootVRUI.PatchEpicLootUI(_harmony);
		}
	}

	public static void LogInfo(string message)
	{
		if (DebugMode.Value)
		{
			Instance.Logger.LogInfo((object)message);
		}
	}

	public static void LogWarning(string message)
	{
		if (DebugMode.Value)
		{
			Instance.Logger.LogWarning((object)message);
		}
	}

	public static void LogError(string message)
	{
		Instance.Logger.LogError((object)message);
	}
}
namespace EpicLootVRFix;

[HarmonyPatch]
public static class EpicLootVRTooltipFix
{
	private static readonly int UILayer = LayerMask.NameToLayer("UI");

	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("EpicLoot.PatchOnHoverFix:AddScrollbar", (Type[])null, (Type[])null);
	}

	private static void Postfix(GameObject tooltipObject)
	{
		try
		{
			if (!UIVRPatch.EnableVRFix.Value || (Object)(object)tooltipObject == (Object)null)
			{
				return;
			}
			Transform val = tooltipObject.transform.Find("Canvas");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform val2 = val.Find("Scroll View");
			if (!((Object)(object)val2 == (Object)null))
			{
				ScrollRect component = ((Component)val2).GetComponent<ScrollRect>();
				if ((Object)(object)component != (Object)null)
				{
					EpicLootVRTooltipScrollState.RegisterTooltipScrollRect(component);
				}
				val2.SetParent(tooltipObject.transform, true);
				SetLayerRecursive(((Component)val2).gameObject, UILayer);
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}
		catch (Exception ex)
		{
			UIVRPatch.LogError("EpicLootVRTooltipFix error: " + ex);
		}
	}

	private static void SetLayerRecursive(GameObject obj, int layer)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		obj.layer = layer;
		foreach (Transform item in obj.transform)
		{
			SetLayerRecursive(((Component)item).gameObject, layer);
		}
	}
}
internal static class EpicLootVRTooltipScrollState
{
	private const float Deadzone = 0.18f;

	private const float ScrollSpeed = 3.8f;

	private const float DigitalScrollHoldSeconds = 0.28f;

	private const float SyntheticWheelStep = 0.22f;

	private static ScrollRect _cachedScrollRect;

	private static ScrollRect _registeredScrollRect;

	private static GameObject _cachedTooltip;

	private static int _lastScrollFrame = -1;

	private static float _lastAxis;

	private static float _setControlsAxis;

	private static float _setControlsAxisUntil;

	private static FieldInfo _uiTooltipField;

	private static bool _steamVrCached;

	private static FieldInfo _toggleCrouchField;

	private static FieldInfo _toggleRunField;

	private static FieldInfo _holdRunField;

	private static PropertyInfo _stateProperty;

	private static MethodInfo _getStateMethod;

	private static Type _inputSourcesType;

	private static MethodInfo _vrControlsInstanceGetter;

	private static MethodInfo _getDirectRightYAxisMethod;

	public static void RegisterTooltipScrollRect(ScrollRect scrollRect)
	{
		if (!((Object)(object)scrollRect == (Object)null))
		{
			_registeredScrollRect = scrollRect;
			_cachedScrollRect = scrollRect;
			UIVRPatch.LogInfo("Registered EpicLoot tooltip ScrollRect for VR right-stick scrolling");
		}
	}

	public static bool ShouldConsumeRightStickY()
	{
		if (UIVRPatch.EnableVRFix.Value)
		{
			return IsInventoryOpen();
		}
		return false;
	}

	public static bool HasActiveScrollTarget()
	{
		if (ShouldConsumeRightStickY())
		{
			return (Object)(object)GetActiveScrollableTooltip() != (Object)null;
		}
		return false;
	}

	public static float GetSyntheticMouseWheelAxis()
	{
		if (!HasActiveScrollTarget())
		{
			return 0f;
		}
		if (Mathf.Abs(_lastAxis) > 0.18f)
		{
			return Mathf.Sign(_lastAxis) * 0.22f;
		}
		CacheSteamVrReflection();
		if (GetSteamVrActionState(_toggleCrouchField))
		{
			return -0.22f;
		}
		if (GetSteamVrActionState(_toggleRunField) || GetSteamVrActionState(_holdRunField))
		{
			return 0.22f;
		}
		return 0f;
	}

	public static void TryScroll(float axis)
	{
		float num = 0f - axis;
		_lastAxis = ((Mathf.Abs(num) > 0.18f) ? num : 0f);
		if (Mathf.Abs(num) > 0.18f)
		{
			_setControlsAxis = num;
			_setControlsAxisUntil = Time.unscaledTime + 0.28f;
		}
		TryScrollInternal(num);
	}

	public static float GetCurrentVrScrollAxis()
	{
		if (!ShouldConsumeRightStickY())
		{
			return 0f;
		}
		float directRightStickYAxis = GetDirectRightStickYAxis();
		if (Mathf.Abs(directRightStickYAxis) > 0.18f)
		{
			return directRightStickYAxis;
		}
		if (Mathf.Abs(_lastAxis) > 0.18f)
		{
			return _lastAxis;
		}
		if (Mathf.Abs(_setControlsAxis) > 0.18f && Time.unscaledTime <= _setControlsAxisUntil)
		{
			return _setControlsAxis;
		}
		if (Time.unscaledTime > _setControlsAxisUntil)
		{
			_setControlsAxis = 0f;
		}
		CacheSteamVrReflection();
		if (GetSteamVrActionState(_toggleCrouchField))
		{
			return -1f;
		}
		if (GetSteamVrActionState(_toggleRunField) || GetSteamVrActionState(_holdRunField))
		{
			return 1f;
		}
		return 0f;
	}

	public static void ScrollRectByAxis(ScrollRect scrollRect, float axis)
	{
		if (!((Object)(object)scrollRect == (Object)null) && !(Mathf.Abs(axis) <= 0.18f))
		{
			Canvas.ForceUpdateCanvases();
			float num = axis * 3.8f * Time.unscaledDeltaTime;
			scrollRect.verticalNormalizedPosition = Mathf.Clamp01(scrollRect.verticalNormalizedPosition + num);
			Canvas.ForceUpdateCanvases();
		}
	}

	public static void TryScrollLastAxis()
	{
		TryScrollInternal(_lastAxis);
	}

	public static void TryScrollFromSetControls(bool run, bool crouch)
	{
		if (ShouldConsumeRightStickY())
		{
			float num = 0f;
			if (crouch)
			{
				num = -1f;
			}
			else if (run)
			{
				num = 1f;
			}
			if (Mathf.Abs(num) > 0.18f)
			{
				_setControlsAxis = num;
				_setControlsAxisUntil = Time.unscaledTime + 0.28f;
			}
			else if (Time.unscaledTime > _setControlsAxisUntil)
			{
				_setControlsAxis = 0f;
			}
			TryScrollInternal(num);
		}
	}

	private static void TryScrollInternal(float axis)
	{
		if (ShouldConsumeRightStickY() && !(Mathf.Abs(axis) <= 0.18f) && _lastScrollFrame != Time.frameCount)
		{
			ScrollRect activeScrollableTooltip = GetActiveScrollableTooltip();
			if (!((Object)(object)activeScrollableTooltip == (Object)null))
			{
				float num = axis * 3.8f * Time.unscaledDeltaTime;
				Canvas.ForceUpdateCanvases();
				activeScrollableTooltip.verticalNormalizedPosition = Mathf.Clamp01(activeScrollableTooltip.verticalNormalizedPosition + num);
				Canvas.ForceUpdateCanvases();
				_lastScrollFrame = Time.frameCount;
			}
		}
	}

	private static bool IsInventoryOpen()
	{
		try
		{
			return InventoryGui.IsVisible();
		}
		catch
		{
			return false;
		}
	}

	private static float GetDirectRightStickYAxis()
	{
		CacheSteamVrReflection();
		try
		{
			object obj = _vrControlsInstanceGetter?.Invoke(null, null);
			if (obj == null || _getDirectRightYAxisMethod == null)
			{
				return 0f;
			}
			if (_getDirectRightYAxisMethod.Invoke(obj, null) is int num)
			{
				return Mathf.Clamp(num, -1, 1);
			}
		}
		catch
		{
			return 0f;
		}
		return 0f;
	}

	private static bool GetSteamVrActionState(FieldInfo actionField)
	{
		CacheSteamVrReflection();
		try
		{
			object obj = actionField?.GetValue(null);
			if (obj == null)
			{
				return false;
			}
			if (_stateProperty != null && _stateProperty.GetValue(obj, null) is bool result)
			{
				return result;
			}
			if (_getStateMethod != null && _inputSourcesType != null)
			{
				object obj2 = Enum.ToObject(_inputSourcesType, 0);
				if (_getStateMethod.Invoke(obj, new object[1] { obj2 }) is bool result2)
				{
					return result2;
				}
			}
		}
		catch
		{
			return false;
		}
		return false;
	}

	private static void CacheSteamVrReflection()
	{
		if (!_steamVrCached)
		{
			_steamVrCached = true;
			_uiTooltipField = AccessTools.Field(typeof(UITooltip), "m_tooltip");
			Type type = AccessTools.TypeByName("SteamVR_Actions");
			_toggleCrouchField = AccessTools.Field(type, "valheim_ToggleCrouch");
			_toggleRunField = AccessTools.Field(type, "valheim_ToggleRun");
			_holdRunField = AccessTools.Field(type, "valheim_HoldRun");
			Type type2 = AccessTools.TypeByName("ValheimVRMod.VRCore.UI.VRControls");
			_vrControlsInstanceGetter = AccessTools.PropertyGetter(type2, "instance");
			_getDirectRightYAxisMethod = AccessTools.Method(type2, "getDirectRightYAxis", (Type[])null, (Type[])null);
			Type type3 = AccessTools.TypeByName("Valve.VR.SteamVR_Action_Boolean");
			_inputSourcesType = AccessTools.TypeByName("Valve.VR.SteamVR_Input_Sources");
			_stateProperty = AccessTools.Property(type3, "state");
			_getStateMethod = AccessTools.Method(type3, "GetState", new Type[1] { _inputSourcesType }, (Type[])null);
		}
	}

	private static ScrollRect GetActiveScrollableTooltip()
	{
		if (IsUsableRegisteredScrollRect(_registeredScrollRect))
		{
			return _registeredScrollRect;
		}
		_registeredScrollRect = null;
		GameObject currentTooltipObject = GetCurrentTooltipObject();
		if ((Object)(object)currentTooltipObject != (Object)null && currentTooltipObject.activeInHierarchy)
		{
			if ((Object)(object)_cachedTooltip != (Object)(object)currentTooltipObject || (Object)(object)_cachedScrollRect == (Object)null)
			{
				_cachedTooltip = currentTooltipObject;
				_cachedScrollRect = FindScrollableInTooltip(currentTooltipObject);
			}
			if (IsScrollable(_cachedScrollRect))
			{
				return _cachedScrollRect;
			}
		}
		_cachedTooltip = null;
		_cachedScrollRect = FindAnyActiveTooltipScrollRect();
		return _cachedScrollRect;
	}

	private static GameObject GetCurrentTooltipObject()
	{
		try
		{
			CacheSteamVrReflection();
			object? obj = _uiTooltipField?.GetValue(null);
			return (GameObject)((obj is GameObject) ? obj : null);
		}
		catch
		{
			return null;
		}
	}

	private static ScrollRect FindScrollableInTooltip(GameObject tooltip)
	{
		ScrollRect[] componentsInChildren = tooltip.GetComponentsInChildren<ScrollRect>(true);
		foreach (ScrollRect val in componentsInChildren)
		{
			if (IsScrollable(val))
			{
				return val;
			}
		}
		return null;
	}

	private static ScrollRect FindAnyActiveTooltipScrollRect()
	{
		ScrollRect[] array = Resources.FindObjectsOfTypeAll<ScrollRect>();
		foreach (ScrollRect val in array)
		{
			if (IsScrollable(val))
			{
				string name = ((Object)((Component)val).gameObject).name;
				Transform parent = ((Component)val).transform.parent;
				string text = (((Object)(object)parent != (Object)null) ? ((Object)parent).name : string.Empty);
				if (name.Contains("Scroll") || text.Contains("Tooltip") || text.Contains("ItemTooltip"))
				{
					return val;
				}
			}
		}
		return null;
	}

	private static bool IsUsableRegisteredScrollRect(ScrollRect scrollRect)
	{
		if ((Object)(object)scrollRect != (Object)null && ((Component)scrollRect).gameObject.activeInHierarchy && scrollRect.vertical)
		{
			return (Object)(object)scrollRect.content != (Object)null;
		}
		return false;
	}

	private static bool IsScrollable(ScrollRect scrollRect)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)scrollRect == (Object)null || !((Component)scrollRect).gameObject.activeInHierarchy || !scrollRect.vertical)
		{
			return false;
		}
		if ((Object)(object)scrollRect.content != (Object)null && (Object)(object)scrollRect.viewport != (Object)null)
		{
			Rect rect = scrollRect.content.rect;
			float height = ((Rect)(ref rect)).height;
			rect = scrollRect.viewport.rect;
			float height2 = ((Rect)(ref rect)).height;
			if (height > height2 + 1f)
			{
				return true;
			}
		}
		if ((Object)(object)scrollRect.verticalScrollbar != (Object)null)
		{
			return scrollRect.verticalScrollbar.size < 0.999f;
		}
		return false;
	}
}
[HarmonyPatch]
public static class EpicLootVRScrollWheelHandlerUpdatePatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("EpicLoot.ScrollWheelHandler:Update", (Type[])null, (Type[])null) ?? AccessTools.Method("ScrollWheelHandler:Update", (Type[])null, (Type[])null);
	}

	[HarmonyPriority(0)]
	private static void Postfix(Component __instance)
	{
		try
		{
			float currentVrScrollAxis = EpicLootVRTooltipScrollState.GetCurrentVrScrollAxis();
			if (!(Mathf.Abs(currentVrScrollAxis) <= 0f))
			{
				EpicLootVRTooltipScrollState.ScrollRectByAxis(__instance.GetComponent<ScrollRect>(), currentVrScrollAxis);
			}
		}
		catch (Exception ex)
		{
			UIVRPatch.LogError("EpicLootVRScrollWheelHandlerUpdatePatch error: " + ex);
		}
	}
}
[HarmonyPatch(typeof(Input), "GetAxis", new Type[] { typeof(string) })]
public static class EpicLootVRMouseScrollWheelAxisPatch
{
	[HarmonyPriority(0)]
	private static void Postfix(string axisName, ref float __result)
	{
		try
		{
			if (!(axisName != "Mouse ScrollWheel"))
			{
				float syntheticMouseWheelAxis = EpicLootVRTooltipScrollState.GetSyntheticMouseWheelAxis();
				if (Mathf.Abs(syntheticMouseWheelAxis) > 0f)
				{
					__result = syntheticMouseWheelAxis;
				}
			}
		}
		catch (Exception ex)
		{
			UIVRPatch.LogError("EpicLootVRMouseScrollWheelAxisPatch error: " + ex);
		}
	}
}
[HarmonyPatch]
public static class EpicLootVRControlsRightStickYPatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("ValheimVRMod.VRCore.UI.VRControls:GetJoyRightStickY", (Type[])null, (Type[])null);
	}

	[HarmonyPriority(0)]
	private static void Postfix(ref float __result)
	{
		try
		{
			if (EpicLootVRTooltipScrollState.ShouldConsumeRightStickY())
			{
				EpicLootVRTooltipScrollState.TryScroll(__result);
			}
		}
		catch (Exception ex)
		{
			UIVRPatch.LogError("EpicLootVRControlsRightStickYPatch error: " + ex);
		}
	}
}
[HarmonyPatch]
public static class EpicLootVRZInputRightStickYPatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("ZInput:GetJoyRightStickY", (Type[])null, (Type[])null);
	}

	[HarmonyPriority(0)]
	private static void Postfix(ref float __result)
	{
		try
		{
			if (EpicLootVRTooltipScrollState.ShouldConsumeRightStickY())
			{
				EpicLootVRTooltipScrollState.TryScroll(__result);
				__result = 0f;
			}
		}
		catch (Exception ex)
		{
			UIVRPatch.LogError("EpicLootVRZInputRightStickYPatch error: " + ex);
		}
	}
}
[HarmonyPatch]
public static class EpicLootVRPlayerSetControlsPatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("Player:SetControls", (Type[])null, (Type[])null);
	}

	[HarmonyPriority(0)]
	private static void Prefix(object __instance, ref bool run, ref bool crouch)
	{
		try
		{
			if (EpicLootVRTooltipScrollState.ShouldConsumeRightStickY())
			{
				EpicLootVRTooltipScrollState.TryScrollFromSetControls(run, crouch);
				EpicLootVRTooltipScrollState.TryScrollLastAxis();
				run = false;
				crouch = false;
			}
		}
		catch (Exception ex)
		{
			UIVRPatch.LogError("EpicLootVRPlayerSetControlsPatch error: " + ex);
		}
	}
}