Decompiled source of ChestPeek v1.0.0

ChestPeek.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using ConditionalConfigSync;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ChestPeek")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ChestPeek")]
[assembly: AssemblyTitle("ChestPeek")]
[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 ChestPeek
{
	[BepInPlugin("com.dreich.chestpeek", "Chest Peek", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ChestPeekPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.dreich.chestpeek";

		public const string Name = "Chest Peek";

		public const string Version = "1.0.0";

		internal const string ConfigSyncGuid = "_shudnal.ConditionalConfigSync";

		internal static bool ConfigSyncAvailable;

		private static ConfigEntry<bool> ConfigLockedEntry;

		private const int DefaultColumns = 6;

		private const int DefaultRows = 3;

		private const int MaxGridSide = 12;

		private const float DefaultScale = 0.6f;

		private const float MinScale = 0.25f;

		private const float MaxScale = 1.5f;

		private const float DefaultVerticalOffset = -6f;

		private const float MaxOffset = 1000f;

		internal static ConfigEntry<bool> ModEnabled;

		internal static ConfigEntry<int> Columns;

		internal static ConfigEntry<int> Rows;

		internal static ConfigEntry<float> Scale;

		internal static ConfigEntry<float> HorizontalOffset;

		internal static ConfigEntry<float> VerticalOffset;

		internal static ConfigEntry<bool> ShowTotal;

		internal static ConfigEntry<string> TotalText;

		internal static ConfigEntry<bool> HideUnopened;

		internal static ConfigEntry<bool> RespectAccess;

		internal static ConfigEntry<bool> ShowCarts;

		internal static ConfigEntry<bool> ShowArmorStands;

		private void Awake()
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			ConfigSyncAvailable = Chainloader.PluginInfos.ContainsKey("_shudnal.ConditionalConfigSync");
			if (ConfigSyncAvailable)
			{
				ConfigSyncCompat.Initialize("com.dreich.chestpeek", "Chest Peek", "1.0.0");
			}
			ConfigLockedEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock Configuration", true, "If on, the configuration is locked and can be changed by server admins only. Requires ConditionalConfigSync.");
			if (ConfigSyncAvailable)
			{
				ConfigSyncCompat.AddLockingConfigEntry(ConfigLockedEntry);
			}
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show what is inside a chest when you look at it.");
			HideUnopened = BindShared("General", "HideUnopenedChests", defaultValue: true, "Chests you didn't build, like the ones in dungeons and villages, show nothing until you have opened them yourself.");
			RespectAccess = BindShared("General", "RespectAccess", defaultValue: true, "Chests you can't open, like other players' private chests or chests inside someone else's ward, show nothing.");
			ShowCarts = BindShared("General", "ShowCarts", defaultValue: true, "Also peek into carts.");
			ShowArmorStands = BindShared("General", "ShowArmorStands", defaultValue: true, "Also show what is hanging on armor stands.");
			Columns = ((BaseUnityPlugin)this).Config.Bind<int>("Layout", "Columns", 6, new ConfigDescription("Item icons per row.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>()));
			Rows = ((BaseUnityPlugin)this).Config.Bind<int>("Layout", "Rows", 3, new ConfigDescription("Rows of item icons. When a chest holds more kinds of items than fit, the last icon shows how many more there are.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>()));
			Scale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Scale", 0.6f, new ConfigDescription("Size of the icons compared to the game's own chest window. 1 is the same size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 1.5f), Array.Empty<object>()));
			HorizontalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "HorizontalOffset", 0f, new ConfigDescription("How far right of the game's hover text the icons sit. Negative moves them left.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 1000f), Array.Empty<object>()));
			VerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "VerticalOffset", -6f, new ConfigDescription("How far below the game's hover text the icons sit. More negative moves them further down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 1000f), Array.Empty<object>()));
			ShowTotal = ((BaseUnityPlugin)this).Config.Bind<bool>("Layout", "ShowTotal", true, "Show how many items are inside in total under the icons.");
			TotalText = ((BaseUnityPlugin)this).Config.Bind<string>("Text", "Total", "{0} items", "The total under the icons. {0} is the number of items.");
			((Component)this).gameObject.AddComponent<PeekPanel>();
		}

		private ConfigEntry<T> BindShared<T>(string section, string key, T defaultValue, string description)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, description);
			if (ConfigSyncAvailable)
			{
				ConfigSyncCompat.AddConfigEntry<T>(val, serverControlled: true);
			}
			return val;
		}
	}
	internal static class ConfigSyncCompat
	{
		private static object configSync;

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Initialize(string guid, string name, string version)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			//IL_002e: Expected O, but got Unknown
			configSync = (object)new ConfigSync(guid)
			{
				DisplayName = name,
				CurrentVersion = version,
				MinimumRequiredVersion = version,
				ModRequired = false,
				ModRequirementMode = (ModRequirementMode)1
			};
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void AddLockingConfigEntry(ConfigEntry<bool> entry)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			((ConditionalConfigSync)(ConfigSync)configSync).AddLockingConfigEntry<bool>(entry);
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void AddConfigEntry<T>(ConfigEntry<T> entry, bool serverControlled)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			((ConditionalConfigSync)(ConfigSync)configSync).AddConfigEntry<T>(entry, (ConfigSyncMode)((!serverControlled) ? 2 : 0));
		}
	}
	internal static class ChestAccess
	{
		private const string OpenedKey = "ChestPeek_Opened";

		private const char OpenedSeparator = ',';

		private const float NoRadius = 0f;

		private const bool NoFlash = false;

		private const bool NotWardCheck = false;

		private static readonly FieldRef<Container, ZNetView> viewOf = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

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

		private static readonly FieldRef<Vagon, Container> cartContainer = AccessTools.FieldRefAccess<Vagon, Container>("m_container");

		private static readonly FieldRef<InventoryGui, Container> openContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer");

		private static readonly HashSet<string> opened = new HashSet<string>();

		private static Player openedOwner;

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

		internal static Container Hovered(GameObject hover)
		{
			Container componentInParent = hover.GetComponentInParent<Container>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return componentInParent;
			}
			if (!ChestPeekPlugin.ShowCarts.Value)
			{
				return null;
			}
			Vagon componentInParent2 = hover.GetComponentInParent<Vagon>();
			if (!((Object)(object)componentInParent2 != (Object)null))
			{
				return null;
			}
			return cartContainer.Invoke(componentInParent2);
		}

		internal static bool Locked(Container container, Player player)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!ChestPeekPlugin.RespectAccess.Value)
			{
				return false;
			}
			if (!mayOpen(container, player.GetPlayerID()))
			{
				return true;
			}
			return !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false);
		}

		internal static bool Unknown(Container container)
		{
			if (!ChestPeekPlugin.HideUnopened.Value)
			{
				return false;
			}
			if ((Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null)
			{
				return false;
			}
			if (BuiltByPlayer(container))
			{
				return false;
			}
			string text = IdOf(container);
			if (text != null)
			{
				return !OpenedBy(Player.m_localPlayer).Contains(text);
			}
			return true;
		}

		internal static void RememberOpened(Player player)
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)player == (Object)null || (Object)(object)instance == (Object)null || !instance.IsContainerOpen())
			{
				return;
			}
			Container val = openContainer.Invoke(instance);
			if (!((Object)(object)val == (Object)null) && !BuiltByPlayer(val))
			{
				string text = IdOf(val);
				if (text != null && OpenedBy(player).Add(text))
				{
					player.m_customData["ChestPeek_Opened"] = string.Join(','.ToString(), opened);
				}
			}
		}

		private static bool BuiltByPlayer(Container container)
		{
			if ((Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null)
			{
				return true;
			}
			Piece val = pieceOf.Invoke(container) ?? ((Component)container).GetComponentInParent<Piece>();
			if ((Object)(object)val != (Object)null)
			{
				return val.IsPlacedByPlayer();
			}
			return false;
		}

		private static HashSet<string> OpenedBy(Player player)
		{
			if ((Object)(object)player == (Object)(object)openedOwner)
			{
				return opened;
			}
			openedOwner = player;
			opened.Clear();
			if ((Object)(object)player != (Object)null && player.m_customData.TryGetValue("ChestPeek_Opened", out var value))
			{
				opened.UnionWith(value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
			}
			return opened;
		}

		private static string IdOf(Container container)
		{
			ZNetView val = viewOf.Invoke(container);
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return null;
			}
			return ((object)Unsafe.As<ZDOID, ZDOID>(ref val.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString();
		}
	}
	internal static class StandContents
	{
		private const int NoItem = 0;

		private static readonly FieldRef<ArmorStand, ZNetView> viewOf = AccessTools.FieldRefAccess<ArmorStand, ZNetView>("m_nview");

		private static readonly FieldInfo slotsField = AccessTools.Field(typeof(ArmorStand), "m_slots");

		private static readonly Func<ArmorStand, int, int> attachedItem = AccessTools.MethodDelegate<Func<ArmorStand, int, int>>(AccessTools.Method(typeof(ArmorStand), "GetAttachedItem", new Type[1] { typeof(int) }, (Type[])null), (object)null, true);

		internal static ArmorStand Hovered(GameObject hover)
		{
			if (!ChestPeekPlugin.ShowArmorStands.Value)
			{
				return null;
			}
			return hover.GetComponentInParent<ArmorStand>();
		}

		internal static List<ItemDrop> Items(ArmorStand stand)
		{
			List<ItemDrop> list = new List<ItemDrop>();
			ZNetView val = viewOf.Invoke(stand);
			if ((Object)(object)val == (Object)null || !val.IsValid() || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return list;
			}
			if (!(slotsField.GetValue(stand) is ICollection collection))
			{
				return list;
			}
			for (int i = 0; i < collection.Count; i++)
			{
				int num = attachedItem(stand, i);
				if (num != 0)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(num);
					ItemDrop val2 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
					if ((Object)(object)val2 != (Object)null)
					{
						list.Add(val2);
					}
				}
			}
			return list;
		}
	}
	internal class PeekPanel : MonoBehaviour
	{
		private struct Entry
		{
			internal Sprite Icon;

			internal int Count;
		}

		private class Slot
		{
			internal GameObject Root;

			internal RectTransform Body;

			internal Image Icon;

			internal TMP_Text Count;
		}

		private const float RefreshSeconds = 0.25f;

		private const float FallbackSpacing = 6f;

		private const float FallbackSlotSize = 64f;

		private const int SingleItem = 1;

		private const string MorePrefix = "+";

		private const string IconChild = "icon";

		private const string AmountChild = "amount";

		private const float FallbackSlotOpacity = 0.35f;

		private static readonly Color FallbackSlot = new Color(0f, 0f, 0f, 0.35f);

		private RectTransform panel;

		private RectTransform grid;

		private GridLayoutGroup layout;

		private TextMeshProUGUI total;

		private GameObject slotPrefab;

		private float slotNativeSize = 64f;

		private float slotSpacing = 6f;

		private readonly List<Slot> slots = new List<Slot>();

		private readonly Dictionary<string, Entry> totals = new Dictionary<string, Entry>();

		private Component shown;

		private float refreshTimer;

		private static readonly FieldRef<InventoryGrid, GameObject> elementPrefab = AccessTools.FieldRefAccess<InventoryGrid, GameObject>("m_elementPrefab");

		private static readonly FieldRef<InventoryGrid, float> elementSpace = AccessTools.FieldRefAccess<InventoryGrid, float>("m_elementSpace");

		private static readonly FieldRef<InventoryGui, InventoryGrid> containerGrid = AccessTools.FieldRefAccess<InventoryGui, InventoryGrid>("m_containerGrid");

		private void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			ChestAccess.RememberOpened(localPlayer);
			Component val = Target(localPlayer);
			if ((Object)(object)val == (Object)null)
			{
				Hide();
			}
			else if (!((Object)(object)panel == (Object)null) || Build())
			{
				FollowHoverText();
				refreshTimer -= Time.deltaTime;
				if (!((Object)(object)val == (Object)(object)shown) || !(refreshTimer > 0f))
				{
					shown = val;
					refreshTimer = 0.25f;
					((Component)panel).gameObject.SetActive(Fill(val));
				}
			}
		}

		private void FollowHoverText()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text hoverName = (TMP_Text)(object)Hud.instance.m_hoverName;
			hoverName.ForceMeshUpdate(false, false);
			TMP_TextInfo textInfo = hoverName.textInfo;
			float num = float.MaxValue;
			float num2 = float.MaxValue;
			for (int i = 0; i < textInfo.characterCount; i++)
			{
				TMP_CharacterInfo val = textInfo.characterInfo[i];
				if (val.isVisible)
				{
					num = Mathf.Min(num, val.bottomLeft.x);
					num2 = Mathf.Min(num2, textInfo.lineInfo[val.lineNumber].descender);
				}
			}
			if (num == float.MaxValue)
			{
				Rect rect = hoverName.rectTransform.rect;
				num = ((Rect)(ref rect)).xMin;
				num2 = ((Rect)(ref rect)).center.y;
			}
			((Transform)panel).position = ((Transform)hoverName.rectTransform).TransformPoint(new Vector3(num, num2, 0f));
			RectTransform obj = panel;
			obj.anchoredPosition += new Vector2(ChestPeekPlugin.HorizontalOffset.Value, ChestPeekPlugin.VerticalOffset.Value);
		}

		private static Component Target(Player player)
		{
			if (!ChestPeekPlugin.ModEnabled.Value)
			{
				return null;
			}
			if ((Object)(object)player == (Object)null || (Object)(object)Hud.instance == (Object)null || Hud.IsUserHidden())
			{
				return null;
			}
			if (InventoryGui.IsVisible() || Minimap.IsOpen() || Menu.IsVisible())
			{
				return null;
			}
			GameObject hoverObject = ((Humanoid)player).GetHoverObject();
			if ((Object)(object)hoverObject == (Object)null)
			{
				return null;
			}
			Container val = ChestAccess.Hovered(hoverObject);
			if ((Object)(object)val != (Object)null)
			{
				if (val.GetInventory() == null || ChestAccess.Locked(val, player))
				{
					return null;
				}
				return (Component)(object)val;
			}
			return (Component)(object)StandContents.Hovered(hoverObject);
		}

		private void Hide()
		{
			shown = null;
			if ((Object)(object)panel != (Object)null && ((Component)panel).gameObject.activeSelf)
			{
				((Component)panel).gameObject.SetActive(false);
			}
		}

		private bool Build()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00c6: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			InventoryGui instance2 = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_rootObject == (Object)null || (Object)(object)instance.m_hoverName == (Object)null || (Object)(object)instance2 == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject("ChestPeek", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasGroup),
				typeof(VerticalLayoutGroup),
				typeof(ContentSizeFitter)
			});
			panel = (RectTransform)val.transform;
			((Transform)panel).SetParent(instance.m_rootObject.transform, false);
			RectTransform obj = panel;
			RectTransform obj2 = panel;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			obj2.anchorMax = val2;
			obj.anchorMin = val2;
			panel.pivot = new Vector2(0f, 1f);
			CanvasGroup component = val.GetComponent<CanvasGroup>();
			component.interactable = false;
			component.blocksRaycasts = false;
			VerticalLayoutGroup component2 = val.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component2).spacing = 6f;
			((LayoutGroup)component2).childAlignment = (TextAnchor)0;
			bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = true);
			((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = childControlWidth;
			childControlWidth = (((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false);
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = childControlWidth;
			ContentSizeFitter component3 = val.GetComponent<ContentSizeFitter>();
			FitMode horizontalFit = (FitMode)2;
			component3.verticalFit = (FitMode)2;
			component3.horizontalFit = horizontalFit;
			GameObject val3 = new GameObject("Items", new Type[2]
			{
				typeof(RectTransform),
				typeof(GridLayoutGroup)
			});
			grid = (RectTransform)val3.transform;
			((Transform)grid).SetParent((Transform)(object)panel, false);
			layout = val3.GetComponent<GridLayoutGroup>();
			layout.constraint = (Constraint)1;
			((LayoutGroup)layout).childAlignment = (TextAnchor)0;
			total = MakeText("Total", (Transform)(object)panel, (TMP_Text)(object)instance.m_hoverName);
			InventoryGrid val4 = containerGrid.Invoke(instance2);
			slotPrefab = (((Object)(object)val4 != (Object)null) ? elementPrefab.Invoke(val4) : null);
			if ((Object)(object)slotPrefab != (Object)null)
			{
				Rect rect = ((RectTransform)slotPrefab.transform).rect;
				if (((Rect)(ref rect)).width > 0f)
				{
					slotNativeSize = ((Rect)(ref rect)).width;
				}
				float num = elementSpace.Invoke(val4) - slotNativeSize;
				if (num >= 0f)
				{
					slotSpacing = num;
				}
			}
			layout.spacing = new Vector2(slotSpacing, slotSpacing);
			layout.cellSize = new Vector2(slotNativeSize, slotNativeSize);
			val.SetActive(false);
			return true;
		}

		private static TextMeshProUGUI MakeText(string name, Transform parent, TMP_Text style)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val.transform.SetParent(parent, false);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).font = style.font;
			((TMP_Text)component).fontSharedMaterial = style.fontSharedMaterial;
			((TMP_Text)component).fontSize = style.fontSize;
			((Graphic)component).color = ((Graphic)style).color;
			((TMP_Text)component).alignment = (TextAlignmentOptions)513;
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
			return component;
		}

		private bool Fill(Component target)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			float value = ChestPeekPlugin.Scale.Value;
			((Transform)panel).localScale = new Vector3(value, value, 1f);
			int value2 = ChestPeekPlugin.Columns.Value;
			int num = value2 * ChestPeekPlugin.Rows.Value;
			layout.constraintCount = value2;
			Container val = (Container)(object)((target is Container) ? target : null);
			if (val != null && ChestAccess.Unknown(val))
			{
				return false;
			}
			((Component)total).gameObject.SetActive(ChestPeekPlugin.ShowTotal.Value);
			Container val2 = (Container)(object)((target is Container) ? target : null);
			List<Entry> list = ((val2 != null) ? Contents(val2.GetInventory()) : Contents(StandContents.Items((ArmorStand)target)));
			if (list.Count == 0)
			{
				return false;
			}
			((TMP_Text)total).text = string.Format(ChestPeekPlugin.TotalText.Value, list.Sum((Entry entry) => entry.Count));
			bool flag = list.Count > num;
			int num2 = (flag ? (num - 1) : list.Count);
			for (int num3 = 0; num3 < num; num3++)
			{
				Slot slot = SlotAt(num3);
				if (num3 < num2)
				{
					ShowItem(slot, list[num3]);
				}
				else if (num3 == num2 && flag)
				{
					ShowMore(slot, list.Count - num2);
				}
				else
				{
					slot.Root.SetActive(false);
				}
			}
			for (int num4 = num; num4 < slots.Count; num4++)
			{
				slots[num4].Root.SetActive(false);
			}
			return true;
		}

		private List<Entry> Contents(Inventory inventory)
		{
			totals.Clear();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && allItem.m_shared != null)
				{
					string name = allItem.m_shared.m_name;
					totals.TryGetValue(name, out var value);
					value.Icon = value.Icon ?? allItem.GetIcon();
					value.Count += allItem.m_stack;
					totals[name] = value;
				}
			}
			return totals.Values.OrderByDescending((Entry entry) => entry.Count).ToList();
		}

		private static List<Entry> Contents(List<ItemDrop> items)
		{
			return items.Select((ItemDrop drop) => new Entry
			{
				Icon = drop.m_itemData.GetIcon(),
				Count = 1
			}).ToList();
		}

		private Slot SlotAt(int index)
		{
			while (slots.Count <= index)
			{
				slots.Add(MakeSlot());
			}
			Slot slot = slots[index];
			slot.Root.SetActive(true);
			return slot;
		}

		private Slot MakeSlot()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Slot", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)grid, false);
			Slot slot = (((Object)(object)slotPrefab != (Object)null) ? VanillaSlot(val.transform) : null);
			if (slot == null)
			{
				slot = PlainSlot(val.transform);
			}
			slot.Root = val;
			RectTransform body = slot.Body;
			RectTransform body2 = slot.Body;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			body2.anchorMax = val2;
			body.anchorMin = val2;
			slot.Body.pivot = new Vector2(0.5f, 0.5f);
			slot.Body.anchoredPosition = Vector2.zero;
			slot.Body.sizeDelta = new Vector2(slotNativeSize, slotNativeSize);
			return slot;
		}

		private Slot VanillaSlot(Transform parent)
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(slotPrefab, parent, false);
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val2 in componentsInChildren)
			{
				if (!(val2 is Graphic) && !(val2 is UIBehaviour))
				{
					Object.Destroy((Object)(object)val2);
				}
			}
			Graphic[] componentsInChildren2 = val.GetComponentsInChildren<Graphic>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].raycastTarget = false;
			}
			Transform val3 = val.transform.Find("icon");
			Transform val4 = val.transform.Find("amount");
			Image val5 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<Image>() : null);
			TMP_Text val6 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			foreach (Transform item in val.transform)
			{
				Transform val7 = item;
				((Component)val7).gameObject.SetActive((Object)(object)val7 == (Object)(object)val3 || (Object)(object)val7 == (Object)(object)val4);
			}
			return new Slot
			{
				Body = (RectTransform)val.transform,
				Icon = val5,
				Count = val6
			};
		}

		private Slot PlainSlot(Transform parent)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_013e: Expected O, but got Unknown
			GameObject val = new GameObject("Body", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = FallbackSlot;
			((Graphic)component).raycastTarget = false;
			GameObject val2 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val3 = (RectTransform)val2.transform;
			((Transform)val3).SetParent(val.transform, false);
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			Vector2 offsetMin = (val3.offsetMax = Vector2.zero);
			val3.offsetMin = offsetMin;
			Image component2 = val2.GetComponent<Image>();
			component2.preserveAspect = true;
			((Graphic)component2).raycastTarget = false;
			TextMeshProUGUI val4 = MakeText("Count", val.transform, (TMP_Text)(object)Hud.instance.m_hoverName);
			((TMP_Text)val4).alignment = (TextAlignmentOptions)1028;
			RectTransform val5 = (RectTransform)((TMP_Text)val4).transform;
			val5.anchorMin = Vector2.zero;
			val5.anchorMax = Vector2.one;
			offsetMin = (val5.offsetMax = Vector2.zero);
			val5.offsetMin = offsetMin;
			return new Slot
			{
				Body = (RectTransform)val.transform,
				Icon = component2,
				Count = (TMP_Text)(object)val4
			};
		}

		private static void ShowItem(Slot slot, Entry entry)
		{
			((Behaviour)slot.Icon).enabled = (Object)(object)entry.Icon != (Object)null;
			slot.Icon.sprite = entry.Icon;
			slot.Count.text = ((entry.Count > 1) ? entry.Count.ToString() : "");
		}

		private static void ShowMore(Slot slot, int hidden)
		{
			((Behaviour)slot.Icon).enabled = false;
			slot.Count.text = "+" + hidden;
		}
	}
}