Decompiled source of ChestPreview v1.0.0

plugins/ChestPreview.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ChestPreview.UI;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ChestPreview")]
[assembly: AssemblyDescription("https://www.nexusmods.com/profile/MagicMikeMods/mods")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("MagicMike")]
[assembly: AssemblyProduct("ChestPreview")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6b1f0c52-3d8e-4a47-9a21-5c7e2f90d4b3")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[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 ChestPreview
{
	[BepInPlugin("MagicMike.ChestPreview", "ChestPreview", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class ChestPreviewMod : BaseUnityPlugin
	{
		internal const string PluginName = "ChestPreview";

		internal const string PluginVersion = "1.0.0";

		internal const string PluginAuthor = "MagicMike";

		internal const string PluginGUID = "MagicMike.ChestPreview";

		internal const string PluginLink = "https://www.nexusmods.com/profile/MagicMikeMods/mods";

		internal static ChestPreviewMod Instance;

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private GameObject _overlayRoot;

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ChestListConfig.Init(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("MagicMike.ChestPreview");
			_harmony.PatchAll();
			_overlayRoot = new GameObject("ChestPreview_Overlay");
			_overlayRoot.AddComponent<ChestListOverlay>();
			Object.DontDestroyOnLoad((Object)(object)_overlayRoot);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ChestPreview v1.0.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			if ((Object)(object)_overlayRoot != (Object)null)
			{
				Object.Destroy((Object)(object)_overlayRoot);
				_overlayRoot = null;
			}
			Instance = null;
		}
	}
	internal enum ChestSortType
	{
		Name,
		Value,
		Weight
	}
	internal static class ChestListConfig
	{
		internal static ConfigEntry<int> MaxEntries;

		internal static ConfigEntry<ChestSortType> SortType;

		internal static ConfigEntry<bool> SortAscending;

		internal static ConfigEntry<bool> CombineStacks;

		internal static ConfigEntry<string> CapacityFormat;

		internal static ConfigEntry<float> UiPositionX;

		internal static ConfigEntry<float> UiPositionY;

		internal static ConfigEntry<float> UiAlpha;

		internal static ConfigEntry<float> BackgroundAlpha;

		internal static ConfigEntry<bool> ShowItemImages;

		internal static ConfigEntry<float> MinPanelWidth;

		internal static ConfigEntry<float> MaxPanelWidth;

		internal static void Init(ConfigFile config)
		{
			MaxEntries = ConfigFileExtensions.BindConfigInOrder<int>(config, "General", "MaxEntries", -1, "Maximum number of rows to show. -1 = unlimited.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 1000), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			SortType = ConfigFileExtensions.BindConfigInOrder<ChestSortType>(config, "General", "SortType", ChestSortType.Value, "How rows are sorted: Name, Value (total value of the row) or Weight (total weight of the row). Ties are sorted by name.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			SortAscending = ConfigFileExtensions.BindConfigInOrder<bool>(config, "General", "SortAscending", false, "When enabled, sort lowest-to-highest (A-Z for Name). When disabled, sort highest-to-lowest (Z-A for Name).", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			CombineStacks = ConfigFileExtensions.BindConfigInOrder<bool>(config, "General", "CombineStacks", true, "When enabled, merge identical items into one row with a total count (same name/world level; quality only when the item supports tiers; variant only when it has multiple variants). When disabled, each inventory stack is listed separately. On by default.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			CapacityFormat = ConfigFileExtensions.BindConfigInOrder<string>(config, "UI", "CapacityFormat", "{0}/{1}", "Capacity text shown next to the chest name. {0} = slots used, {1} = total slots. Leave empty to hide.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UiPositionX = ConfigFileExtensions.BindConfigInOrder<float>(config, "UI", "PositionX", 0.72f, "Horizontal screen position of the overlay (0 = left edge, 1 = right edge). Anchor is the panel center.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UiPositionY = ConfigFileExtensions.BindConfigInOrder<float>(config, "UI", "PositionY", 0.55f, "Vertical screen position of the overlay (0 = bottom edge, 1 = top edge). Anchor is the panel center.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UiAlpha = ConfigFileExtensions.BindConfigInOrder<float>(config, "UI", "Alpha", 0.92f, "Overlay transparency (0 = invisible, 1 = fully opaque).", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			BackgroundAlpha = ConfigFileExtensions.BindConfigInOrder<float>(config, "UI", "BackgroundAlpha", 0.66f, "Opacity of the black panel background behind the text (0 = no background, 1 = solid black).", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ShowItemImages = ConfigFileExtensions.BindConfigInOrder<bool>(config, "UI", "ShowItemImages", true, "When enabled, show item icons to the left of each name/count. On by default.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			MinPanelWidth = ConfigFileExtensions.BindConfigInOrder<float>(config, "UI", "MinPanelWidth", 300f, "Minimum overlay panel width in UI pixels. Panel grows with the longest row up to MaxPanelWidth.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(200f, 600f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			MaxPanelWidth = ConfigFileExtensions.BindConfigInOrder<float>(config, "UI", "MaxPanelWidth", 470f, "Maximum overlay panel width in UI pixels. Longer item names are clipped beyond this.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(250f, 800f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
		}
	}
	internal static class ChestTarget
	{
		internal static readonly FieldRef<Container, ZNetView> ContainerNView = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

		internal static readonly FieldRef<Container, Piece> ContainerPiece = AccessTools.FieldRefAccess<Container, Piece>("m_piece");

		private static readonly Func<Container, long, bool> ContainerCheckAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null), (object)null, true);

		internal static Container Current { get; private set; }

		internal static void SetFromHoverObject(GameObject hover)
		{
			Current = ResolveContainer(hover);
		}

		internal static void Clear()
		{
			Current = null;
		}

		internal static Container ResolveContainer(GameObject hover)
		{
			if ((Object)(object)hover == (Object)null)
			{
				return null;
			}
			Container componentInParent = hover.GetComponentInParent<Container>();
			if ((Object)(object)componentInParent == (Object)null || !IsValidContainer(componentInParent))
			{
				return null;
			}
			if (!ShouldShow(componentInParent))
			{
				return null;
			}
			return componentInParent;
		}

		internal static bool IsValidContainer(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			ZNetView val = ContainerNView.Invoke(container);
			if ((Object)(object)val != (Object)null && !val.IsValid())
			{
				return false;
			}
			return container.GetInventory() != null;
		}

		internal static bool IsPlayerPlaced(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			Piece val = ContainerPiece.Invoke(container);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)container).GetComponent<Piece>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)container).GetComponentInParent<Piece>();
			}
			if ((Object)(object)val != (Object)null)
			{
				return val.IsPlacedByPlayer();
			}
			return false;
		}

		internal static bool ShouldShow(Container container)
		{
			return IsPlayerPlaced(container);
		}

		internal static bool CanPreview(Container container, Player player)
		{
			if ((Object)(object)container == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!IsValidContainer(container))
			{
				return false;
			}
			if (!ShouldShow(container))
			{
				return false;
			}
			try
			{
				if (!ContainerCheckAccess(container, player.GetPlayerID()))
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			return true;
		}
	}
}
namespace ChestPreview.UI
{
	internal sealed class ChestListOverlay : MonoBehaviour
	{
		private sealed class DisplayEntry
		{
			public ItemData Item;

			public int Stack;

			public int Order;

			public string SortName;

			public int HiddenCount;
		}

		private sealed class RowWidgets
		{
			public GameObject Root;

			public RectTransform Rect;

			public LayoutElement Layout;

			public Image Icon;

			public TextMeshProUGUI Label;
		}

		private readonly struct InvisibleMeasureScope : IDisposable
		{
			private readonly ChestListOverlay _owner;

			private readonly bool _restoreAlpha;

			private readonly float _previousAlpha;

			public InvisibleMeasureScope(ChestListOverlay owner, bool restoreAlpha, float previousAlpha)
			{
				_owner = owner;
				_restoreAlpha = restoreAlpha;
				_previousAlpha = previousAlpha;
			}

			public void Dispose()
			{
				if (!((Object)(object)_owner == (Object)null) && _restoreAlpha && Alive((Object)(object)_owner._canvasGroup))
				{
					_owner._canvasGroup.alpha = _previousAlpha;
				}
			}
		}

		private const float DefaultMinPanelWidth = 300f;

		private const float DefaultMaxPanelWidth = 470f;

		private const float ContentRightPad = 28f;

		private const float TitleHeight = 34f;

		private const float TitleGap = 4f;

		private const float RowHeight = 31f;

		private const float MinRowHeight = 22f;

		private const float IconSize = 27f;

		private const float MinIconSize = 20f;

		private const float TitleFontSize = 25f;

		private const float ItemFontSize = 21f;

		private const float MinItemFontSize = 16f;

		private const float MinPad = 16f;

		private const float InnerPad = 4f;

		private const float ColumnGap = 14f;

		private const float ScreenEdgeMargin = 36f;

		private const float HudTopReserve = 88f;

		private const float HudBottomReserve = 100f;

		private const float ComfortableHeightFraction = 0.55f;

		private const int MaxColumns = 3;

		private Canvas _canvas;

		private CanvasGroup _canvasGroup;

		private RectTransform _panel;

		private Image _panelImage;

		private RectTransform _content;

		private RectTransform _titleRt;

		private TextMeshProUGUI _title;

		private RectTransform _listArea;

		private RectTransform _listRoot;

		private GridLayoutGroup _listGrid;

		private readonly List<RowWidgets> _rows = new List<RowWidgets>(64);

		private readonly List<DisplayEntry> _displayEntries = new List<DisplayEntry>(64);

		private readonly Dictionary<string, int> _mergeIndexByKey = new Dictionary<string, int>(64);

		private readonly StringBuilder _labelBuilder = new StringBuilder(64);

		private readonly StringBuilder _keyBuilder = new StringBuilder(64);

		private Container _boundContainer;

		private int _boundRevision = -1;

		private int _boundStackRevision = -1;

		private bool _boundShowIcons;

		private bool _boundCombineStacks;

		private float _boundMinPanelWidth = -1f;

		private float _boundMaxPanelWidth = -1f;

		private ChestSortType _boundSortType;

		private bool _boundSortAscending;

		private int _boundMaxEntries = int.MinValue;

		private string _boundCapacityFormat;

		private bool _uiBuilt;

		private float _panelWidth = 300f;

		private float _listContentHeight;

		private int _layoutColumns = 1;

		private int _layoutRowsPerColumn = 1;

		private float _layoutRowHeight = 31f;

		private float _layoutIconSize = 27f;

		private float _layoutItemFontSize = 21f;

		private int _remeasureAfterFrame = -1;

		private float _remeasurePanelHeight;

		private float _padL = 12f;

		private float _padR = 12f;

		private float _padT = 8f;

		private float _padB = 10f;

		private static TMP_FontAsset _cachedFont;

		private static Material _cachedFontMaterial;

		private static float _cachedFontSize = 16f;

		private static Color _cachedFontColor = new Color(1f, 0.984f, 0.875f, 1f);

		private void Update()
		{
			try
			{
				Tick();
			}
			catch (Exception arg)
			{
				ManualLogSource log = ChestPreviewMod.Log;
				if (log != null)
				{
					log.LogError((object)$"ChestListOverlay tick failed: {arg}");
				}
				SafeHide();
			}
		}

		private void Tick()
		{
			if (!_uiBuilt)
			{
				if (!TryResolveGameFont(out var _, out var _, out var _, out var _))
				{
					return;
				}
				BuildUi();
				_uiBuilt = true;
				SafeHide();
			}
			if (!Alive((Object)(object)_canvas) || !Alive((Object)(object)_panel) || !Alive((Object)(object)_canvasGroup))
			{
				_uiBuilt = false;
				return;
			}
			if (!TryGetPreviewTarget(out var container, out var inventory))
			{
				SafeHide();
				return;
			}
			ApplyLayoutAndAlpha();
			RefreshContents(container, inventory);
			TryDeferredWidthRemeasure();
			SafeShow();
		}

		private void OnDestroy()
		{
			_rows.Clear();
			_uiBuilt = false;
			_boundContainer = null;
		}

		private static bool TryGetPreviewTarget(out Container container, out Inventory inventory)
		{
			container = null;
			inventory = null;
			Player localPlayer = Player.m_localPlayer;
			if (!Alive((Object)(object)localPlayer))
			{
				return false;
			}
			if (ShouldHideForMenus())
			{
				return false;
			}
			container = ChestTarget.Current;
			if (!ChestTarget.CanPreview(container, localPlayer))
			{
				GameObject val = null;
				try
				{
					val = ((Humanoid)localPlayer).GetHoverObject();
				}
				catch
				{
					return false;
				}
				container = ChestTarget.ResolveContainer(val);
				if (!ChestTarget.CanPreview(container, localPlayer))
				{
					return false;
				}
			}
			if (!Alive((Object)(object)container))
			{
				return false;
			}
			try
			{
				inventory = container.GetInventory();
			}
			catch
			{
				return false;
			}
			return inventory != null;
		}

		private static bool ShouldHideForMenus()
		{
			try
			{
				if (InventoryGui.IsVisible())
				{
					return true;
				}
				if (Menu.IsVisible())
				{
					return true;
				}
				if (Alive((Object)(object)TextViewer.instance) && TextViewer.instance.IsVisible())
				{
					return true;
				}
				if (Console.IsVisible())
				{
					return true;
				}
				if (Alive((Object)(object)Chat.instance) && Chat.instance.HasFocus())
				{
					return true;
				}
				if (StoreGui.IsVisible())
				{
					return true;
				}
			}
			catch
			{
				return true;
			}
			return false;
		}

		private void BuildUi()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Expected O, but got Unknown
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Expected O, but got Unknown
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Expected O, but got Unknown
			_canvas = ((Component)this).gameObject.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 80;
			CanvasScaler obj = ((Component)this).gameObject.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			obj.matchWidthOrHeight = 0.5f;
			_canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
			_canvasGroup.blocksRaycasts = false;
			_canvasGroup.interactable = false;
			GameObject val = new GameObject("Panel", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(((Component)this).transform, false);
			_panel = val.GetComponent<RectTransform>();
			_panel.anchorMin = new Vector2(0.5f, 0.5f);
			_panel.anchorMax = new Vector2(0.5f, 0.5f);
			_panel.pivot = new Vector2(0.5f, 0.5f);
			_panel.sizeDelta = new Vector2(_panelWidth, 120f);
			_panelImage = val.GetComponent<Image>();
			((Graphic)_panelImage).color = GetBackgroundColor();
			((Graphic)_panelImage).raycastTarget = false;
			GameObject val2 = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent((Transform)(object)_panel, false);
			_content = val2.GetComponent<RectTransform>();
			ApplyContentInsets();
			_title = CreateGameTmp("Title", (Transform)(object)_content, isTitle: true);
			_titleRt = ((TMP_Text)_title).rectTransform;
			_titleRt.anchorMin = new Vector2(0f, 1f);
			_titleRt.anchorMax = new Vector2(1f, 1f);
			_titleRt.pivot = new Vector2(0.5f, 1f);
			_titleRt.anchoredPosition = Vector2.zero;
			_titleRt.sizeDelta = new Vector2(0f, 34f);
			((TMP_Text)_title).alignment = (TextAlignmentOptions)514;
			((Graphic)_title).raycastTarget = false;
			((MaskableGraphic)_title).maskable = false;
			((TMP_Text)_title).overflowMode = (TextOverflowModes)0;
			((TMP_Text)_title).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)_title).enableAutoSizing = false;
			((TMP_Text)_title).text = "Chest";
			((Component)_title).gameObject.SetActive(true);
			GameObject val3 = new GameObject("ListArea", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent((Transform)(object)_content, false);
			_listArea = val3.GetComponent<RectTransform>();
			_listArea.anchorMin = Vector2.zero;
			_listArea.anchorMax = Vector2.one;
			_listArea.pivot = new Vector2(0.5f, 1f);
			_listArea.offsetMin = Vector2.zero;
			_listArea.offsetMax = new Vector2(0f, -38f);
			((TMP_Text)_title).transform.SetAsFirstSibling();
			GameObject val4 = new GameObject("List", new Type[2]
			{
				typeof(RectTransform),
				typeof(GridLayoutGroup)
			});
			val4.transform.SetParent(val3.transform, false);
			_listRoot = val4.GetComponent<RectTransform>();
			_listRoot.anchorMin = new Vector2(0f, 1f);
			_listRoot.anchorMax = new Vector2(1f, 1f);
			_listRoot.pivot = new Vector2(0.5f, 1f);
			_listRoot.anchoredPosition = Vector2.zero;
			_listRoot.sizeDelta = new Vector2(0f, 0f);
			_listGrid = val4.GetComponent<GridLayoutGroup>();
			_listGrid.cellSize = new Vector2(100f, 31f);
			_listGrid.spacing = new Vector2(14f, 0f);
			_listGrid.startCorner = (Corner)0;
			_listGrid.startAxis = (Axis)1;
			((LayoutGroup)_listGrid).childAlignment = (TextAnchor)0;
			_listGrid.constraint = (Constraint)1;
			_listGrid.constraintCount = 1;
			((LayoutGroup)_listGrid).padding = new RectOffset(0, 0, 0, 0);
			ApplyPanelSize(_panelWidth, GetMinPanelHeight());
		}

		private float GetTitleBlockHeight()
		{
			return 38f;
		}

		private float GetBorderChromeHeight()
		{
			return _padT + _padB;
		}

		private float GetMinPanelHeight()
		{
			return GetBorderChromeHeight() + GetTitleBlockHeight() + _layoutRowHeight;
		}

		private float GetAvailableScreenHeight()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(1f, GetParentCanvasSize().y);
			float configuredPositionY = GetConfiguredPositionY();
			float num2 = num * (1f - configuredPositionY) - 88f;
			float num3 = num * configuredPositionY - 100f;
			float num4 = 2f * Mathf.Max(0f, Mathf.Min(num2, num3));
			float num5 = num * 0.55f;
			float num6 = num - 88f - 100f;
			float num7 = Mathf.Min(new float[3] { num4, num5, num6 });
			return Mathf.Max(140f, num7);
		}

		private static float GetConfiguredPositionY()
		{
			try
			{
				if (ChestListConfig.UiPositionY != null)
				{
					return Mathf.Clamp01(ChestListConfig.UiPositionY.Value);
				}
			}
			catch
			{
			}
			return 0.55f;
		}

		private Vector2 GetParentCanvasSize()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)(Alive((Object)(object)_panel) ? /*isinst with value type is only supported in some contexts*/: null);
			Vector2 val2;
			if (!((Object)(object)val != (Object)null))
			{
				val2 = Vector2.zero;
			}
			else
			{
				Rect rect = val.rect;
				val2 = ((Rect)(ref rect)).size;
			}
			Vector2 val3 = val2;
			if (val3.x <= 1f || val3.y <= 1f)
			{
				float num = 1080f;
				float num2 = 1920f;
				float num3 = Mathf.Max(1f, (float)Screen.width);
				float num4 = Mathf.Max(1f, (float)Screen.height);
				float num5 = Mathf.Log(num3 / num2, 2f);
				float num6 = Mathf.Log(num4 / num, 2f);
				float num7 = Mathf.Lerp(num5, num6, 0.5f);
				float num8 = Mathf.Pow(2f, num7);
				((Vector2)(ref val3))..ctor(num3 / num8, num4 / num8);
			}
			return val3;
		}

		private void ComputeFitToScreenLayout(int total)
		{
			int value = Mathf.Max(1, total);
			float availableScreenHeight = GetAvailableScreenHeight();
			float num = GetBorderChromeHeight() + GetTitleBlockHeight();
			float num2 = Mathf.Max(22f, availableScreenHeight - num);
			int num3 = 1;
			float num4 = 31f;
			for (int i = 1; i <= 3; i++)
			{
				int num5 = CeilDiv(value, i);
				float num6 = (float)num5 * 31f;
				if (num + num6 <= availableScreenHeight + 0.5f)
				{
					num3 = i;
					num4 = 31f;
					break;
				}
				num3 = i;
				if (i == 3)
				{
					num4 = Mathf.Clamp(num2 / (float)num5, 22f, 31f);
				}
			}
			int num7 = CeilDiv(value, num3);
			float num8 = (float)num7 * num4;
			if (num + num8 > availableScreenHeight + 0.5f)
			{
				num4 = Mathf.Max(22f, num2 / (float)Mathf.Max(1, num7));
			}
			_layoutColumns = num3;
			_layoutRowsPerColumn = num7;
			_layoutRowHeight = num4;
			if (Mathf.Approximately(num4, 31f))
			{
				_layoutIconSize = 27f;
				_layoutItemFontSize = 21f;
			}
			else
			{
				float num9 = Mathf.InverseLerp(22f, 31f, num4);
				_layoutIconSize = Mathf.Lerp(20f, 27f, num9);
				_layoutItemFontSize = Mathf.Lerp(16f, 21f, num9);
			}
		}

		private static int CeilDiv(int value, int divisor)
		{
			if (divisor <= 0)
			{
				return value;
			}
			return (value + divisor - 1) / divisor;
		}

		private float GetMinPanelWidth()
		{
			float num = 300f;
			try
			{
				if (ChestListConfig.MinPanelWidth != null)
				{
					num = ChestListConfig.MinPanelWidth.Value;
				}
			}
			catch
			{
			}
			return Mathf.Clamp(num, 200f, 600f);
		}

		private float GetMaxPanelWidth()
		{
			float num = 470f;
			try
			{
				if (ChestListConfig.MaxPanelWidth != null)
				{
					num = ChestListConfig.MaxPanelWidth.Value;
				}
			}
			catch
			{
			}
			num = Mathf.Clamp(num, 250f, 800f);
			return Mathf.Max(num, GetMinPanelWidth());
		}

		private float GetMaxTotalPanelWidth()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, _layoutColumns);
			float maxPanelWidth = GetMaxPanelWidth();
			float num2 = 14f * (float)Mathf.Max(0, num - 1);
			float num3 = maxPanelWidth * (float)num + num2;
			float num4 = Mathf.Max(maxPanelWidth, GetParentCanvasSize().x - 72f);
			return Mathf.Min(num3, num4);
		}

		private void ApplyLayoutAndAlpha()
		{
			//IL_0027: 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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(ChestListConfig.UiPositionX.Value);
			float configuredPositionY = GetConfiguredPositionY();
			float alpha = Mathf.Clamp01(ChestListConfig.UiAlpha.Value);
			Vector2 parentCanvasSize = GetParentCanvasSize();
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor((num - 0.5f) * parentCanvasSize.x, (configuredPositionY - 0.5f) * parentCanvasSize.y);
			float num2 = (Alive((Object)(object)_panel) ? (_panel.sizeDelta.x * 0.5f) : (_panelWidth * 0.5f));
			float num3 = (Alive((Object)(object)_panel) ? (_panel.sizeDelta.y * 0.5f) : (GetMinPanelHeight() * 0.5f));
			float num4 = parentCanvasSize.x * 0.5f - num2 - 36f;
			float num5 = (0f - parentCanvasSize.x) * 0.5f + num2 + 36f;
			float num6 = parentCanvasSize.y * 0.5f - num3 - 88f;
			float num7 = (0f - parentCanvasSize.y) * 0.5f + num3 + 100f;
			if (num4 < num5)
			{
				val.x = 0f;
			}
			else
			{
				val.x = Mathf.Clamp(val.x, num5, num4);
			}
			if (num6 < num7)
			{
				val.y = 0f;
			}
			else
			{
				val.y = Mathf.Clamp(val.y, num7, num6);
			}
			_panel.anchoredPosition = val;
			if (Alive((Object)(object)_canvasGroup))
			{
				_canvasGroup.alpha = alpha;
			}
			if (Alive((Object)(object)_panelImage))
			{
				((Graphic)_panelImage).color = GetBackgroundColor();
			}
		}

		private void RefreshContents(Container container, Inventory inventory)
		{
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			if (!Alive((Object)(object)container) || inventory == null || !Alive((Object)(object)_title) || !Alive((Object)(object)_listRoot))
			{
				return;
			}
			int num;
			int num2;
			try
			{
				num = inventory.NrOfItems();
				num2 = inventory.NrOfItemsIncludingStacks();
			}
			catch
			{
				return;
			}
			bool value = ChestListConfig.ShowItemImages.Value;
			bool value2 = ChestListConfig.CombineStacks.Value;
			float minPanelWidth = GetMinPanelWidth();
			float maxPanelWidth = GetMaxPanelWidth();
			ChestSortType value3 = ChestListConfig.SortType.Value;
			bool value4 = ChestListConfig.SortAscending.Value;
			int value5 = ChestListConfig.MaxEntries.Value;
			string value6 = ChestListConfig.CapacityFormat.Value;
			if (container == _boundContainer && num == _boundRevision && num2 == _boundStackRevision && value == _boundShowIcons && value2 == _boundCombineStacks && Mathf.Approximately(minPanelWidth, _boundMinPanelWidth) && Mathf.Approximately(maxPanelWidth, _boundMaxPanelWidth) && value3 == _boundSortType && value4 == _boundSortAscending && value5 == _boundMaxEntries && value6 == _boundCapacityFormat)
			{
				return;
			}
			int num3;
			List<ItemData> list;
			try
			{
				List<ItemData> allItems = inventory.GetAllItems();
				num3 = allItems?.Count ?? 0;
				list = BuildGridOrderedCopy(allItems);
			}
			catch
			{
				return;
			}
			if (list == null)
			{
				list = new List<ItemData>();
				num3 = 0;
			}
			BuildDisplayEntries(list, value2);
			SortAndLimitDisplayEntries(value3, value4, value5);
			_boundSortType = value3;
			_boundSortAscending = value4;
			_boundMaxEntries = value5;
			_boundCapacityFormat = value6;
			_boundContainer = container;
			_boundRevision = num;
			_boundStackRevision = num2;
			_boundShowIcons = value;
			_boundCombineStacks = value2;
			_boundMinPanelWidth = minPanelWidth;
			_boundMaxPanelWidth = maxPanelWidth;
			float borderChromeHeight = GetBorderChromeHeight();
			float titleBlockHeight = GetTitleBlockHeight();
			int count = _displayEntries.Count;
			ComputeFitToScreenLayout(count);
			float minPanelHeight = GetMinPanelHeight();
			float num4 = Mathf.Max((float)_layoutRowsPerColumn * _layoutRowHeight, _layoutRowHeight);
			float num5 = borderChromeHeight + titleBlockHeight + num4;
			if (num5 < minPanelHeight)
			{
				num5 = minPanelHeight;
			}
			float availableScreenHeight = GetAvailableScreenHeight();
			if (num5 > availableScreenHeight)
			{
				num5 = availableScreenHeight;
				num4 = Mathf.Max(_layoutRowHeight, num5 - borderChromeHeight - titleBlockHeight);
				_layoutRowHeight = Mathf.Max(22f, num4 / (float)Mathf.Max(1, _layoutRowsPerColumn));
			}
			if (Alive((Object)(object)_title))
			{
				if (Alive((Object)(object)((Component)_title).gameObject) && !((Component)_title).gameObject.activeSelf)
				{
					((Component)_title).gameObject.SetActive(true);
				}
				((TMP_Text)_title).text = GetContainerTitle(container) + FormatCapacity(value6, num, inventory);
			}
			EnsureRowCount(count);
			for (int i = 0; i < _rows.Count; i++)
			{
				RowWidgets rowWidgets = _rows[i];
				if (!Alive((Object)(object)rowWidgets.Root))
				{
					continue;
				}
				if (i >= count)
				{
					rowWidgets.Root.SetActive(false);
					continue;
				}
				rowWidgets.Root.SetActive(true);
				if (Alive((Object)(object)rowWidgets.Layout))
				{
					rowWidgets.Layout.preferredHeight = _layoutRowHeight;
					rowWidgets.Layout.minHeight = _layoutRowHeight;
					rowWidgets.Layout.flexibleHeight = 0f;
				}
				((TMP_Text)rowWidgets.Label).fontStyle = (FontStyles)0;
				((TMP_Text)rowWidgets.Label).fontSize = _layoutItemFontSize;
				DisplayEntry displayEntry = _displayEntries[i];
				ItemData val = displayEntry?.Item;
				if (val == null || val.m_shared == null)
				{
					((Component)rowWidgets.Icon).gameObject.SetActive(false);
					((TMP_Text)rowWidgets.Label).margin = Vector4.zero;
					((TMP_Text)rowWidgets.Label).text = string.Empty;
					if (displayEntry != null && displayEntry.HiddenCount > 0)
					{
						((TMP_Text)rowWidgets.Label).fontStyle = (FontStyles)2;
						((TMP_Text)rowWidgets.Label).text = $"<alpha=#AA>+{displayEntry.HiddenCount} more";
					}
					continue;
				}
				if (value)
				{
					Sprite val2 = null;
					try
					{
						val2 = val.GetIcon();
					}
					catch
					{
						val2 = null;
					}
					bool flag = (Object)(object)val2 != (Object)null;
					((Behaviour)rowWidgets.Icon).enabled = flag;
					rowWidgets.Icon.sprite = val2;
					((Component)rowWidgets.Icon).gameObject.SetActive(flag);
					if (flag && Alive((Object)(object)((Graphic)rowWidgets.Icon).rectTransform))
					{
						((Graphic)rowWidgets.Icon).rectTransform.sizeDelta = new Vector2(_layoutIconSize, _layoutIconSize);
					}
					((TMP_Text)rowWidgets.Label).margin = (Vector4)(flag ? new Vector4(_layoutIconSize + 8f, 0f, 0f, 0f) : Vector4.zero);
				}
				else
				{
					((Component)rowWidgets.Icon).gameObject.SetActive(false);
					((TMP_Text)rowWidgets.Label).margin = Vector4.zero;
				}
				((TMP_Text)rowWidgets.Label).text = FormatItemLabel(val, displayEntry.Stack);
			}
			ApplyListContentSize(count);
			RelayoutPanelWidth(value, count, num5, scheduleDeferredRemeasure: true);
			ApplyListContentSize(count);
			if (!value2 && count != num3)
			{
				ManualLogSource log = ChestPreviewMod.Log;
				if (log != null)
				{
					log.LogDebug((object)$"Chest list row count mismatch: shown={count}, inventory.GetAllItems()={num3}");
				}
			}
			ApplyLayoutAndAlpha();
		}

		private static List<ItemData> BuildGridOrderedCopy(List<ItemData> raw)
		{
			if (raw == null || raw.Count == 0)
			{
				return new List<ItemData>();
			}
			List<ItemData> list = new List<ItemData>(raw.Count);
			for (int i = 0; i < raw.Count; i++)
			{
				ItemData val = raw[i];
				if (val != null)
				{
					list.Add(val);
				}
			}
			list.Sort(CompareGridPos);
			return list;
		}

		private static int CompareGridPos(ItemData a, ItemData b)
		{
			if (a == b)
			{
				return 0;
			}
			if (a == null)
			{
				return 1;
			}
			if (b == null)
			{
				return -1;
			}
			int num = a.m_gridPos.y.CompareTo(b.m_gridPos.y);
			if (num != 0)
			{
				return num;
			}
			return a.m_gridPos.x.CompareTo(b.m_gridPos.x);
		}

		private void ApplyListContentSize(int rowCount)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, _layoutColumns);
			_listContentHeight = Mathf.Max(0f, (float)(_layoutRowsPerColumn = ((rowCount <= 0) ? 1 : Mathf.Max(1, CeilDiv(rowCount, num)))) * _layoutRowHeight);
			if (Alive((Object)(object)_listRoot))
			{
				if (Alive((Object)(object)_listGrid))
				{
					float num2 = Mathf.Max(1f, _panelWidth - _padL - _padR);
					float num3 = 14f * (float)Mathf.Max(0, num - 1);
					float num4 = Mathf.Max(1f, (num2 - num3) / (float)num);
					_listGrid.constraintCount = num;
					_listGrid.cellSize = new Vector2(num4, _layoutRowHeight);
					_listGrid.spacing = new Vector2((num > 1) ? 14f : 0f, 0f);
				}
				Vector2 sizeDelta = _listRoot.sizeDelta;
				sizeDelta.y = _listContentHeight;
				_listRoot.sizeDelta = sizeDelta;
				_listRoot.anchoredPosition = new Vector2(_listRoot.anchoredPosition.x, 0f);
				LayoutRebuilder.ForceRebuildLayoutImmediate(_listRoot);
			}
		}

		private float RelayoutPanelWidth(bool showIcons, int total, float panelHeight, bool scheduleDeferredRemeasure)
		{
			EnsureFontsAppliedForMeasure(total);
			using (BeginInvisibleMeasureScope())
			{
				Canvas.ForceUpdateCanvases();
				float num = MeasurePanelWidth(showIcons, total);
				Canvas.ForceUpdateCanvases();
				num = Mathf.Max(num, MeasurePanelWidth(showIcons, total));
				ApplyPanelSize(num, panelHeight);
				ApplyListContentSize(total);
				if (scheduleDeferredRemeasure)
				{
					_remeasurePanelHeight = panelHeight;
					_remeasureAfterFrame = Time.frameCount + 1;
				}
				return num;
			}
		}

		private void TryDeferredWidthRemeasure()
		{
			if (_remeasureAfterFrame >= 0 && Time.frameCount >= _remeasureAfterFrame)
			{
				_remeasureAfterFrame = -1;
				if (Alive((Object)(object)_panel) && Alive((Object)(object)((Component)_panel).gameObject) && ((Component)_panel).gameObject.activeSelf)
				{
					int count = _displayEntries.Count;
					RelayoutPanelWidth(_boundShowIcons, count, _remeasurePanelHeight, scheduleDeferredRemeasure: false);
					ApplyListContentSize(count);
				}
			}
		}

		private InvisibleMeasureScope BeginInvisibleMeasureScope()
		{
			float previousAlpha = (Alive((Object)(object)_canvasGroup) ? _canvasGroup.alpha : 1f);
			bool num = Alive((Object)(object)_panel) && ((Component)_panel).gameObject.activeSelf;
			bool flag = Alive((Object)(object)_canvas) && ((Behaviour)_canvas).enabled;
			if (!num || !flag)
			{
				if (Alive((Object)(object)_canvasGroup))
				{
					_canvasGroup.alpha = 0f;
				}
				if (Alive((Object)(object)_canvas) && !((Behaviour)_canvas).enabled)
				{
					((Behaviour)_canvas).enabled = true;
				}
				if (Alive((Object)(object)_panel) && !((Component)_panel).gameObject.activeSelf)
				{
					((Component)_panel).gameObject.SetActive(true);
				}
				return new InvisibleMeasureScope(this, restoreAlpha: true, previousAlpha);
			}
			return new InvisibleMeasureScope(this, restoreAlpha: false, previousAlpha);
		}

		private void EnsureFontsAppliedForMeasure(int total)
		{
			if (!TryResolveGameFont(out var _, out var _, out var _, out var _))
			{
				return;
			}
			if (Alive((Object)(object)_title) && (!Alive((Object)(object)((TMP_Text)_title).font) || IsLiberation(((TMP_Text)_title).font)))
			{
				ApplyGameFont(_title, isTitle: true);
			}
			for (int i = 0; i < total && i < _rows.Count; i++)
			{
				TextMeshProUGUI label = _rows[i].Label;
				if (Alive((Object)(object)label))
				{
					if (!Alive((Object)(object)((TMP_Text)label).font) || IsLiberation(((TMP_Text)label).font))
					{
						ApplyGameFont(label, isTitle: false);
					}
					((TMP_Text)label).fontSize = _layoutItemFontSize;
				}
			}
		}

		private float MeasurePanelWidth(bool showIcons, int total)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			float num2 = 0f;
			float minPanelWidth = GetMinPanelWidth();
			float maxPanelWidth = GetMaxPanelWidth();
			if (Alive((Object)(object)_title) && !string.IsNullOrEmpty(((TMP_Text)_title).text))
			{
				PrepareTmpForMeasure(_title);
				num2 = ((TMP_Text)_title).GetPreferredValues(((TMP_Text)_title).text).x;
			}
			for (int i = 0; i < total && i < _rows.Count; i++)
			{
				RowWidgets rowWidgets = _rows[i];
				if (Alive((Object)(object)rowWidgets.Label) && !string.IsNullOrEmpty(((TMP_Text)rowWidgets.Label).text))
				{
					Vector4 margin = ((TMP_Text)rowWidgets.Label).margin;
					((TMP_Text)rowWidgets.Label).margin = Vector4.zero;
					PrepareTmpForMeasure(rowWidgets.Label);
					float x = ((TMP_Text)rowWidgets.Label).GetPreferredValues(((TMP_Text)rowWidgets.Label).text).x;
					((TMP_Text)rowWidgets.Label).margin = margin;
					float num3 = 0f;
					if (showIcons && Alive((Object)(object)rowWidgets.Icon) && ((Component)rowWidgets.Icon).gameObject.activeSelf)
					{
						num3 = _layoutIconSize + 8f;
					}
					num = Mathf.Max(num, num3 + x);
				}
			}
			int num4 = Mathf.Max(1, _layoutColumns);
			float maxTotalPanelWidth = GetMaxTotalPanelWidth();
			if (num <= 0.5f && num2 <= 0.5f)
			{
				return Mathf.Min(minPanelWidth * (float)num4 + 14f * (float)Mathf.Max(0, num4 - 1), maxTotalPanelWidth);
			}
			float num5 = Mathf.Max(num, num2) + _padL + _padR + 28f;
			num5 = Mathf.Clamp(num5, minPanelWidth, maxPanelWidth);
			if (num4 <= 1)
			{
				return num5;
			}
			float num6 = Mathf.Clamp(num + 28f, Mathf.Max(1f, minPanelWidth - _padL - _padR), Mathf.Max(1f, maxPanelWidth - _padL - _padR));
			float num7 = 14f * (float)(num4 - 1);
			float num8 = _padL + _padR + num6 * (float)num4 + num7;
			float num9 = num2 + _padL + _padR + 28f;
			return Mathf.Clamp(Mathf.Max(num8, Mathf.Min(num9, maxTotalPanelWidth)), minPanelWidth, maxTotalPanelWidth);
		}

		private static void PrepareTmpForMeasure(TextMeshProUGUI tmp)
		{
			if (Alive((Object)(object)tmp))
			{
				((TMP_Text)tmp).ForceMeshUpdate(true, false);
			}
		}

		private void ApplyPanelSize(float panelWidth, float panelHeight)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (Alive((Object)(object)_panel) && Alive((Object)(object)_content))
			{
				panelHeight = Mathf.Max(panelHeight, GetMinPanelHeight());
				float minPanelWidth = GetMinPanelWidth();
				float maxTotalPanelWidth = GetMaxTotalPanelWidth();
				panelWidth = Mathf.Clamp(panelWidth, minPanelWidth, maxTotalPanelWidth);
				_panelWidth = panelWidth;
				_panel.sizeDelta = new Vector2(panelWidth, panelHeight);
				ApplyContentInsets();
			}
		}

		private void ApplyContentInsets()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (Alive((Object)(object)_content))
			{
				_content.anchorMin = Vector2.zero;
				_content.anchorMax = Vector2.one;
				_content.offsetMin = new Vector2(_padL, _padB);
				_content.offsetMax = new Vector2(0f - _padR, 0f - _padT);
			}
		}

		private void EnsureRowCount(int count)
		{
			while (_rows.Count < count)
			{
				_rows.Add(CreateRow(_rows.Count));
			}
		}

		private RowWidgets CreateRow(int index)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject($"Row_{index}", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			val.transform.SetParent((Transform)(object)_listRoot, false);
			val.SetActive(false);
			RectTransform component = val.GetComponent<RectTransform>();
			LayoutElement component2 = val.GetComponent<LayoutElement>();
			component2.preferredHeight = 31f;
			component2.minHeight = 31f;
			component2.flexibleHeight = 0f;
			component2.flexibleWidth = 0f;
			component2.layoutPriority = 100;
			GameObject val2 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0f, 0.5f);
			component3.anchorMax = new Vector2(0f, 0.5f);
			component3.pivot = new Vector2(0f, 0.5f);
			component3.anchoredPosition = Vector2.zero;
			component3.sizeDelta = new Vector2(27f, 27f);
			Image component4 = val2.GetComponent<Image>();
			component4.preserveAspect = true;
			((Graphic)component4).raycastTarget = false;
			((MaskableGraphic)component4).maskable = true;
			val2.SetActive(false);
			TextMeshProUGUI val3 = CreateGameTmp("Label", val.transform, isTitle: false);
			StretchFull(((TMP_Text)val3).rectTransform);
			((TMP_Text)val3).alignment = (TextAlignmentOptions)4097;
			((Graphic)val3).raycastTarget = false;
			((MaskableGraphic)val3).maskable = true;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val3).textWrappingMode = (TextWrappingModes)0;
			((Component)val3).gameObject.SetActive(true);
			val.SetActive(true);
			return new RowWidgets
			{
				Root = val,
				Rect = component,
				Layout = component2,
				Icon = component4,
				Label = val3
			};
		}

		private void BuildDisplayEntries(List<ItemData> items, bool combineStacks)
		{
			_displayEntries.Clear();
			_mergeIndexByKey.Clear();
			if (items == null || items.Count == 0)
			{
				return;
			}
			if (!combineStacks)
			{
				for (int i = 0; i < items.Count; i++)
				{
					ItemData val = items[i];
					if (val != null)
					{
						_displayEntries.Add(new DisplayEntry
						{
							Item = val,
							Stack = val.m_stack
						});
					}
				}
				return;
			}
			for (int j = 0; j < items.Count; j++)
			{
				ItemData val2 = items[j];
				if (val2 != null && val2.m_shared != null)
				{
					string key = BuildMergeKey(val2);
					if (_mergeIndexByKey.TryGetValue(key, out var value))
					{
						_displayEntries[value].Stack += val2.m_stack;
						continue;
					}
					_mergeIndexByKey[key] = _displayEntries.Count;
					_displayEntries.Add(new DisplayEntry
					{
						Item = val2,
						Stack = val2.m_stack
					});
				}
			}
		}

		private void SortAndLimitDisplayEntries(ChestSortType sortType, bool ascending, int maxEntries)
		{
			for (int i = 0; i < _displayEntries.Count; i++)
			{
				DisplayEntry displayEntry = _displayEntries[i];
				displayEntry.Order = i;
				displayEntry.SortName = Localize(displayEntry.Item?.m_shared?.m_name);
			}
			_displayEntries.Sort((DisplayEntry a, DisplayEntry b) => CompareEntries(a, b, sortType, ascending));
			if (maxEntries >= 0 && _displayEntries.Count > maxEntries)
			{
				int num = _displayEntries.Count - maxEntries;
				_displayEntries.RemoveRange(maxEntries, num);
				_displayEntries.Add(new DisplayEntry
				{
					HiddenCount = num
				});
			}
		}

		private static int CompareEntries(DisplayEntry a, DisplayEntry b, ChestSortType sortType, bool ascending)
		{
			int num = 0;
			switch (sortType)
			{
			case ChestSortType.Value:
				num = GetSortValue(a).CompareTo(GetSortValue(b));
				break;
			case ChestSortType.Weight:
				num = GetSortWeight(a).CompareTo(GetSortWeight(b));
				break;
			case ChestSortType.Name:
				num = string.Compare(a.SortName, b.SortName, StringComparison.CurrentCultureIgnoreCase);
				break;
			}
			if (!ascending)
			{
				num = -num;
			}
			if (num == 0 && sortType != ChestSortType.Name)
			{
				num = string.Compare(a.SortName, b.SortName, StringComparison.CurrentCultureIgnoreCase);
			}
			if (num == 0)
			{
				num = a.Order.CompareTo(b.Order);
			}
			return num;
		}

		private static float GetSortValue(DisplayEntry entry)
		{
			SharedData val = entry.Item?.m_shared;
			if (val == null)
			{
				return 0f;
			}
			return (float)val.m_value * (float)entry.Stack;
		}

		private static float GetSortWeight(DisplayEntry entry)
		{
			SharedData val = entry.Item?.m_shared;
			if (val == null)
			{
				return 0f;
			}
			return val.m_weight * (float)entry.Stack;
		}

		private string BuildMergeKey(ItemData item)
		{
			_keyBuilder.Length = 0;
			SharedData shared = item.m_shared;
			string text = ((shared != null) ? shared.m_name : string.Empty);
			_keyBuilder.Append(text ?? string.Empty);
			_keyBuilder.Append('|');
			_keyBuilder.Append(item.m_worldLevel);
			if (shared != null && shared.m_maxQuality > 1)
			{
				_keyBuilder.Append('|');
				_keyBuilder.Append('q');
				_keyBuilder.Append(item.m_quality);
			}
			if (shared != null && shared.m_variants > 1)
			{
				_keyBuilder.Append('|');
				_keyBuilder.Append('v');
				_keyBuilder.Append(item.m_variant);
			}
			return _keyBuilder.ToString();
		}

		private static string GetContainerTitle(Container container)
		{
			if (!Alive((Object)(object)container))
			{
				return "Chest";
			}
			try
			{
				if (container != null)
				{
					string hoverName = ((Hoverable)container).GetHoverName();
					if (!string.IsNullOrEmpty(hoverName))
					{
						return Localize(hoverName);
					}
				}
			}
			catch
			{
			}
			string name = container.m_name;
			if (!string.IsNullOrEmpty(name))
			{
				return Localize(name);
			}
			try
			{
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					string name2 = inventory.GetName();
					if (!string.IsNullOrEmpty(name2))
					{
						return Localize(name2);
					}
				}
			}
			catch
			{
			}
			try
			{
				Piece val = ChestTarget.ContainerPiece.Invoke(container);
				if (!Alive((Object)(object)val))
				{
					val = ((Component)container).GetComponentInParent<Piece>();
				}
				if (Alive((Object)(object)val) && !string.IsNullOrEmpty(val.m_name))
				{
					return Localize(val.m_name);
				}
			}
			catch
			{
			}
			return "Chest";
		}

		private static string FormatCapacity(string format, int usedSlots, Inventory inventory)
		{
			if (string.IsNullOrEmpty(format))
			{
				return string.Empty;
			}
			int num = inventory.GetWidth() * inventory.GetHeight();
			string text;
			try
			{
				text = string.Format(format, usedSlots, num);
			}
			catch (FormatException)
			{
				text = format;
			}
			return "  <alpha=#AA>" + text;
		}

		private string FormatItemLabel(ItemData item, int stack)
		{
			_labelBuilder.Length = 0;
			if (item == null || item.m_shared == null)
			{
				return string.Empty;
			}
			string value = Localize(item.m_shared.m_name);
			_labelBuilder.Append(value);
			if (stack > 1)
			{
				_labelBuilder.Append("  x").Append(stack);
			}
			if (item.m_quality > 1)
			{
				_labelBuilder.Append("  [Q").Append(item.m_quality).Append(']');
			}
			return _labelBuilder.ToString();
		}

		private static string Localize(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return string.Empty;
			}
			if (Localization.instance != null)
			{
				return Localization.instance.Localize(token);
			}
			return token;
		}

		private static Color GetBackgroundColor()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return new Color(0f, 0f, 0f, Mathf.Clamp01(ChestListConfig.BackgroundAlpha.Value));
		}

		private static TextMeshProUGUI CreateGameTmp(string name, Transform parent, bool isTitle)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			ApplyGameFont(val2, isTitle);
			if (!Alive((Object)(object)((TMP_Text)val2).font) || IsLiberation(((TMP_Text)val2).font))
			{
				ApplyGameFont(val2, isTitle);
			}
			return val2;
		}

		private static void ApplyGameFont(TextMeshProUGUI text, bool isTitle)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (!Alive((Object)(object)text) || !TryResolveGameFont(out var font, out var material, out var _, out var color) || IsLiberation(font) || !Alive((Object)(object)font))
			{
				return;
			}
			((TMP_Text)text).font = font;
			if (Alive((Object)(object)material))
			{
				((TMP_Text)text).fontSharedMaterial = material;
			}
			else if (Alive((Object)(object)((TMP_Asset)font).material))
			{
				((TMP_Text)text).fontSharedMaterial = ((TMP_Asset)font).material;
			}
			if (Alive((Object)(object)((TMP_Text)text).font) && IsLiberation(((TMP_Text)text).font))
			{
				((TMP_Text)text).font = font;
				if (Alive((Object)(object)material))
				{
					((TMP_Text)text).fontSharedMaterial = material;
				}
			}
			((TMP_Text)text).fontSize = (isTitle ? 25f : 21f);
			((Graphic)text).color = (Color)(isTitle ? new Color(1f, 0.92f, 0.7f, 1f) : color);
			((TMP_Text)text).fontStyle = (FontStyles)0;
		}

		private static bool TryResolveGameFont(out TMP_FontAsset font, out Material material, out float size, out Color color)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			font = null;
			material = null;
			size = _cachedFontSize;
			color = _cachedFontColor;
			if (Alive((Object)(object)_cachedFont))
			{
				font = _cachedFont;
				material = (Alive((Object)(object)_cachedFontMaterial) ? _cachedFontMaterial : ((TMP_Asset)_cachedFont).material);
				size = _cachedFontSize;
				color = _cachedFontColor;
				return !IsLiberation(font);
			}
			_cachedFont = null;
			_cachedFontMaterial = null;
			InventoryGui instance = InventoryGui.instance;
			if (Alive((Object)(object)instance) && (TryTakeFont(instance.m_containerName, ref font, ref material, ref size, ref color) || TryTakeFont(instance.m_weight, ref font, ref material, ref size, ref color) || TryTakeFont(instance.m_containerWeight, ref font, ref material, ref size, ref color) || TryTakeFont(instance.m_playerName, ref font, ref material, ref size, ref color) || TryTakeFontFromChildren(((Component)instance).gameObject, ref font, ref material, ref size, ref color)))
			{
				CacheGameFont(font, material, size, color);
				return true;
			}
			if (Alive((Object)(object)Hud.instance) && TryTakeFontFromChildren(((Component)Hud.instance).gameObject, ref font, ref material, ref size, ref color))
			{
				CacheGameFont(font, material, size, color);
				return true;
			}
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			TMP_FontAsset[] array2 = array;
			foreach (TMP_FontAsset val in array2)
			{
				if (Alive((Object)(object)val) && !string.IsNullOrEmpty(((Object)val).name) && !IsLiberation(val))
				{
					string name = ((Object)val).name;
					if (name.IndexOf("Norse", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Valheim", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						font = val;
						material = ((TMP_Asset)val).material;
						CacheGameFont(font, material, size, color);
						return true;
					}
				}
			}
			array2 = array;
			foreach (TMP_FontAsset val2 in array2)
			{
				if (Alive((Object)(object)val2) && !string.IsNullOrEmpty(((Object)val2).name) && !IsLiberation(val2))
				{
					font = val2;
					material = ((TMP_Asset)val2).material;
					CacheGameFont(font, material, size, color);
					return true;
				}
			}
			return false;
		}

		private static bool TryTakeFont(TMP_Text source, ref TMP_FontAsset font, ref Material material, ref float size, ref Color color)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!Alive((Object)(object)source) || !Alive((Object)(object)source.font) || IsLiberation(source.font))
			{
				return false;
			}
			font = source.font;
			material = (Alive((Object)(object)source.fontSharedMaterial) ? source.fontSharedMaterial : ((TMP_Asset)source.font).material);
			size = ((source.fontSize > 1f) ? source.fontSize : 16f);
			color = ((Graphic)source).color;
			return true;
		}

		private static bool TryTakeFontFromChildren(GameObject root, ref TMP_FontAsset font, ref Material material, ref float size, ref Color color)
		{
			if (!Alive((Object)(object)root))
			{
				return false;
			}
			TextMeshProUGUI[] componentsInChildren = root.GetComponentsInChildren<TextMeshProUGUI>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (TryTakeFont((TMP_Text)(object)componentsInChildren[i], ref font, ref material, ref size, ref color))
				{
					return true;
				}
			}
			return false;
		}

		private static void CacheGameFont(TMP_FontAsset font, Material material, float size, Color color)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			_cachedFont = font;
			_cachedFontMaterial = (Alive((Object)(object)material) ? material : (((Object)(object)font != (Object)null) ? ((TMP_Asset)font).material : null));
			_cachedFontSize = ((size > 1f) ? size : 16f);
			_cachedFontColor = color;
		}

		private static bool IsLiberation(TMP_FontAsset font)
		{
			if (!Alive((Object)(object)font) || string.IsNullOrEmpty(((Object)font).name))
			{
				return true;
			}
			return ((Object)font).name.IndexOf("Liberation", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static void StretchFull(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.offsetMin = Vector2.zero;
			rt.offsetMax = Vector2.zero;
		}

		private static bool Alive(Object obj)
		{
			return obj != (Object)null;
		}

		private void SafeShow()
		{
			if (_uiBuilt)
			{
				if (Alive((Object)(object)_canvas) && !((Behaviour)_canvas).enabled)
				{
					((Behaviour)_canvas).enabled = true;
				}
				if (Alive((Object)(object)_panel) && !((Component)_panel).gameObject.activeSelf)
				{
					((Component)_panel).gameObject.SetActive(true);
				}
			}
		}

		private void SafeHide()
		{
			_boundContainer = null;
			_boundRevision = -1;
			_boundStackRevision = -1;
			_boundShowIcons = false;
			_boundCombineStacks = false;
			_boundMinPanelWidth = -1f;
			_boundMaxPanelWidth = -1f;
			_boundMaxEntries = int.MinValue;
			_remeasureAfterFrame = -1;
			_listContentHeight = 0f;
			_layoutColumns = 1;
			_layoutRowsPerColumn = 1;
			_layoutRowHeight = 31f;
			_layoutIconSize = 27f;
			_layoutItemFontSize = 21f;
			if (_uiBuilt && Alive((Object)(object)_panel) && ((Component)_panel).gameObject.activeSelf)
			{
				((Component)_panel).gameObject.SetActive(false);
			}
		}
	}
}
namespace ChestPreview.Patches
{
	[HarmonyPatch(typeof(Player), "OnDestroy")]
	internal static class PlayerOnDestroyPatch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				ChestTarget.Clear();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateHover")]
	internal static class PlayerUpdateHoverPatch
	{
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				ChestTarget.SetFromHoverObject(((Humanoid)__instance).GetHoverObject());
			}
		}
	}
}