Decompiled source of Chest Preview v1.0.15

plugins/ChestContentsPreview.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("ChestContentsPreview")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ChestContentsPreview")]
[assembly: AssemblyTitle("ChestContentsPreview")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 ChestContentsPreview
{
	[BepInPlugin("com.chestcontentspreview.valheim", "Chest Contents Preview", "1.0.15")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.chestcontentspreview.valheim";

		public const string PluginName = "Chest Contents Preview";

		public const string PluginVersion = "1.0.15";

		internal static ConfigEntry<bool> IsModEnabled;

		internal static ConfigEntry<bool> StartHidden;

		internal static ConfigEntry<KeyboardShortcut> ToggleShortcut;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			IsModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("_Global", "isModEnabled", true, "Globally enable or disable the chest contents preview.");
			StartHidden = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "startHidden", false, "Start with the chest contents preview hidden until the shortcut is pressed.");
			ToggleShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "toggleShowContentsShortcut", new KeyboardShortcut((KeyCode)112, (KeyCode[])(object)new KeyCode[1] { (KeyCode)303 }), "Toggle the chest contents preview.");
			PreviewController.Initialize(((BaseUnityPlugin)this).Logger);
			PreviewController.SetVisible(!StartHidden.Value);
			_harmony = new Harmony("com.chestcontentspreview.valheim");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Chest Contents Preview 1.0.15 loaded.");
		}

		private void Update()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			NoScrollWardrobesCompatibilityPatch.TryInstall(_harmony, ((BaseUnityPlugin)this).Logger);
			if (!IsModEnabled.Value)
			{
				return;
			}
			KeyboardShortcut value = ToggleShortcut.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				PreviewController.ToggleVisible();
				if (!PreviewController.IsVisible && !PreviewController.IsRealGuiVisible && (Object)(object)InventoryGui.instance != (Object)null)
				{
					InventoryGui.instance.Hide();
				}
			}
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	internal static class PreviewController
	{
		private static readonly FieldInfo PlayerHoveringField = AccessTools.Field(typeof(Player), "m_hovering");

		private static readonly FieldInfo GuiAnimatorField = AccessTools.Field(typeof(InventoryGui), "m_animator");

		private static readonly FieldInfo GuiHiddenFramesField = AccessTools.Field(typeof(InventoryGui), "m_hiddenFrames");

		private static readonly FieldInfo GuiPlayerField = AccessTools.Field(typeof(InventoryGui), "m_player");

		private static readonly FieldInfo GuiInfoPanelField = AccessTools.Field(typeof(InventoryGui), "m_infoPanel");

		private static readonly FieldInfo GuiInventoryRootField = AccessTools.Field(typeof(InventoryGui), "m_inventoryRoot");

		private static readonly FieldInfo GuiContainerField = AccessTools.Field(typeof(InventoryGui), "m_container");

		private static readonly FieldInfo GuiContainerGridField = AccessTools.Field(typeof(InventoryGui), "m_containerGrid");

		private static readonly FieldInfo GuiTakeAllButtonField = AccessTools.Field(typeof(InventoryGui), "m_takeAllButton");

		private static readonly FieldInfo GuiStackAllButtonField = AccessTools.Field(typeof(InventoryGui), "m_stackAllButton");

		private static readonly FieldInfo GuiContainerNameField = AccessTools.Field(typeof(InventoryGui), "m_containerName");

		private static readonly FieldInfo GuiContainerWeightField = AccessTools.Field(typeof(InventoryGui), "m_containerWeight");

		private static readonly FieldInfo GuiCurrentContainerField = AccessTools.Field(typeof(InventoryGui), "m_currentContainer");

		private static readonly FieldInfo GamePlayerProfileField = AccessTools.Field(typeof(Game), "m_playerProfile");

		private static readonly FieldInfo ProfilePlayerIdField = AccessTools.Field(typeof(PlayerProfile), "m_playerID");

		private static readonly MethodInfo ContainerCheckAccessMethod = (from method in typeof(Container).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
			where method.Name == "CheckAccess"
			orderby method.GetParameters().Length
			select method).FirstOrDefault();

		private static readonly Dictionary<GameObject, bool> PreviewObjectActiveStates = new Dictionary<GameObject, bool>();

		private static readonly Dictionary<Behaviour, bool> PreviewBehaviourEnabledStates = new Dictionary<Behaviour, bool>();

		private static ManualLogSource _log;

		private static bool _visible = true;

		private static bool _realGuiVisible;

		private static bool _previewUiSuppressed;

		private static Container _hoveredContainer;

		private static GameObject _hoveredObject;

		private static Container _lastAccessLogContainer;

		private static bool _lastAccessLogValue;

		private static bool _hasAccessLogValue;

		private static bool _isPreviewGridUpdate;

		private static InventoryGui _previewGridGui;

		private static Container _previewGridContainer;

		private static InventoryGui _cachedGui;

		private static Transform _playerPanelTransform;

		private static GameObject _infoPanel;

		private static GameObject _craftingPanel;

		private static GameObject _takeAllButton;

		private static GameObject _stackAllButton;

		private static GameObject _containerName;

		private static GameObject _containerWeight;

		private static Component[] _textComponents;

		internal static bool IsVisible => _visible;

		internal static bool IsRealGuiVisible => _realGuiVisible;

		internal static void Initialize(ManualLogSource logger)
		{
			_log = logger;
			if (GuiCurrentContainerField == null)
			{
				_log.LogWarning((object)"InventoryGui.m_currentContainer was not found. Grid layout compatibility may be unavailable.");
			}
		}

		internal static Container ResolveLayoutContainer(object ignoredAccessor, InventoryGui gui)
		{
			if (_isPreviewGridUpdate && (Object)(object)gui == (Object)(object)_previewGridGui)
			{
				return _previewGridContainer;
			}
			object obj = Get(GuiCurrentContainerField, gui);
			return (Container)((obj is Container) ? obj : null);
		}

		internal static void SetVisible(bool value)
		{
			_visible = value;
		}

		internal static void ToggleVisible()
		{
			_visible = !_visible;
		}

		internal static void TrackHover(Player player)
		{
			if (!((Object)(object)player == (Object)null) && Plugin.IsModEnabled != null && Plugin.IsModEnabled.Value)
			{
				object obj = Get(PlayerHoveringField, player);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if (!((Object)(object)_hoveredObject == (Object)(object)val))
				{
					_hoveredObject = val;
					_hoveredContainer = (((Object)(object)val != (Object)null) ? val.GetComponentInParent<Container>() : null);
				}
			}
		}

		internal static void CacheGui(InventoryGui gui)
		{
			if (!((Object)(object)gui == (Object)null) && !((Object)(object)gui == (Object)(object)_cachedGui))
			{
				_cachedGui = gui;
				_playerPanelTransform = AsTransform(Get(GuiPlayerField, gui));
				_infoPanel = AsGameObject(Get(GuiInfoPanelField, gui));
				_takeAllButton = AsGameObject(Get(GuiTakeAllButtonField, gui));
				_stackAllButton = AsGameObject(Get(GuiStackAllButtonField, gui));
				_containerName = AsGameObject(Get(GuiContainerNameField, gui));
				_containerWeight = AsGameObject(Get(GuiContainerWeightField, gui));
				_textComponents = (from component in ((Component)gui).GetComponentsInChildren<Component>(true)
					where (Object)(object)component != (Object)null && GetTextProperty(((object)component).GetType()) != null
					select component).ToArray();
				Transform val = AsTransform(Get(GuiInventoryRootField, gui));
				Transform val2 = (((Object)(object)val != (Object)null) ? val.Find("Crafting") : null);
				if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.auga"))
				{
					val2 = (((Object)(object)val != (Object)null) ? val.Find("RightPanel") : null);
				}
				_craftingPanel = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null);
			}
		}

		internal static void OnShow()
		{
			_realGuiVisible = true;
			RestorePreviewUi();
		}

		internal static void OnHide()
		{
			bool realGuiVisible = _realGuiVisible;
			_realGuiVisible = false;
			if (realGuiVisible)
			{
				RestorePreviewUi();
			}
		}

		internal static void BeforeGuiUpdate(InventoryGui gui)
		{
			if ((Object)(object)gui == (Object)null)
			{
				return;
			}
			CacheGui(gui);
			if (!ShowRealGui())
			{
				object obj = Get(GuiAnimatorField, gui);
				Animator val = (Animator)((obj is Animator) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.SetBool("visible", false);
				}
			}
		}

		internal static void AfterGuiUpdate(InventoryGui gui)
		{
			if ((Object)(object)gui == (Object)null)
			{
				return;
			}
			CacheGui(gui);
			if (ShowRealGui())
			{
				if (_realGuiVisible)
				{
					RestorePreviewUi();
					return;
				}
				object obj = Get(GuiAnimatorField, gui);
				Animator val = (Animator)((obj is Animator) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.SetBool("visible", false);
				}
				return;
			}
			bool num = HasContainerAccess(_hoveredContainer);
			LogHoverAccessState(num);
			if (!num || !ShowPreviewContainer(gui, _hoveredContainer))
			{
				object obj2 = Get(GuiAnimatorField, gui);
				Animator val2 = (Animator)((obj2 is Animator) ? obj2 : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.SetBool("visible", false);
				}
				if (!_previewUiSuppressed)
				{
					RestorePreviewUi();
				}
			}
		}

		private static void LogHoverAccessState(bool hasAccess)
		{
			if ((Object)(object)_hoveredContainer == (Object)null)
			{
				_lastAccessLogContainer = null;
				_hasAccessLogValue = false;
			}
			else if (!((Object)(object)_hoveredContainer == (Object)(object)_lastAccessLogContainer) || !_hasAccessLogValue || _lastAccessLogValue != hasAccess)
			{
				_lastAccessLogContainer = _hoveredContainer;
				_lastAccessLogValue = hasAccess;
				_hasAccessLogValue = true;
				_log.LogInfo((object)("Hover target " + ((Object)_hoveredContainer).name + ": preview access " + (hasAccess ? "granted." : "denied.")));
			}
		}

		internal static bool AllowDrag()
		{
			return ShowRealGui();
		}

		private static bool ShowRealGui()
		{
			if (Plugin.IsModEnabled == null || !Plugin.IsModEnabled.Value || !_visible)
			{
				return true;
			}
			return _realGuiVisible;
		}

		private static bool ShowPreviewContainer(InventoryGui gui, Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			Inventory inventory = container.GetInventory();
			object obj = Get(GuiContainerGridField, gui);
			InventoryGrid val = (InventoryGrid)((obj is InventoryGrid) ? obj : null);
			Transform val2 = AsTransform(Get(GuiContainerField, gui));
			if (inventory == null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return false;
			}
			object obj2 = Get(GuiAnimatorField, gui);
			Animator val3 = (Animator)((obj2 is Animator) ? obj2 : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.SetBool("visible", true);
			}
			Set(GuiHiddenFramesField, gui, 10);
			((Component)val2).gameObject.SetActive(true);
			HidePreviewUi(gui, val2);
			bool isPreviewGridUpdate = _isPreviewGridUpdate;
			InventoryGui previewGridGui = _previewGridGui;
			Container previewGridContainer = _previewGridContainer;
			try
			{
				_isPreviewGridUpdate = true;
				_previewGridGui = gui;
				_previewGridContainer = container;
				val.UpdateInventory(inventory, (Player)null, (ItemData)null);
				val.ResetView();
				UpdateContainerLabels(gui, inventory);
				return true;
			}
			finally
			{
				_isPreviewGridUpdate = isPreviewGridUpdate;
				_previewGridGui = previewGridGui;
				_previewGridContainer = previewGridContainer;
			}
		}

		private static void HidePreviewUi(InventoryGui gui, Transform containerPanel)
		{
			_previewUiSuppressed = true;
			if ((Object)(object)_playerPanelTransform != (Object)null)
			{
				for (int i = 0; i < _playerPanelTransform.childCount; i++)
				{
					Transform child = _playerPanelTransform.GetChild(i);
					if ((Object)(object)child != (Object)null && !IsContainerBranch(child, containerPanel))
					{
						SetPreviewObjectActive(((Component)child).gameObject, active: false);
					}
				}
			}
			SetPreviewObjectActive(_infoPanel, active: false);
			SetPreviewObjectActive(_craftingPanel, active: false);
			SetPreviewObjectActive(_takeAllButton, active: false);
			SetPreviewObjectActive(_stackAllButton, active: false);
			SetPreviewObjectActive(_containerName, active: true);
			SetPreviewObjectActive(_containerWeight, active: true);
			HideActionHints();
			HideContainerFrame(containerPanel);
			HideQuickStackButtons();
		}

		private static void HideActionHints()
		{
			if (_textComponents == null)
			{
				return;
			}
			for (int i = 0; i < _textComponents.Length; i++)
			{
				Component val = _textComponents[i];
				if (!((Object)(object)val == (Object)null))
				{
					PropertyInfo textProperty = GetTextProperty(((object)val).GetType());
					if (IsActionHint((textProperty != null && textProperty.CanRead) ? (textProperty.GetValue(val, null) as string) : null))
					{
						SetPreviewObjectActive(val.gameObject, active: false);
					}
				}
			}
		}

		private static bool IsActionHint(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string text = value.ToUpperInvariant().Replace(" ", "");
			if (!text.Contains("[LMB]") && !text.Contains("[RMB]") && !text.Contains("[SHIFT+LMB]"))
			{
				return text.Contains("[CTRL+LMB]");
			}
			return true;
		}

		private static void HideContainerFrame(Transform containerPanel)
		{
			if (!((Object)(object)containerPanel == (Object)null))
			{
				SetPreviewBehaviourEnabled((Behaviour)(object)((Component)containerPanel).GetComponent<Image>(), enabled: false);
				SetPreviewBehaviourEnabled((Behaviour)(object)((Component)containerPanel).GetComponent<Outline>(), enabled: false);
			}
		}

		private static void SetPreviewBehaviourEnabled(Behaviour behaviour, bool enabled)
		{
			if (!((Object)(object)behaviour == (Object)null))
			{
				if (!PreviewBehaviourEnabledStates.ContainsKey(behaviour))
				{
					PreviewBehaviourEnabledStates.Add(behaviour, behaviour.enabled);
				}
				behaviour.enabled = enabled;
			}
		}

		private static bool IsContainerBranch(Transform child, Transform containerPanel)
		{
			if ((Object)(object)child == (Object)null)
			{
				return false;
			}
			if ((Object)(object)containerPanel != (Object)null && ((Object)(object)child == (Object)(object)containerPanel || containerPanel.IsChildOf(child)))
			{
				return true;
			}
			return ((Object)child).name == "Container";
		}

		private static void HideQuickStackButtons()
		{
			if ((Object)(object)_takeAllButton == (Object)null || (Object)(object)_takeAllButton.transform.parent == (Object)null)
			{
				return;
			}
			Transform parent = _takeAllButton.transform.parent;
			for (int i = 0; i < parent.childCount; i++)
			{
				Transform child = parent.GetChild(i);
				if (!((Object)(object)child == (Object)null))
				{
					switch (((Object)child).name)
					{
					case "quickStackToContainerButton":
					case "storeAllButton":
					case "sortContainerButton":
					case "restockFromContainerButton":
						SetPreviewObjectActive(((Component)child).gameObject, active: false);
						break;
					}
				}
			}
		}

		private static void SetPreviewObjectActive(GameObject gameObject, bool active)
		{
			if (!((Object)(object)gameObject == (Object)null))
			{
				if (!PreviewObjectActiveStates.ContainsKey(gameObject))
				{
					PreviewObjectActiveStates.Add(gameObject, gameObject.activeSelf);
				}
				gameObject.SetActive(active);
			}
		}

		private static void SetPreviewObjectActive(Component component, bool active)
		{
			if ((Object)(object)component != (Object)null)
			{
				SetPreviewObjectActive(component.gameObject, active);
			}
		}

		private static void RestorePreviewUi()
		{
			foreach (KeyValuePair<GameObject, bool> previewObjectActiveState in PreviewObjectActiveStates)
			{
				if ((Object)(object)previewObjectActiveState.Key != (Object)null)
				{
					previewObjectActiveState.Key.SetActive(previewObjectActiveState.Value);
				}
			}
			PreviewObjectActiveStates.Clear();
			foreach (KeyValuePair<Behaviour, bool> previewBehaviourEnabledState in PreviewBehaviourEnabledStates)
			{
				if ((Object)(object)previewBehaviourEnabledState.Key != (Object)null)
				{
					previewBehaviourEnabledState.Key.enabled = previewBehaviourEnabledState.Value;
				}
			}
			PreviewBehaviourEnabledStates.Clear();
			_previewUiSuppressed = false;
		}

		private static void UpdateContainerLabels(InventoryGui gui, Inventory inventory)
		{
			if (!((Object)(object)gui == (Object)null) && inventory != null)
			{
				string text = inventory.GetName();
				if (Localization.instance != null)
				{
					text = Localization.instance.Localize(text);
				}
				SetTextValue(Get(GuiContainerNameField, gui), text);
				SetTextValue(Get(GuiContainerWeightField, gui), Mathf.CeilToInt(inventory.GetTotalWeight()).ToString());
			}
		}

		private static PropertyInfo GetTextProperty(Type type)
		{
			if (type == null)
			{
				return null;
			}
			PropertyInfo property = type.GetProperty("text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property == null || property.PropertyType != typeof(string) || property.GetIndexParameters().Length != 0)
			{
				return null;
			}
			return property;
		}

		private static void SetTextValue(object textComponent, string value)
		{
			PropertyInfo propertyInfo = ((textComponent != null) ? GetTextProperty(textComponent.GetType()) : null);
			if (propertyInfo != null && propertyInfo.CanWrite)
			{
				propertyInfo.SetValue(textComponent, value, null);
			}
		}

		private static bool HasContainerAccess(Container container)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			bool flag = PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false);
			if (ContainerCheckAccessMethod == null)
			{
				return flag;
			}
			object instance = Get(GamePlayerProfileField, Game.instance);
			object obj = Get(ProfilePlayerIdField, instance);
			if (obj == null)
			{
				return flag;
			}
			ParameterInfo[] parameters = ContainerCheckAccessMethod.GetParameters();
			if (parameters.Length == 0)
			{
				return flag;
			}
			try
			{
				object[] array = new object[parameters.Length];
				array[0] = Convert.ChangeType(obj, parameters[0].ParameterType);
				for (int i = 1; i < parameters.Length; i++)
				{
					array[i] = (parameters[i].HasDefaultValue ? parameters[i].DefaultValue : DefaultValue(parameters[i].ParameterType));
				}
				bool flag2 = (bool)ContainerCheckAccessMethod.Invoke(container, array);
				return flag && flag2;
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("Container access check failed; preview hidden. " + ex.GetBaseException().Message));
				return false;
			}
		}

		private static object DefaultValue(Type type)
		{
			if (!type.IsValueType)
			{
				return null;
			}
			return Activator.CreateInstance(type);
		}

		private static object Get(FieldInfo field, object instance)
		{
			if (!(field != null) || instance == null)
			{
				return null;
			}
			return field.GetValue(instance);
		}

		private static void Set(FieldInfo field, object instance, object value)
		{
			if (field != null && instance != null)
			{
				field.SetValue(instance, value);
			}
		}

		private static Transform AsTransform(object value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (value is Transform)
			{
				return (Transform)value;
			}
			if (value is Component)
			{
				return ((Component)value).transform;
			}
			if (value is GameObject)
			{
				return ((GameObject)value).transform;
			}
			return null;
		}

		private static GameObject AsGameObject(object value)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (value is GameObject)
			{
				return (GameObject)value;
			}
			if (value is Component)
			{
				return ((Component)value).gameObject;
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateHover")]
	internal static class PlayerHoverPatch
	{
		private static void Postfix(Player __instance)
		{
			PreviewController.TrackHover(__instance);
		}
	}
	[HarmonyPatch]
	internal static class InventoryGuiAwakePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in AccessTools.GetDeclaredMethods(typeof(InventoryGui))
				where method.Name == "Awake"
				select method;
		}

		[HarmonyPriority(200)]
		private static void Postfix(InventoryGui __instance)
		{
			PreviewController.CacheGui(__instance);
		}
	}
	[HarmonyPatch]
	internal static class InventoryGuiShowPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in AccessTools.GetDeclaredMethods(typeof(InventoryGui))
				where method.Name == "Show"
				select method;
		}

		private static void Postfix()
		{
			PreviewController.OnShow();
		}
	}
	[HarmonyPatch]
	internal static class InventoryGuiHidePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in AccessTools.GetDeclaredMethods(typeof(InventoryGui))
				where method.Name == "Hide"
				select method;
		}

		private static void Postfix()
		{
			PreviewController.OnHide();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	internal static class InventoryGuiUpdatePatch
	{
		private static void Prefix(InventoryGui __instance)
		{
			PreviewController.BeforeGuiUpdate(__instance);
		}

		private static void Postfix(InventoryGui __instance)
		{
			PreviewController.AfterGuiUpdate(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "SetupDragItem")]
	internal static class SetupDragItemPatch
	{
		private static bool Prefix()
		{
			return PreviewController.AllowDrag();
		}
	}
	internal static class NoScrollWardrobesCompatibilityPatch
	{
		private static bool _attempted;

		private static bool _accessorReplaced;

		private static int _frame;

		private static int _nextLookupFrame;

		private static Container _resolvedContainer;

		internal static void TryInstall(Harmony harmony, ManualLogSource log)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			if (_attempted || harmony == null)
			{
				return;
			}
			_frame++;
			if (_frame < _nextLookupFrame)
			{
				return;
			}
			_nextLookupFrame = _frame + 30;
			Type type = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				if (!(type == null))
				{
					break;
				}
				type = assemblies[i].GetType("NoScrollWardrobes.ContainerLayout", throwOnError: false);
			}
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "Postfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(NoScrollWardrobesCompatibilityPatch), "Transpiler", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				_attempted = true;
				log.LogWarning((object)"No Scroll Wardrobes was found, but its grid layout method could not be patched.");
				return;
			}
			_attempted = true;
			_accessorReplaced = false;
			try
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null);
				if (_accessorReplaced)
				{
					log.LogInfo((object)"No Scroll Wardrobes preview layout compatibility installed.");
				}
				else
				{
					log.LogWarning((object)"No Scroll Wardrobes loaded, but its container accessor was not recognized; previews may use its vanilla layout.");
				}
			}
			catch (Exception ex)
			{
				log.LogWarning((object)("Could not install No Scroll Wardrobes preview layout compatibility. " + ex.GetBaseException().Message));
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			bool replaced = false;
			foreach (CodeInstruction instruction in instructions)
			{
				MethodInfo methodInfo = instruction.operand as MethodInfo;
				if (!replaced && methodInfo != null && methodInfo.Name == "Invoke" && methodInfo.GetParameters().Length == 1 && methodInfo.GetParameters()[0].ParameterType == typeof(InventoryGui))
				{
					MethodInfo methodInfo2 = null;
					if (methodInfo.ReturnType == typeof(Container))
					{
						methodInfo2 = AccessTools.Method(typeof(NoScrollWardrobesCompatibilityPatch), "ResolveContainer", (Type[])null, (Type[])null);
					}
					else if (methodInfo.ReturnType.IsByRef && methodInfo.ReturnType.GetElementType() == typeof(Container))
					{
						methodInfo2 = AccessTools.Method(typeof(NoScrollWardrobesCompatibilityPatch), "ResolveContainerReference", (Type[])null, (Type[])null);
					}
					if (methodInfo2 != null)
					{
						instruction.opcode = OpCodes.Call;
						instruction.operand = methodInfo2;
						replaced = true;
						_accessorReplaced = true;
					}
				}
				yield return instruction;
			}
		}

		private static Container ResolveContainer(object currentContainerAccessor, InventoryGui gui)
		{
			return PreviewController.ResolveLayoutContainer(currentContainerAccessor, gui);
		}

		private static ref Container ResolveContainerReference(object currentContainerAccessor, InventoryGui gui)
		{
			_resolvedContainer = PreviewController.ResolveLayoutContainer(currentContainerAccessor, gui);
			return ref _resolvedContainer;
		}
	}
}