Decompiled source of HearthLogistics v0.4.0

BepInEx/plugins/HearthLogistics/HearthLogistics.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HearthLogistics.Core;
using HearthLogistics.Runtime;
using HearthLogistics.UI;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valheim.SettingsGui;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HearthLogistics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0")]
[assembly: AssemblyProduct("HearthLogistics")]
[assembly: AssemblyTitle("HearthLogistics")]
[assembly: AssemblyVersion("0.4.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 HearthLogistics
{
	[BepInPlugin("local.hearthlogistics", "Hearth Logistics", "0.4.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal const string ModVersion = "0.4.0";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static readonly PersonalRuleStore Personal = new PersonalRuleStore();

		internal static readonly SharedContainerRuleStore Shared = new SharedContainerRuleStore();

		internal static readonly ContainerRuleCache RuleCache = new ContainerRuleCache();

		internal static readonly ContainerDiscovery Discovery = new ContainerDiscovery();

		internal static readonly SortingEngine Sorting = new SortingEngine();

		internal static readonly InventoryRestockEngine Restocking = new InventoryRestockEngine();

		internal static readonly StorageRebalanceEngine Rebalancing = new StorageRebalanceEngine();

		internal static readonly WorldObjectServiceEngine Servicing = new WorldObjectServiceEngine();

		internal static readonly FeedbackUI Feedback = new FeedbackUI();

		internal static bool Busy;

		internal static OperationResult CurrentResult;

		private Harmony harmony;

		private SettingsUI ui;

		private string profile = "menu";

		private bool usable;

		private bool serverOnly;

		public static Player Player => Player.m_localPlayer;

		public static LocalSettings Settings => Personal.Settings;

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			PortalServer.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				serverOnly = true;
				harmony = new Harmony("local.hearthlogistics");
				harmony.CreateClassProcessor(typeof(PortalContainerDestruction)).Patch();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Hearth Logistics optional portal server module loaded. Enable [Portal server] Enabled in the configuration to process unloaded endpoints.");
				return;
			}
			try
			{
				Personal.Load();
				Diagnostics.Start();
				ui = new SettingsUI();
				harmony = new Harmony("local.hearthlogistics");
				harmony.PatchAll(typeof(Plugin).Assembly);
				usable = true;
				SceneManager.activeSceneChanged += SceneChanged;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Hearth Logistics 0.4.0 loaded. Client-only; shared multiplayer layouts pending qualification.");
			}
			catch (Exception ex)
			{
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				((BaseUnityPlugin)this).Logger.LogError((object)("Logistics disabled: " + ex));
			}
		}

		private void Update()
		{
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PortalServer.Tick();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Portal server: " + ex));
			}
			if (serverOnly || !usable)
			{
				return;
			}
			string text = (Object.op_Implicit((Object)(object)Player) ? Player.GetPlayerID().ToString(CultureInfo.InvariantCulture) : "menu");
			if (text != profile)
			{
				try
				{
					Personal.Save();
					Personal.Load(text);
					profile = text;
					ui.Close();
					Diagnostics.ModeChanged();
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)ex2);
					usable = false;
					return;
				}
			}
			RuleCache.Observed = ChestColourSwatches.Observe;
			if (!Busy)
			{
				RuleCache.Tick();
			}
			ChestColourSwatches.Tick();
			try
			{
				PortalContainers.Tick();
			}
			catch (Exception error)
			{
				Diagnostics.Error("PortalContainers", error);
			}
			try
			{
				ContainerWorldUI.Tick();
			}
			catch (Exception error2)
			{
				ContainerWorldUI.Clear();
				Diagnostics.Error("ContainerWorldUI", error2);
			}
			try
			{
				CraftingResources.Tick();
			}
			catch (Exception error3)
			{
				Diagnostics.Error("CraftingResources", error3);
			}
			ui.Update();
			if (HearthLogisticsTextInput.SuppressGameplay || Object.op_Implicit((Object)(object)Settings.instance))
			{
				return;
			}
			if (Input.GetKeyDown(Key(Settings.settingsKey)))
			{
				if (Object.op_Implicit((Object)(object)Player) && !Menu.IsVisible() && !InventoryGui.IsVisible())
				{
					Menu.instance.Show();
				}
				ui.Toggle();
			}
			if (Object.op_Implicit((Object)(object)Player) && !((Character)Player).IsDead() && !ui.Visible && !Busy && CraftFromStorage.Active == null && !InventoryGui.IsVisible() && !Menu.IsVisible() && (!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !BuildDownloadShortcut.Handle())
			{
				if (Input.GetKeyDown(Key(Settings.depositKey)))
				{
					Run("Deposit");
				}
				else if (Input.GetKeyDown(Key(Settings.restockKey)))
				{
					Run("Restock");
				}
				else if (Input.GetKeyDown(Key(Settings.rebalanceKey)))
				{
					Run("Rebalance");
				}
				else if (Input.GetKeyDown(Key(Settings.serviceKey)))
				{
					Run("Service Base");
				}
				else if (Input.GetKeyDown(Key(Settings.serviceObjectsKey)))
				{
					Run("Service objects");
				}
				else if (Input.GetKeyDown(Key(Settings.collectKey)))
				{
					Run("Collect outputs");
				}
				else if (Input.GetKeyDown(Key(Settings.loadoutKey)))
				{
					Run("Apply loadout");
				}
			}
		}

		private static KeyCode Key(string key)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<KeyCode>(key, out KeyCode result))
			{
				return (KeyCode)0;
			}
			return result;
		}

		internal static void Run(string action)
		{
			if (Object.op_Implicit((Object)(object)Player) && !((Character)Player).IsDead() && !Busy && CraftFromStorage.Active == null)
			{
				((MonoBehaviour)Instance).StartCoroutine(RunBatched(action));
			}
		}

		private static IEnumerator RunBatched(string action)
		{
			Busy = true;
			CurrentResult = new OperationResult();
			Player player = Player;
			ActionInventories working = new ActionInventories();
			DepositTrace perf = new DepositTrace(action);
			List<Container> boxes = new List<Container>();
			Diagnostics.Info("Action started: " + action);
			Diagnostics.Detail("Active Inventory Profile: " + Settings.ActiveProfile.name + " id=" + Settings.ActiveProfile.id);
			try
			{
				if (action == "Rebalance")
				{
					int dirty = RuleCache.PendingContents;
					for (int i = 0; i < dirty; i++)
					{
						RuleCache.RefreshOneContents();
						if (i % 2 == 1)
						{
							yield return null;
						}
					}
					if ((Object)(object)Player != (Object)(object)player || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead())
					{
						yield break;
					}
					IEnumerable<ContainerRuleCache.Entry> entries = RuleCache.Entries;
					int batch = 0;
					ContainerRuleCache.Entry[] array = entries.ToArray();
					foreach (ContainerRuleCache.Entry e in array)
					{
						if ((Object)(object)Player != (Object)(object)player || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead())
						{
							yield break;
						}
						if (RuleCache.InRange(e))
						{
							perf.Inspected++;
							Container val = RuleCache.Resolve(e);
							if (Object.op_Implicit((Object)(object)val) && Access.Container(val, player, Settings.storageRange))
							{
								try
								{
									if (RuleCache.Get(val).Rules != null)
									{
										working.Load(val);
										boxes.Add(val);
									}
								}
								catch (Exception error)
								{
									Diagnostics.Error("ActionPreparation", error);
								}
							}
						}
						int num = batch + 1;
						batch = num;
						if (num == 2)
						{
							batch = 0;
							yield return null;
						}
					}
					boxes = boxes.OrderBy<Container, string>((Container c) => ((object)Unsafe.As<ZDOID, ZDOID>(ref Access.View(c).GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal).ToList();
				}
				if ((Object)(object)Player != (Object)(object)player || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead())
				{
					yield break;
				}
				IEnumerator preparation = null;
				if (action == "Service Base" || action == "Service objects")
				{
					preparation = Servicing.PrepareSources(boxes);
				}
				if (preparation != null)
				{
					try
					{
						while (preparation.MoveNext())
						{
							yield return preparation.Current;
						}
					}
					finally
					{
						(preparation as IDisposable)?.Dispose();
					}
				}
				if ((Object)(object)Player != (Object)(object)player || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead())
				{
					yield break;
				}
				if (action == "Service Base")
				{
					try
					{
						Servicing.Run(boxes, CurrentResult);
					}
					catch (Exception ex)
					{
						Diagnostics.Error("Action:" + action, ex);
						Feedback.Show("Action stopped: " + ex.GetBaseException().Message);
						yield break;
					}
				}
				if (action == "Service objects")
				{
					try
					{
						Servicing.Run(boxes, CurrentResult);
					}
					catch (Exception ex2)
					{
						Diagnostics.Error("Action:" + action, ex2);
						Feedback.Show("Action stopped: " + ex2.GetBaseException().Message);
						yield break;
					}
				}
				if (action == "Collect outputs" || (Settings.collectOutputs && (action == "Service Base" || action == "Service objects")))
				{
					{
						IEnumerator fermenters = Servicing.CollectFermenters(boxes, CurrentResult);
						try
						{
							while (true)
							{
								bool flag;
								try
								{
									flag = fermenters.MoveNext();
								}
								catch (Exception ex3)
								{
									Diagnostics.Error("FermenterCollection", ex3);
									Feedback.Show("Collection stopped: " + ex3.GetBaseException().Message);
									yield break;
								}
								if (!flag)
								{
									break;
								}
								yield return fermenters.Current;
							}
						}
						finally
						{
							IDisposable disposable = fermenters as IDisposable;
							if (disposable != null)
							{
								disposable.Dispose();
							}
						}
					}
				}
				if ((Object)(object)Player != (Object)(object)player || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead())
				{
					yield break;
				}
				if (action == "Service Base" && Settings.serviceDeposits)
				{
					{
						IEnumerator fermenters = CachedDeposit.RunBatched(CurrentResult, perf);
						try
						{
							while (true)
							{
								bool flag2;
								try
								{
									flag2 = fermenters.MoveNext();
								}
								catch (Exception ex4)
								{
									Diagnostics.Error("Action:" + action, ex4);
									Feedback.Show("Action stopped: " + ex4.GetBaseException().Message);
									yield break;
								}
								if (!flag2)
								{
									break;
								}
								yield return fermenters.Current;
							}
						}
						finally
						{
							IDisposable disposable2 = fermenters as IDisposable;
							if (disposable2 != null)
							{
								disposable2.Dispose();
							}
						}
					}
				}
				switch (action)
				{
				case "Service Base":
					if (!Settings.serviceRestocks)
					{
						break;
					}
					goto case "Restock";
				case "Restock":
				case "Apply loadout":
					{
						IEnumerator fermenters = Restocking.RestockBatched(CurrentResult, perf);
						try
						{
							while (true)
							{
								bool flag3;
								try
								{
									flag3 = fermenters.MoveNext();
								}
								catch (Exception ex5)
								{
									Diagnostics.Error("Action:" + action, ex5);
									Feedback.Show("Action stopped: " + ex5.GetBaseException().Message);
									yield break;
								}
								if (!flag3)
								{
									break;
								}
								yield return fermenters.Current;
							}
						}
						finally
						{
							IDisposable disposable3 = fermenters as IDisposable;
							if (disposable3 != null)
							{
								disposable3.Dispose();
							}
						}
					}
					break;
				}
				if ((Object)(object)Player != (Object)(object)player || !Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead())
				{
					yield break;
				}
				if (action == "Collect outputs" || (Settings.collectOutputs && (action == "Service Base" || action == "Service objects")))
				{
					{
						IEnumerator fermenters = MultiplayerPreparation.Destinations(Servicing.OutputDemand(), boxes);
						try
						{
							while (fermenters.MoveNext())
							{
								yield return fermenters.Current;
							}
						}
						finally
						{
							IDisposable disposable4 = fermenters as IDisposable;
							if (disposable4 != null)
							{
								disposable4.Dispose();
							}
						}
					}
					Servicing.Collect(boxes, CurrentResult);
				}
				if (action == "Deposit")
				{
					try
					{
						if (Settings.serviceDuringDeposit)
						{
							Servicing.Run(boxes, CurrentResult, carriedOnly: true);
						}
					}
					catch (Exception ex6)
					{
						Diagnostics.Error("DepositService", ex6);
						Feedback.Show(ex6.Message);
						yield break;
					}
					{
						IEnumerator fermenters = CachedDeposit.RunBatched(CurrentResult, perf);
						try
						{
							while (true)
							{
								bool flag4;
								try
								{
									flag4 = fermenters.MoveNext();
								}
								catch (Exception ex7)
								{
									Diagnostics.Error("Deposit", ex7);
									Feedback.Show("Deposit stopped: " + ex7.GetBaseException().Message);
									yield break;
								}
								if (!flag4)
								{
									break;
								}
								yield return fermenters.Current;
							}
						}
						finally
						{
							IDisposable disposable5 = fermenters as IDisposable;
							if (disposable5 != null)
							{
								disposable5.Dispose();
							}
						}
					}
				}
				try
				{
					switch (action)
					{
					case "Deposit":
						PlayerStackConsolidation.Run();
						break;
					case "Rebalance":
						Rebalancing.Run(boxes, CurrentResult);
						break;
					case "Collect outputs":
						Servicing.Collect(boxes, CurrentResult);
						break;
					}
					Feedback.Show(CurrentResult.ToString());
					Diagnostics.Info("Action complete: " + action + "; " + CurrentResult);
				}
				catch (Exception ex8)
				{
					Diagnostics.Error("Action:" + action, ex8);
					Feedback.Show("Action stopped: " + ex8.GetBaseException().Message);
				}
			}
			finally
			{
				try
				{
					perf.Finish();
				}
				finally
				{
					working.Dispose();
					CurrentResult = null;
					Busy = false;
				}
			}
		}

		private void LateUpdate()
		{
			if (usable)
			{
				ContainerUI.Instance.Tick();
				InventoryProfileUI.Instance.Tick();
				DownloadUI.Tick();
				ContainerWorldUI.FaceCamera();
			}
		}

		private void OnDisable()
		{
			PortalServer.Clear();
			if (!serverOnly)
			{
				ContainerWorldUI.Clear();
			}
		}

		private void SceneChanged(Scene previous, Scene next)
		{
			ContainerWorldUI.Clear();
		}

		private void OnDestroy()
		{
			PortalServer.Clear();
			if (serverOnly)
			{
				Harmony obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				return;
			}
			ui?.ReleaseVisuals();
			SceneManager.activeSceneChanged -= SceneChanged;
			ContainerWorldUI.Clear();
			((MonoBehaviour)this).StopAllCoroutines();
			ActionInventories.Current?.Dispose();
			ContainerAccess.Clear();
			MachinePredictions.Clear();
			RuleCache.Clear();
			Harmony obj2 = harmony;
			if (obj2 != null)
			{
				obj2.UnpatchSelf();
			}
			ContainerUI.Instance.Dispose();
			InventoryProfileUI.Instance.Dispose();
			DownloadUI.Close();
			if (!usable)
			{
				return;
			}
			try
			{
				Personal.Save();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}
	}
}
namespace HearthLogistics.UI
{
	[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
	internal static class BlockFilterDrag
	{
		private static bool Prefix(InventoryGrid __instance, ref bool __result)
		{
			if (!ContainerUI.Instance.Accepts(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	internal static class BuildDownloadShortcut
	{
		internal static bool Handle()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Hud.instance) || !Hud.IsPieceSelectionVisible() || !((Character)Plugin.Player).InPlaceMode() || !Enum.TryParse<KeyCode>(Plugin.Settings.buildDownloadKey, out KeyCode result) || (int)result == 0 || !Input.GetKeyDown(result))
			{
				return false;
			}
			GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				TMP_InputField componentInParent = val.GetComponentInParent<TMP_InputField>();
				InputField componentInParent2 = val.GetComponentInParent<InputField>();
				if ((Object.op_Implicit((Object)(object)componentInParent) && componentInParent.isFocused) || (Object.op_Implicit((Object)(object)componentInParent2) && componentInParent2.isFocused))
				{
					return true;
				}
			}
			try
			{
				Piece piece = Access.Field<Piece>(Hud.instance, "m_hoveredPiece");
				((MonoBehaviour)Plugin.Instance).StartCoroutine(NetworkActions.BuildMaterials(piece));
			}
			catch (Exception ex)
			{
				Diagnostics.Error("BuildDownloadShortcut", ex);
				Plugin.Feedback.Show("Could not download building materials: " + ex.GetBaseException().Message);
			}
			return true;
		}
	}
	internal sealed class ChestColourPicker : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IDragHandler
	{
		private Texture2D texture;

		private float hue;

		private float saturation;

		private float brightness = 1f;

		private float alpha = 1f;

		private Image preview;

		private TMP_Text value;

		private TMP_InputField hexInput;

		private string Hex => "#" + ColorUtility.ToHtmlStringRGBA(Colour);

		private Color Colour
		{
			get
			{
				//IL_0012: 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_0025: Unknown result type (might be due to invalid IL or missing references)
				Color result = Color.HSVToRGB(hue, saturation, brightness);
				result.a = alpha;
				return result;
			}
		}

		internal static void Build(Transform parent, RectTransform owner, string colour, bool editable, Action<string> apply)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0493: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			RectTransform panel = NativeUi.Rect("Chest colour picker", (Transform)(object)owner);
			((Component)panel).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
			RectTransform obj = panel;
			RectTransform obj2 = panel;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(1f, 1f);
			obj2.anchorMax = val;
			obj.anchorMin = val;
			panel.pivot = new Vector2(0f, 1f);
			panel.sizeDelta = new Vector2(320f, 460f);
			NativeUi.PanelBackground(panel, (Transform)(object)InventoryGui.instance.m_container);
			NativeUi.Vertical(panel, 10);
			((Component)panel).gameObject.AddComponent<AdjacentPanel>();
			((Component)panel).gameObject.SetActive(false);
			((Selectable)NativeUi.Button(parent, "Colour: " + colour, delegate
			{
				((Component)panel).gameObject.SetActive(!((Component)panel).gameObject.activeSelf);
				((Transform)panel).SetAsLastSibling();
			}, 180f)).interactable = editable;
			NativeUi.Label((Transform)(object)panel, "BACKGROUND COLOUR");
			RectTransform parent2 = NativeUi.Row((Transform)(object)panel);
			ChestColourPicker picker = null;
			NativeUi.Button((Transform)(object)parent2, "Save colour", delegate
			{
				apply(picker.Hex);
				((Component)panel).gameObject.SetActive(false);
				try
				{
					Plugin.Personal.Commit(delegate(LocalSettings s)
					{
						s.colourSwatches = ChestColours.Merge(s.colourSwatches, new string[1] { picker.Hex });
					});
				}
				catch (Exception error)
				{
					Diagnostics.Error("ColourSwatchSave", error);
					Plugin.Feedback.Show("Chest colour saved; personal swatch could not be saved.");
				}
			});
			NativeUi.Button((Transform)(object)parent2, "Cancel", delegate
			{
				((Component)panel).gameObject.SetActive(false);
			}, 80f);
			RectTransform parent3 = NativeUi.Row((Transform)(object)panel, 140f);
			RectTransform val2 = NativeUi.Rect("Colour wheel", (Transform)(object)parent3);
			NativeUi.Size(val2, 140f, 140f);
			picker = ((Component)val2).gameObject.AddComponent<ChestColourPicker>();
			picker.texture = new Texture2D(128, 128, (TextureFormat)4, false);
			for (int num = 0; num < 128; num++)
			{
				for (int num2 = 0; num2 < 128; num2++)
				{
					float num3 = ((float)num2 - 63.5f) / 63.5f;
					float num4 = ((float)num - 63.5f) / 63.5f;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4);
					picker.texture.SetPixel(num2, num, (num5 > 1f) ? Color.clear : Color.HSVToRGB(Mathf.Repeat(Mathf.Atan2(num4, num3) / ((float)Math.PI * 2f), 1f), num5, 1f));
				}
			}
			picker.texture.Apply();
			((Component)val2).gameObject.AddComponent<RawImage>().texture = (Texture)(object)picker.texture;
			RectTransform val3 = NativeUi.Rect("Preview", (Transform)(object)parent3);
			NativeUi.Size(val3, 80f, 100f);
			picker.preview = ((Component)val3).gameObject.AddComponent<Image>();
			picker.value = NativeUi.Label((Transform)(object)panel, colour);
			Color val4 = default(Color);
			ColorUtility.TryParseHtmlString(colour, ref val4);
			Color.RGBToHSV(val4, ref picker.hue, ref picker.saturation, ref picker.brightness);
			picker.alpha = val4.a;
			Slider bright = Slider((Transform)(object)panel, "Brightness", picker.brightness, delegate(float v)
			{
				picker.brightness = v;
				picker.Refresh();
			});
			Slider opacity = Slider((Transform)(object)panel, "Opacity", picker.alpha, delegate(float v)
			{
				picker.alpha = v;
				picker.Refresh();
			});
			picker.hexInput = NativeUi.Input((Transform)(object)panel, "", "#RRGGBBAA", delegate(string v)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				Color val5 = default(Color);
				ColorUtility.TryParseHtmlString(ChestColours.Normalize(v), ref val5);
				Color.RGBToHSV(val5, ref picker.hue, ref picker.saturation, ref picker.brightness);
				picker.alpha = val5.a;
				bright.SetValueWithoutNotify(picker.brightness);
				opacity.SetValueWithoutNotify(picker.alpha);
				picker.Refresh();
			}, 150f);
			NativeUi.Label((Transform)(object)panel, "Saved swatches — select, then Save");
			RectTransform parent4 = NativeUi.Scroll((Transform)(object)panel, 60f, 180f);
			RectTransform parent5 = null;
			int num6 = 0;
			Color color = default(Color);
			foreach (string swatch in ChestColours.Merge(Plugin.Settings.colourSwatches, null))
			{
				if (num6++ % 3 == 0)
				{
					parent5 = NativeUi.Row((Transform)(object)parent4);
				}
				Button obj3 = NativeUi.Button((Transform)(object)parent5, swatch, delegate
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_004f: Unknown result type (might be due to invalid IL or missing references)
					Color val5 = default(Color);
					ColorUtility.TryParseHtmlString(swatch, ref val5);
					Color.RGBToHSV(val5, ref picker.hue, ref picker.saturation, ref picker.brightness);
					picker.alpha = val5.a;
					bright.SetValueWithoutNotify(picker.brightness);
					opacity.SetValueWithoutNotify(picker.alpha);
					picker.Refresh();
				});
				ColorUtility.TryParseHtmlString(swatch, ref color);
				color.a = 1f;
				((Selectable)obj3).targetGraphic.color = color;
				((Graphic)((Component)obj3).GetComponentInChildren<TMP_Text>()).color = ((((Color)(ref color)).grayscale > 0.5f) ? Color.black : Color.white);
			}
			picker.Refresh();
		}

		private static Slider Slider(Transform parent, string name, float initial, Action<float> update)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			RectTransform parent2 = NativeUi.Row(parent);
			NativeUi.Label((Transform)(object)parent2, name, 90f);
			RectTransform val = NativeUi.Rect(name, (Transform)(object)parent2);
			NativeUi.Size(val, 0f, 24f);
			NativeUi.ControlBackground(((Component)val).gameObject.AddComponent<Image>(), "SliderTrack");
			RectTransform val2 = NativeUi.Rect("Handle", (Transform)(object)val);
			val2.sizeDelta = new Vector2(14f, 24f);
			Image val3 = ((Component)val2).gameObject.AddComponent<Image>();
			NativeUi.ControlBackground(val3, "SliderHandle");
			Slider obj = ((Component)val).gameObject.AddComponent<Slider>();
			obj.handleRect = val2;
			((Selectable)obj).targetGraphic = (Graphic)(object)val3;
			obj.value = initial;
			((UnityEvent<float>)(object)obj.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
			{
				update(v);
			});
			return obj;
		}

		private void Refresh()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)preview).color = Colour;
			value.text = Hex;
			if (Object.op_Implicit((Object)(object)hexInput))
			{
				hexInput.SetTextWithoutNotify(Hex);
			}
		}

		public void OnPointerDown(PointerEventData e)
		{
			Select(e);
		}

		public void OnDrag(PointerEventData e)
		{
			Select(e);
		}

		private void Select(PointerEventData e)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000e: 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_0025: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//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_0041: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)this).transform;
			Vector2 val2 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, e.position, e.pressEventCamera, ref val2))
			{
				Vector2 val3 = val2;
				Rect rect = val.rect;
				val2 = val3 - ((Rect)(ref rect)).center;
				float x = val2.x;
				rect = val.rect;
				float num = x / (((Rect)(ref rect)).width * 0.5f);
				float y = val2.y;
				rect = val.rect;
				((Vector2)(ref val2))..ctor(num, y / (((Rect)(ref rect)).height * 0.5f));
				hue = Mathf.Repeat(Mathf.Atan2(val2.y, val2.x) / ((float)Math.PI * 2f), 1f);
				saturation = Mathf.Clamp01(((Vector2)(ref val2)).magnitude);
				Refresh();
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)texture))
			{
				Object.Destroy((Object)(object)texture);
			}
		}
	}
	internal sealed class AdjacentPanel : MonoBehaviour
	{
		private void LateUpdate()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e9: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)this).transform;
			RectTransform val2 = (RectTransform)((Transform)val).parent;
			((Transform)val).localScale = Vector3.one;
			float num = Screen.height - 16;
			Rect rect = val.rect;
			float num2 = Mathf.Min(1f, num / Mathf.Max(1f, ((Rect)(ref rect)).height * Mathf.Abs(((Transform)val).lossyScale.y)));
			((Transform)val).localScale = Vector3.one * num2;
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			Camera val3 = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			val2.GetWorldCorners(array);
			Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val3, array[1]);
			Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val3, array[2]);
			rect = val.rect;
			float num3 = ((Rect)(ref rect)).width * Mathf.Abs(((Transform)val).lossyScale.x);
			rect = val.rect;
			float num4 = ((Rect)(ref rect)).height * Mathf.Abs(((Transform)val).lossyScale.y);
			float num5 = val5.x + 8f;
			if (num5 + num3 > (float)(Screen.width - 8))
			{
				num5 = val4.x - num3 - 8f;
			}
			num5 = Mathf.Clamp(num5, 8f, Mathf.Max(8f, (float)Screen.width - num3 - 8f));
			float num6 = Mathf.Clamp(val5.y, Mathf.Min(num4 + 8f, (float)(Screen.height - 8)), (float)(Screen.height - 8));
			Vector3 position = default(Vector3);
			if (RectTransformUtility.ScreenPointToWorldPointInRectangle(val2, new Vector2(num5, num6), val3, ref position))
			{
				((Transform)val).position = position;
			}
		}
	}
	internal static class ChestContentsIcons
	{
		private sealed class Display
		{
			internal GameObject Root;

			internal long Contents = -1L;

			internal uint Revision;

			internal string Colour;

			internal bool Single;

			internal bool FrontBack;

			internal bool Background;

			internal bool Initialized;

			internal float Checked;

			internal string Signature;

			internal LocalSettings Settings;
		}

		internal sealed class Geometry
		{
			internal Container Template;

			internal MeshRenderer[] Renderers;

			internal Bounds Body;

			internal string Source;
		}

		private static readonly Dictionary<Container, Display> displays = new Dictionary<Container, Display>();

		private static readonly Dictionary<int, Geometry> prefabGeometry = new Dictionary<int, Geometry>();

		private static readonly HashSet<int> missingGeometry = new HashSet<int>();

		private static readonly Queue<(Container chest, Display state)> pending = new Queue<(Container, Display)>();

		private static float nextScan;

		private static float nextWork;

		private static Sprite backgroundSprite;

		internal static void Clear()
		{
			foreach (Display value in displays.Values)
			{
				Destroy(value);
			}
			displays.Clear();
			pending.Clear();
			prefabGeometry.Clear();
			missingGeometry.Clear();
			nextScan = (nextWork = 0f);
			if (Object.op_Implicit((Object)(object)backgroundSprite))
			{
				Object.Destroy((Object)(object)backgroundSprite);
			}
			backgroundSprite = null;
		}

		private static void Destroy(Display d)
		{
			if (Object.op_Implicit((Object)(object)d.Root))
			{
				d.Root.SetActive(false);
				Object.Destroy((Object)(object)d.Root);
			}
			d.Root = null;
		}

		internal static void Tick()
		{
			if (!Object.op_Implicit((Object)(object)Plugin.Instance) || !((Behaviour)Plugin.Instance).isActiveAndEnabled || !Object.op_Implicit((Object)(object)Plugin.Player) || ((Character)Plugin.Player).IsDead() || !Plugin.Settings.showContainerContentsOnHover)
			{
				if (displays.Count > 0)
				{
					Clear();
				}
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup >= nextScan)
			{
				nextScan = realtimeSinceStartup + 0.5f;
				HashSet<Container> nearby = new HashSet<Container>();
				ContainerRuleCache.Entry[] array = Plugin.RuleCache.Entries.ToArray();
				foreach (ContainerRuleCache.Entry e in array)
				{
					Container val = Plugin.RuleCache.Resolve(e);
					if (ContainerWorldUI.Accessible(val))
					{
						nearby.Add(val);
						if (!displays.ContainsKey(val))
						{
							Display display = new Display();
							displays[val] = display;
							pending.Enqueue((val, display));
						}
					}
				}
				Container[] array2 = displays.Keys.Where((Container c) => !Object.op_Implicit((Object)(object)c) || !nearby.Contains(c)).ToArray();
				foreach (Container key in array2)
				{
					Destroy(displays[key]);
					displays.Remove(key);
				}
			}
			if (realtimeSinceStartup < nextWork)
			{
				return;
			}
			nextWork = realtimeSinceStartup + 0.05f;
			int num = Math.Min(4, pending.Count);
			while (num-- > 0)
			{
				(Container, Display) tuple = pending.Dequeue();
				var (val2, _) = tuple;
				if (!Object.op_Implicit((Object)(object)val2) || !displays.TryGetValue(val2, out var value) || value != tuple.Item2)
				{
					continue;
				}
				pending.Enqueue(tuple);
				if (realtimeSinceStartup - value.Checked < 0.5f && value.Initialized)
				{
					continue;
				}
				value.Checked = realtimeSinceStartup;
				if (!ContainerWorldUI.Accessible(val2))
				{
					Destroy(value);
					displays.Remove(val2);
					continue;
				}
				try
				{
					if (Update(val2, value))
					{
						break;
					}
				}
				catch (Exception error)
				{
					Destroy(value);
					value.Initialized = false;
					Diagnostics.Error("ChestContentsIcons", error);
					break;
				}
			}
		}

		private static bool Update(Container c, Display d)
		{
			//IL_00ea: 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)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_00fe: Expected O, but got Unknown
			ContainerRuleCache.Entry entry = Plugin.RuleCache.Get(c);
			ZNetView val = Access.View(c);
			ZDO zDO = val.GetZDO();
			ContainerRules rules = entry.Rules;
			if (d.Settings != Plugin.Settings)
			{
				d.Initialized = false;
			}
			if (d.Initialized && d.Settings == Plugin.Settings && d.Contents == entry.ContentsVersion && d.Revision == zDO.DataRevision && d.Single == rules.displaySingle && d.FrontBack == rules.displayFrontBack && d.Background == rules.displayBackground && d.Colour == rules.displayColour)
			{
				return false;
			}
			Inventory val2 = c.GetInventory();
			if (!val.IsOwner())
			{
				byte[] byteArray = zDO.GetByteArray(ZDOVars.s_items, (byte[])null);
				if (byteArray == null)
				{
					Destroy(d);
					d.Initialized = false;
					return true;
				}
				Inventory val3 = new Inventory("Chest icon preview", (Sprite)null, val2.GetWidth(), val2.GetHeight());
				val3.Load(new ZPackage(byteArray));
				val2 = val3;
			}
			ItemData[] array = ChestDisplayLayout.FirstUnique(from i in val2.GetAllItems()
				orderby i.m_gridPos.y, i.m_gridPos.x
				select i, (ItemData i) => (!string.IsNullOrEmpty(Access.Id(i))) ? Access.Id(i) : i.m_shared.m_name, ChestDisplayLayout.Capacity(rules.displaySingle, rules.displayFrontBack));
			Sprite[] array2 = array.Select((ItemData i) => i.GetIcon()).ToArray();
			string text = rules.displaySingle + "/" + rules.displayFrontBack + "/" + rules.displayBackground + "/" + rules.displayColour + "/" + string.Join(",", array2.Select((Sprite s) => (!Object.op_Implicit((Object)(object)s)) ? "none" : ((Object)s).GetInstanceID().ToString()));
			if (text != d.Signature || !d.Initialized)
			{
				Destroy(d);
				if (array.Length != 0 && !Create(c, d, array2, rules.displaySingle, rules.displayFrontBack, rules.displayBackground, rules.displayColour))
				{
					d.Initialized = false;
					return true;
				}
				d.Signature = text;
			}
			d.Contents = entry.ContentsVersion;
			d.Revision = zDO.DataRevision;
			d.Colour = rules.displayColour;
			d.Settings = Plugin.Settings;
			d.Single = rules.displaySingle;
			d.FrontBack = rules.displayFrontBack;
			d.Background = rules.displayBackground;
			d.Initialized = true;
			return true;
		}

		private static bool RestRenderer(Container template, MeshRenderer renderer, bool excludeClosed)
		{
			if (!((Renderer)renderer).enabled)
			{
				return false;
			}
			Transform val = ((Component)renderer).transform;
			if (Object.op_Implicit((Object)(object)template.m_open) && val.IsChildOf(template.m_open.transform))
			{
				return false;
			}
			if (excludeClosed && Object.op_Implicit((Object)(object)template.m_closed) && val.IsChildOf(template.m_closed.transform))
			{
				return false;
			}
			while (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)((Component)template).transform)
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					return false;
				}
				val = val.parent;
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return Object.op_Implicit((Object)(object)component.sharedMesh);
			}
			return false;
		}

		internal static Geometry ClosedGeometry(GameObject prefab)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: 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_0125: 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)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			int instanceID = ((Object)prefab).GetInstanceID();
			if (prefabGeometry.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			Container template = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponentInChildren<Container>(true) : null);
			if (!Object.op_Implicit((Object)(object)template))
			{
				if (missingGeometry.Add(instanceID))
				{
					Diagnostics.Detail("ICON ANCHOR prefab=" + instanceID + " geometrySource=Unavailable action=WaitForPrefab");
				}
				return null;
			}
			MeshRenderer[] componentsInChildren = ((Component)template).GetComponentsInChildren<MeshRenderer>(true);
			MeshRenderer[] array = componentsInChildren.Where((MeshRenderer r) => RestRenderer(template, r, excludeClosed: true)).ToArray();
			string source = "ClosedBody";
			if (array.Length == 0)
			{
				array = componentsInChildren.Where((MeshRenderer r) => RestRenderer(template, r, excludeClosed: false)).ToArray();
				source = "ClosedRestPose";
			}
			bool flag = false;
			Bounds body = default(Bounds);
			MeshRenderer[] array2 = array;
			foreach (MeshRenderer val in array2)
			{
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if (!((Renderer)val).enabled || !Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh))
				{
					continue;
				}
				Bounds bounds = component.sharedMesh.bounds;
				for (int num2 = 0; num2 < 8; num2++)
				{
					Vector3 val2 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((num2 & 1) != 0) ? 1 : (-1)), (float)(((num2 & 2) != 0) ? 1 : (-1)), (float)(((num2 & 4) != 0) ? 1 : (-1))));
					Vector3 val3 = ((Component)template).transform.InverseTransformPoint(((Component)val).transform.TransformPoint(val2));
					if (!flag)
					{
						((Bounds)(ref body))..ctor(val3, Vector3.zero);
						flag = true;
					}
					else
					{
						((Bounds)(ref body)).Encapsulate(val3);
					}
				}
			}
			if (flag)
			{
				Vector3 size = ((Bounds)(ref body)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude <= 0.01f))
				{
					Dictionary<int, Geometry> dictionary = prefabGeometry;
					int key = instanceID;
					Geometry obj = new Geometry
					{
						Template = template,
						Renderers = array,
						Body = body,
						Source = source
					};
					Geometry result = obj;
					dictionary[key] = obj;
					return result;
				}
			}
			return null;
		}

		internal static void CalibrationChanged()
		{
			foreach (Display value in displays.Values)
			{
				value.Initialized = false;
				value.Checked = 0f;
			}
		}

		internal static MeshRenderer[] PreviewRenderers(GameObject prefab)
		{
			Container template = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponentInChildren<Container>(true) : null);
			if (!Object.op_Implicit((Object)(object)template))
			{
				return Array.Empty<MeshRenderer>();
			}
			return (from r in ((Component)template).GetComponentsInChildren<MeshRenderer>(true)
				where RestRenderer(template, r, excludeClosed: false)
				select r).ToArray();
		}

		internal static IconPlacementFrame Frame(GameObject prefab, IconCalibration calibration = null)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0058: 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_00c0: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			Geometry geometry = ClosedGeometry(prefab);
			if (geometry == null)
			{
				return null;
			}
			calibration = calibration ?? Plugin.Settings.iconCalibrations.FirstOrDefault((IconCalibration c) => c.prefab == ((Object)prefab).name && c.Valid());
			Vector3 val = ((Bounds)(ref geometry.Body)).center;
			Vector3 size = ((Bounds)(ref geometry.Body)).size;
			Quaternion rotation = Quaternion.identity;
			if (calibration != null && calibration.Valid())
			{
				val += new Vector3(calibration.originX, calibration.originY, calibration.originZ);
				((Vector3)(ref size))..ctor(calibration.sizeX, calibration.sizeY, calibration.sizeZ);
				rotation = Quaternion.Euler(calibration.rotationX, calibration.rotationY, calibration.rotationZ);
			}
			return new IconPlacementFrame
			{
				Center = val,
				Size = size,
				Rotation = rotation,
				SideNormalX = (((Bounds)(ref geometry.Body)).size.x >= ((Bounds)(ref geometry.Body)).size.z)
			};
		}

		private static bool Create(Container c, Display d, Sprite[] sprites, bool single, bool frontBack, bool background, string colour = "#0F0E0BD9")
		{
			sprites = sprites.Where((Sprite s) => Object.op_Implicit((Object)(object)s)).ToArray();
			if (sprites.Length == 0)
			{
				return true;
			}
			IconPlacementFrame iconPlacementFrame = Frame(Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(Access.View(c).GetZDO().GetPrefab()) : null);
			if (iconPlacementFrame == null)
			{
				return false;
			}
			d.Root = DrawIcons(((Component)c).transform, iconPlacementFrame, sprites, single, frontBack, background, colour);
			return true;
		}

		internal static GameObject DrawIcons(Transform parent, IconPlacementFrame frame, Sprite[] sprites, bool single, bool frontBack, bool background, string colour = "#0F0E0BD9")
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			//IL_006d: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_009f: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_0117: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: 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_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			sprites = sprites.Where((Sprite s) => Object.op_Implicit((Object)(object)s)).Take(ChestDisplayLayout.Capacity(single, frontBack)).ToArray();
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(frame.Center, frame.Size);
			bool flag = (frontBack ? (!frame.SideNormalX) : frame.SideNormalX);
			GameObject val2 = new GameObject("HearthLogistics chest contents");
			val2.transform.SetParent(parent, false);
			int[] array = new int[2] { -1, 1 };
			Color color = default(Color);
			foreach (int num2 in array)
			{
				Bounds val3 = val;
				float num3 = (flag ? ((Bounds)(ref val3)).size.z : ((Bounds)(ref val3)).size.x) * 0.82f;
				float num4 = ((Bounds)(ref val3)).size.y * 0.68f;
				float num5 = Math.Min(num3 / (float)ChestDisplayLayout.Columns(single, frontBack), num4 / (float)ChestDisplayLayout.Rows(single)) * 0.84f;
				Vector3 val4 = (flag ? Vector3.right : Vector3.forward) * (float)num2;
				Quaternion val5 = frame.Rotation * Quaternion.LookRotation(-val4, Vector3.up);
				Vector3 val6 = frame.Center + frame.Rotation * (val4 * ((flag ? ((Bounds)(ref val3)).extents.x : ((Bounds)(ref val3)).extents.z) + 0.015f));
				val4 = frame.Rotation * val4;
				if (background)
				{
					if (!Object.op_Implicit((Object)(object)backgroundSprite))
					{
						Texture2D whiteTexture = Texture2D.whiteTexture;
						backgroundSprite = Sprite.Create(whiteTexture, new Rect(0f, 0f, (float)((Texture)whiteTexture).width, (float)((Texture)whiteTexture).height), new Vector2(0.5f, 0.5f), (float)((Texture)whiteTexture).width);
					}
					int num6 = ChestDisplayLayout.Columns(single, frontBack);
					int num7 = ChestDisplayLayout.Rows(single);
					int num8 = Math.Min(num6, sprites.Length);
					int num9 = (sprites.Length + num6 - 1) / num6;
					GameObject val7 = new GameObject("Contents background");
					val7.transform.SetParent(val2.transform, false);
					val7.transform.localPosition = val6 - val4 * 0.003f;
					val7.transform.localRotation = val5;
					val7.transform.localScale = new Vector3((float)(num8 - 1) * num3 / (float)num6 + num5 * 1.12f, (float)(num9 - 1) * num4 / (float)num7 + num5 * 1.12f, 1f);
					SpriteRenderer obj = val7.AddComponent<SpriteRenderer>();
					obj.sprite = backgroundSprite;
					ColorUtility.TryParseHtmlString(colour, ref color);
					obj.color = color;
					((Renderer)obj).sortingOrder = -1;
					((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)obj).receiveShadows = false;
				}
				for (int num10 = 0; num10 < sprites.Length; num10++)
				{
					Sprite val8 = sprites[num10];
					if (Object.op_Implicit((Object)(object)val8))
					{
						(float, float) tuple = ChestDisplayLayout.Cell(num10, single, frontBack, sprites.Length);
						GameObject val9 = new GameObject("Item " + num10);
						val9.transform.SetParent(val2.transform, false);
						val9.transform.localRotation = val5;
						Bounds bounds = val8.bounds;
						float x = ((Bounds)(ref bounds)).size.x;
						bounds = val8.bounds;
						float num11 = num5 / Math.Max(x, ((Bounds)(ref bounds)).size.y);
						Transform transform = val9.transform;
						Vector3 val10 = new Vector3(tuple.Item1 * num3, tuple.Item2 * num4, 0f);
						bounds = val8.bounds;
						transform.localPosition = val6 + val5 * (val10 - ((Bounds)(ref bounds)).center * num11);
						val9.transform.localScale = Vector3.one * num11;
						SpriteRenderer obj2 = val9.AddComponent<SpriteRenderer>();
						obj2.sprite = val8;
						((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)0;
						((Renderer)obj2).receiveShadows = false;
					}
				}
			}
			return val2;
		}
	}
	internal sealed class ChestPanelWheel : MonoBehaviour, IScrollHandler, IEventSystemHandler
	{
		public void OnScroll(PointerEventData data)
		{
			//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)
			Vector2 scrollDelta = data.scrollDelta;
			if (((Vector2)(ref scrollDelta)).sqrMagnitude != 0f)
			{
				((Component)this).GetComponentInChildren<ScrollRect>().OnScroll(data);
				((AbstractEventData)data).Use();
			}
		}

		internal static bool UnderPointer()
		{
			//IL_001e: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)EventSystem.current))
			{
				return false;
			}
			List<RaycastResult> list = new List<RaycastResult>();
			EventSystem.current.RaycastAll(new PointerEventData(EventSystem.current)
			{
				position = Vector2.op_Implicit(ZInput.pointerPosition)
			}, list);
			if (list.Count > 0)
			{
				RaycastResult val = list[0];
				return Object.op_Implicit((Object)(object)((RaycastResult)(ref val)).gameObject.GetComponentInParent<ChestPanelWheel>());
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
	internal static class ChestWheelConsumption
	{
		private static void Postfix(ref float __result)
		{
			if (__result != 0f && ChestPanelWheel.UnderPointer())
			{
				__result = 0f;
			}
		}
	}
	internal sealed class ContainerIconCalibrationUI : IDisposable
	{
		private GameObject stage;

		private GameObject model;

		private GameObject overlays;

		private GameObject cameraObject;

		private Camera camera;

		private RenderTexture texture;

		private Material wireMaterial;

		private RawImage previewImage;

		private TMP_Text previewStatus;

		private readonly List<Material> materials = new List<Material>();

		private GameObject selected;

		private IconCalibration draft;

		private string selectedName;

		private bool autoRotate = true;

		private bool single;

		private bool frontBack;

		private bool background = true;

		private float yaw = 35f;

		private const int PreviewLayer = 31;

		private Action rebuild;

		private string nearbySignature = "";

		private float nextNearbyCheck;

		internal static GameObject[] NearbyPrefabs()
		{
			if (!Object.op_Implicit((Object)(object)Plugin.Player) || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return Array.Empty<GameObject>();
			}
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(StringComparer.Ordinal);
			Container[] array = ContainerDiscovery.Loaded.ToArray();
			foreach (Container val in array)
			{
				if (!ContainerWorldUI.Accessible(val))
				{
					continue;
				}
				Piece val2 = ((Component)val).GetComponent<Piece>() ?? ((Component)val).GetComponentInParent<Piece>();
				if (Object.op_Implicit((Object)(object)val2) && val2.GetCreator() != 0L)
				{
					GameObject prefab = ZNetScene.instance.GetPrefab(Access.View(val).GetZDO().GetPrefab());
					if (Object.op_Implicit((Object)(object)prefab) && Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<Container>(true)))
					{
						dictionary[((Object)prefab).name] = prefab;
					}
				}
			}
			return dictionary.Values.OrderBy<GameObject, string>((GameObject p) => ((Object)p).name, StringComparer.Ordinal).ToArray();
		}

		internal void Build(Transform parent, Action rebuildPage)
		{
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			rebuild = rebuildPage;
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				NativeUi.Label(parent, "Enter a world to calibrate container models.");
				return;
			}
			GameObject[] prefabs = NearbyPrefabs();
			nearbySignature = string.Join("|", prefabs.Select((GameObject p) => ((Object)p).name));
			nextNearbyCheck = Time.realtimeSinceStartup + 1f;
			if (prefabs.Length == 0)
			{
				NativeUi.Label(parent, $"No accessible player-built containers within {Plugin.Settings.storageRange:0.#} m.");
				return;
			}
			selected = ((IEnumerable<GameObject>)prefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => ((Object)p).name == selectedName)) ?? prefabs[0];
			selectedName = ((Object)selected).name;
			int index = Array.IndexOf(prefabs, selected);
			RectTransform parent2 = NativeUi.Row(parent);
			NativeUi.Button((Transform)(object)parent2, "Previous type", delegate
			{
				selectedName = ((Object)prefabs[(index + prefabs.Length - 1) % prefabs.Length]).name;
				rebuild();
			}, 110f);
			Piece component = selected.GetComponent<Piece>();
			NativeUi.Label((Transform)(object)parent2, (Object.op_Implicit((Object)(object)component) ? (Localization.instance.Localize(component.m_name) + " · ") : "") + selectedName);
			NativeUi.Button((Transform)(object)parent2, "Next type", delegate
			{
				selectedName = ((Object)prefabs[(index + 1) % prefabs.Length]).name;
				rebuild();
			}, 95f);
			ChestContentsIcons.Geometry geometry = ChestContentsIcons.ClosedGeometry(selected);
			if (geometry == null)
			{
				NativeUi.Label(parent, "This model has no usable closed/rest mesh geometry.");
				return;
			}
			draft = Plugin.Settings.iconCalibrations.FirstOrDefault((IconCalibration c) => c.prefab == selectedName && c.Valid())?.Copy() ?? new IconCalibration
			{
				prefab = selectedName,
				sizeX = ((Bounds)(ref geometry.Body)).size.x,
				sizeY = ((Bounds)(ref geometry.Body)).size.y,
				sizeZ = ((Bounds)(ref geometry.Body)).size.z
			};
			RectTransform val = NativeUi.Rect("Container preview", parent);
			NativeUi.Size(val, 0f, 190f);
			NativeUi.PanelBackground(val);
			RectTransform obj = NativeUi.Rect("Preview model", (Transform)(object)val);
			NativeUi.Stretch(obj, 4);
			RawImage val2 = ((Component)obj).gameObject.AddComponent<RawImage>();
			((Graphic)val2).raycastTarget = false;
			previewImage = val2;
			((Graphic)val2).color = Color.clear;
			previewStatus = NativeUi.Label((Transform)(object)val, "Preparing preview…");
			NativeUi.Stretch((RectTransform)previewStatus.transform, 12);
			previewStatus.alignment = (TextAlignmentOptions)514;
			previewStatus.overflowMode = (TextOverflowModes)0;
			try
			{
				CreatePreview(geometry, val2);
				if (Object.op_Implicit((Object)(object)camera))
				{
					((Graphic)val2).color = Color.white;
					((Component)previewStatus).gameObject.SetActive(false);
				}
			}
			catch (Exception error)
			{
				FailPreview(error);
			}
			RectTransform parent3 = NativeUi.Row(parent);
			NativeUi.Button((Transform)(object)parent3, "Auto Rotate: " + (autoRotate ? "On" : "Off"), delegate
			{
				autoRotate = !autoRotate;
				rebuild();
			});
			NativeUi.Button((Transform)(object)parent3, "Previous view", delegate
			{
				autoRotate = false;
				yaw -= 90f;
			});
			NativeUi.Button((Transform)(object)parent3, "Next view", delegate
			{
				autoRotate = false;
				yaw += 90f;
			});
			NativeUi.Button((Transform)(object)parent3, frontBack ? "Front / back" : "Sides", delegate
			{
				frontBack = !frontBack;
				rebuild();
			});
			NativeUi.Button((Transform)(object)parent3, single ? "1 icon" : "Grid", delegate
			{
				single = !single;
				rebuild();
			});
			NumberRow(parent, "Origin", new string[3] { "originX", "originY", "originZ" }, 0.02f, positive: false);
			NumberRow(parent, "Size", new string[3] { "sizeX", "sizeY", "sizeZ" }, 0.02f, positive: true);
			NumberRow(parent, "Rotation", new string[3] { "rotationX", "rotationY", "rotationZ" }, 1f, positive: false);
			RectTransform parent4 = NativeUi.Row(parent);
			NativeUi.Button((Transform)(object)parent4, "Reset This Container", delegate
			{
				Plugin.Settings.iconCalibrations.RemoveAll((IconCalibration c) => c.prefab == selectedName);
				ChestContentsIcons.CalibrationChanged();
				Plugin.Personal.Save();
				rebuild();
			});
			NativeUi.Button((Transform)(object)parent4, "Background: " + (background ? "On" : "Off"), delegate
			{
				background = !background;
				rebuild();
			});
			NativeUi.Label(parent, "Local only · origin offsets in metres · absolute size X/Y/Z · rotation in degrees");
		}

		private void NumberRow(Transform parent, string label, string[] fields, float step, bool positive)
		{
			RectTransform parent2 = NativeUi.Row(parent);
			NativeUi.Label((Transform)(object)parent2, label, 66f);
			for (int i = 0; i < 3; i++)
			{
				string text = fields[i];
				FieldInfo field = typeof(IconCalibration).GetField(text);
				NativeUi.Label((Transform)(object)parent2, "XYZ"[i].ToString(), 14f);
				TMP_InputField input = null;
				NativeUi.Button((Transform)(object)parent2, "−", delegate
				{
					float num = (float)field.GetValue(draft) - step;
					Apply(positive ? Math.Max(0.01f, num) : num);
					input.SetTextWithoutNotify(((float)field.GetValue(draft)).ToString("0.###", CultureInfo.InvariantCulture));
				}, 24f);
				input = NativeUi.Input((Transform)(object)parent2, ((float)field.GetValue(draft)).ToString("0.###", CultureInfo.InvariantCulture), text, delegate(string s)
				{
					if (float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						Apply(result);
					}
				}, 65f, live: true);
				NativeUi.Button((Transform)(object)parent2, "+", delegate
				{
					Apply((float)field.GetValue(draft) + step);
					input.SetTextWithoutNotify(((float)field.GetValue(draft)).ToString("0.###", CultureInfo.InvariantCulture));
				}, 24f);
				void Apply(float value)
				{
					IconCalibration iconCalibration = draft.Copy();
					field.SetValue(iconCalibration, value);
					if (!iconCalibration.Valid())
					{
						return;
					}
					draft = iconCalibration;
					Plugin.Settings.iconCalibrations.RemoveAll((IconCalibration c) => c.prefab == selectedName);
					Plugin.Settings.iconCalibrations.Add(draft.Copy());
					ChestContentsIcons.CalibrationChanged();
					try
					{
						DrawOverlay();
					}
					catch (Exception error)
					{
						FailPreview(error);
					}
				}
			}
		}

		private void CreatePreview(ChestContentsIcons.Geometry geometry, RawImage image)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0109: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Expected O, but got Unknown
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: 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_03e5: Unknown result type (might be due to invalid IL or missing references)
			stage = new GameObject("HL render-only calibration");
			stage.transform.position = new Vector3(100000f, 100000f, 100000f);
			model = new GameObject("Rest model");
			model.transform.SetParent(stage.transform, false);
			Container template = geometry.Template;
			MeshRenderer[] array = ChestContentsIcons.PreviewRenderers(selected);
			Material fallback = array.SelectMany((MeshRenderer r) => ((Renderer)r).sharedMaterials).FirstOrDefault((Func<Material, bool>)((Material m) => Object.op_Implicit((Object)(object)m) && Object.op_Implicit((Object)(object)m.shader) && m.shader.isSupported));
			if (!Object.op_Implicit((Object)(object)fallback))
			{
				throw new InvalidOperationException("The selected model has no supported loaded material.");
			}
			Dictionary<Material, Material> copies = new Dictionary<Material, Material>();
			MeshRenderer[] array2 = array;
			foreach (MeshRenderer val in array2)
			{
				GameObject val2 = new GameObject(((Object)val).name);
				val2.transform.SetParent(model.transform, false);
				val2.layer = 31;
				val2.transform.localPosition = ((Component)template).transform.InverseTransformPoint(((Component)val).transform.position);
				val2.transform.localRotation = Quaternion.Inverse(((Component)template).transform.rotation) * ((Component)val).transform.rotation;
				Vector3 lossyScale = ((Component)template).transform.lossyScale;
				Vector3 lossyScale2 = ((Component)val).transform.lossyScale;
				val2.transform.localScale = new Vector3(lossyScale2.x / lossyScale.x, lossyScale2.y / lossyScale.y, lossyScale2.z / lossyScale.z);
				val2.AddComponent<MeshFilter>().sharedMesh = ((Component)val).GetComponent<MeshFilter>().sharedMesh;
				MeshRenderer obj = val2.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterials = ((IEnumerable<Material>)((Renderer)val).sharedMaterials).Select((Func<Material, Material>)delegate(Material original)
				{
					//IL_003f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0045: Expected O, but got Unknown
					Material val5 = ((Object.op_Implicit((Object)(object)original) && Object.op_Implicit((Object)(object)original.shader) && original.shader.isSupported) ? original : fallback);
					if (copies.TryGetValue(val5, out var value))
					{
						return value;
					}
					value = new Material(val5);
					materials.Add(value);
					copies[val5] = value;
					return value;
				}).ToArray();
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			}
			cameraObject = new GameObject("Calibration camera");
			cameraObject.transform.SetParent(stage.transform, false);
			camera = cameraObject.AddComponent<Camera>();
			((Behaviour)camera).enabled = false;
			camera.orthographic = true;
			camera.clearFlags = (CameraClearFlags)2;
			camera.backgroundColor = Color.clear;
			camera.cullingMask = int.MinValue;
			camera.nearClipPlane = 0.01f;
			camera.farClipPlane = 500f;
			camera.allowHDR = false;
			camera.allowMSAA = false;
			texture = new RenderTexture(900, 360, 24, (RenderTextureFormat)0);
			if (!texture.Create())
			{
				throw new InvalidOperationException("Could not create the preview render texture.");
			}
			camera.targetTexture = texture;
			image.texture = (Texture)(object)texture;
			GameObject val3 = new GameObject("Preview key light");
			val3.transform.SetParent(stage.transform, false);
			val3.transform.localPosition = new Vector3(4f, 7f, -6f);
			Light obj2 = val3.AddComponent<Light>();
			obj2.type = (LightType)2;
			obj2.range = 40f;
			obj2.intensity = 2f;
			obj2.cullingMask = int.MinValue;
			GameObject val4 = new GameObject("Preview fill light");
			val4.transform.SetParent(stage.transform, false);
			val4.transform.localPosition = new Vector3(-4f, 4f, 6f);
			Light obj3 = val4.AddComponent<Light>();
			obj3.type = (LightType)2;
			obj3.range = 40f;
			obj3.intensity = 1.2f;
			obj3.cullingMask = int.MinValue;
			DrawOverlay();
			Tick();
		}

		private void DrawOverlay()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)model))
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)overlays))
			{
				overlays.SetActive(false);
				Object.Destroy((Object)(object)overlays);
			}
			overlays = new GameObject("Calibrated frame");
			overlays.transform.SetParent(model.transform, false);
			IconPlacementFrame iconPlacementFrame = ChestContentsIcons.Frame(selected, draft);
			Sprite[] sprites = (from s in ((IEnumerable<string>)new string[6] { "Wood", "Stone", "Resin", "Coal", "Iron", "ArrowWood" }).Select((Func<string, Sprite>)delegate(string id)
				{
					if (!Object.op_Implicit((Object)(object)ObjectDB.instance))
					{
						return (Sprite)null;
					}
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(id);
					if (itemPrefab == null)
					{
						return (Sprite)null;
					}
					ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
					return (component == null) ? null : component.m_itemData.GetIcon();
				})
				where Object.op_Implicit((Object)(object)s)
				select s).ToArray();
			ChestContentsIcons.DrawIcons(overlays.transform, iconPlacementFrame, sprites, single, frontBack, background);
			if (!Object.op_Implicit((Object)(object)wireMaterial))
			{
				SpriteRenderer obj = overlays.AddComponent<SpriteRenderer>();
				Material sharedMaterial = ((Renderer)obj).sharedMaterial;
				if (!Object.op_Implicit((Object)(object)sharedMaterial) || !Object.op_Implicit((Object)(object)sharedMaterial.shader) || !sharedMaterial.shader.isSupported)
				{
					throw new InvalidOperationException("No supported sprite material for the calibration wireframe.");
				}
				wireMaterial = new Material(sharedMaterial);
				materials.Add(wireMaterial);
				Object.Destroy((Object)(object)obj);
			}
			for (int num = 0; num < 8; num++)
			{
				for (int num2 = 0; num2 < 3; num2++)
				{
					if ((num & (1 << num2)) == 0)
					{
						Line(iconPlacementFrame.Corner(num), iconPlacementFrame.Corner(num | (1 << num2)), Color.cyan, ((Vector3)(ref iconPlacementFrame.Size)).magnitude * 0.002f, wireMaterial);
					}
				}
			}
			for (int num3 = 0; num3 < 3; num3++)
			{
				Vector3 val = iconPlacementFrame.Rotation * (Vector3)(num3 switch
				{
					1 => Vector3.up, 
					0 => Vector3.right, 
					_ => Vector3.forward, 
				}) * ((Vector3)(ref iconPlacementFrame.Size)).magnitude * 0.035f;
				Line(iconPlacementFrame.Center - val, iconPlacementFrame.Center + val, Color.yellow, ((Vector3)(ref iconPlacementFrame.Size)).magnitude * 0.003f, wireMaterial);
			}
			Transform[] componentsInChildren = overlays.GetComponentsInChildren<Transform>(true);
			for (int num4 = 0; num4 < componentsInChildren.Length; num4++)
			{
				((Component)componentsInChildren[num4]).gameObject.layer = 31;
			}
		}

		private void Line(Vector3 a, Vector3 b, Color color, float width, Material material)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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)
			GameObject val = new GameObject("Calibration edge");
			val.transform.SetParent(overlays.transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			val2.useWorldSpace = false;
			((Renderer)val2).sharedMaterial = material;
			val2.positionCount = 2;
			val2.SetPositions((Vector3[])(object)new Vector3[2] { a, b });
			float startWidth = (val2.endWidth = width);
			val2.startWidth = startWidth;
			Color startColor = (val2.endColor = color);
			val2.startColor = startColor;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
		}

		internal void Tick()
		{
			if (Time.realtimeSinceStartup >= nextNearbyCheck)
			{
				nextNearbyCheck = Time.realtimeSinceStartup + 1f;
				string text = string.Join("|", from p in NearbyPrefabs()
					select ((Object)p).name);
				if (text != nearbySignature)
				{
					nearbySignature = text;
					rebuild?.Invoke();
					return;
				}
			}
			if (!Object.op_Implicit((Object)(object)camera) || !Object.op_Implicit((Object)(object)selected) || !Object.op_Implicit((Object)(object)stage))
			{
				return;
			}
			try
			{
				RenderPreview();
			}
			catch (Exception error)
			{
				FailPreview(error);
			}
		}

		private void RenderPreview()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			if (autoRotate)
			{
				yaw += Time.unscaledDeltaTime * 15f;
			}
			IconPlacementFrame iconPlacementFrame = ChestContentsIcons.Frame(selected, draft);
			Bounds body = ChestContentsIcons.ClosedGeometry(selected).Body;
			float val = ((Vector3)(ref iconPlacementFrame.Size)).magnitude + Vector3.Distance(iconPlacementFrame.Center, ((Bounds)(ref body)).center) * 2f;
			Vector3 size = ((Bounds)(ref body)).size;
			float num = Math.Max(val, ((Vector3)(ref size)).magnitude);
			Vector3 val2 = (iconPlacementFrame.Center + ((Bounds)(ref body)).center) * 0.5f;
			camera.orthographicSize = Math.Max(0.4f, num * 0.65f);
			camera.farClipPlane = num * 5f + 10f;
			((Component)camera).transform.localPosition = val2 + Quaternion.Euler(18f, yaw, 0f) * new Vector3(0f, 0f, (0f - num) * 2f - 1f);
			((Component)camera).transform.LookAt(stage.transform.TransformPoint(val2));
			camera.Render();
		}

		private void FailPreview(Exception error)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Diagnostics.Error("ContainerCalibrationPreview", error);
			Dispose();
			if (Object.op_Implicit((Object)(object)previewImage))
			{
				((Graphic)previewImage).color = Color.clear;
			}
			if (Object.op_Implicit((Object)(object)previewStatus))
			{
				previewStatus.text = "Preview unavailable. Calibration controls still work.\nChoose another type or reopen this page to retry.\n" + error.GetBaseException().Message;
				((Component)previewStatus).gameObject.SetActive(true);
			}
		}

		public void Dispose()
		{
			if (Object.op_Implicit((Object)(object)previewImage))
			{
				previewImage.texture = null;
			}
			if (Object.op_Implicit((Object)(object)camera))
			{
				((Behaviour)camera).enabled = false;
				camera.targetTexture = null;
			}
			if (Object.op_Implicit((Object)(object)stage))
			{
				stage.SetActive(false);
				Object.Destroy((Object)(object)stage);
			}
			if (Object.op_Implicit((Object)(object)texture))
			{
				texture.Release();
				Object.Destroy((Object)(object)texture);
			}
			foreach (Material material in materials)
			{
				if (Object.op_Implicit((Object)(object)material))
				{
					Object.Destroy((Object)(object)material);
				}
			}
			materials.Clear();
			wireMaterial = null;
			stage = (model = (overlays = (cameraObject = null)));
			camera = null;
			texture = null;
		}
	}
	public sealed class ContainerUI
	{
		internal static readonly ContainerUI Instance = new ContainerUI();

		internal int Selected = -1;

		private RectTransform root;

		private Button downloadShortcut;

		private RectTransform body;

		private const float PanelHeight = 440f;

		private bool filtersOpen;

		private ContainerRules clipboard;

		private Filter selection = new Filter();

		private bool rebuild;

		private bool picking;

		private bool pickingStock;

		private bool categories;

		private bool showStock = true;

		private bool diagnostics;

		private bool templates;

		private string search = "";

		private string status = "";

		private string templateName = "";

		private string contentsKey = "";

		private readonly Dictionary<string, TMP_Text> currentLabels = new Dictionary<string, TMP_Text>();

		private string[] stockModel = Array.Empty<string>();

		private string stockDraft = "";

		private readonly List<Func<string>> controlSnapshots = new List<Func<string>>();

		private bool tickFailed;

		private bool diagnosticRefresh;

		private bool canEdit;

		private bool ignoredState;

		private string accessStatus = "";

		internal Container Container { get; private set; }

		internal ContainerRules Layout { get; private set; }

		internal bool Editing { get; private set; }

		private string EditReason
		{
			get
			{
				if (!canEdit)
				{
					return ContainerConfigurationAccess.Status;
				}
				return "ContainerAccessible";
			}
		}

		internal bool Typing
		{
			get
			{
				GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
				if (Object.op_Implicit((Object)(object)root) && Object.op_Implicit((Object)(object)val) && val.transform.IsChildOf((Transform)(object)root) && Object.op_Implicit((Object)(object)val.GetComponent<TMP_InputField>()))
				{
					return val.GetComponent<TMP_InputField>().isFocused;
				}
				return false;
			}
		}

		private string[] PresentItems()
		{
			return (from id in (from i in Container.GetInventory().GetAllItems()
					where i != null && i.m_stack > 0
					orderby i.m_gridPos.y, i.m_gridPos.x
					select i).Select(Access.Id)
				where !string.IsNullOrEmpty(id)
				select id).Distinct<string>(StringComparer.Ordinal).ToArray();
		}

		internal void RequestRefresh()
		{
			rebuild = true;
			tickFailed = false;
		}

		private static ContainerRules Clone(ContainerRules r)
		{
			return ChestRuleCodec.Clone(r);
		}

		internal bool Accepts(InventoryGrid grid)
		{
			if (Editing && Layout != null && Object.op_Implicit((Object)(object)Container))
			{
				return grid.GetInventory() == Container.GetInventory();
			}
			return false;
		}

		internal void Tick()
		{
			try
			{
				TickCore();
			}
			catch (Exception error)
			{
				tickFailed = true;
				rebuild = false;
				Diagnostics.Error("ChestPanel", error);
			}
		}

		private void TickCore()
		{
			InventoryGui instance = InventoryGui.instance;
			Container val = ((Object.op_Implicit((Object)(object)instance) && InventoryGui.IsVisible()) ? Access.Field<Container>(instance, "m_currentContainer") : null);
			if ((Object)(object)val != (Object)(object)Container)
			{
				Dispose();
				Container = val;
				Layout = null;
				Selected = -1;
				picking = (diagnostics = (templates = false));
				status = "";
				tickFailed = false;
				if (Object.op_Implicit((Object)(object)Container))
				{
					if (Diagnostics.Verbose)
					{
						Diagnostics.Capture("ContainerOpen", delegate
						{
							Diagnostics.Detail("Container opened");
							Diagnostics.ContainerInfo(Container);
						});
					}
					try
					{
						Layout = Plugin.RuleCache.ReadForUI(Container);
					}
					catch (Exception ex)
					{
						status = "Cannot read chest rules. See log; debug refresh can retry.";
						Diagnostics.Error("RuleDecode", ex);
						Plugin.Feedback.Show(ex.Message);
					}
					canEdit = Plugin.Shared.CanEdit(Container);
					LogEditState();
					rebuild = true;
				}
			}
			if (!Object.op_Implicit((Object)(object)Container) || tickFailed)
			{
				return;
			}
			ContainerConfigurationAccess.Tick(Container);
			if (accessStatus != ContainerConfigurationAccess.Status)
			{
				accessStatus = ContainerConfigurationAccess.Status;
				rebuild = true;
			}
			bool flag = Plugin.Shared.CanEdit(Container);
			bool flag2 = ContainerParticipation.Ignored(Container);
			if (flag2 != ignoredState)
			{
				ignoredState = flag2;
				rebuild = true;
			}
			if (flag != canEdit)
			{
				canEdit = flag;
				if (flag)
				{
					Layout = Plugin.RuleCache.ReadForUI(Container);
				}
				rebuild = true;
				LogEditState();
			}
			string text = string.Join("|", PresentItems());
			bool typing = Typing;
			if (text != contentsKey && !typing)
			{
				contentsKey = text;
				rebuild = true;
			}
			if (rebuild)
			{
				rebuild = false;
				try
				{
					Build(instance);
					if (diagnosticRefresh)
					{
						Diagnostics.Info("Refresh Logistics Panel: UIBuild complete");
					}
				}
				catch (Exception error)
				{
					Diagnostics.Error("UIBuild", error);
					status = "Panel build failed. See Hearth Logistics log.";
				}
				finally
				{
					diagnosticRefresh = false;
				}
			}
			if (!Object.op_Implicit((Object)(object)root))
			{
				return;
			}
			((Component)root).gameObject.SetActive(!(SettingsUI.Instance?.Visible ?? false));
			if (Object.op_Implicit((Object)(object)downloadShortcut))
			{
				GameObject gameObject = ((Component)downloadShortcut).gameObject;
				SettingsUI instance2 = SettingsUI.Instance;
				gameObject.SetActive((instance2 == null || !instance2.Visible) && !Menu.IsVisible() && !ContainerParticipation.Ignored(Container));
				((Selectable)(object)downloadShortcut).SetInteractable(canEdit, EditReason);
			}
			Place(instance);
			if (((Component)root).gameObject.activeInHierarchy)
			{
				NativeUi.Navigate(root);
			}
			foreach (KeyValuePair<string, TMP_Text> currentLabel in currentLabels)
			{
				if (Object.op_Implicit((Object)(object)currentLabel.Value))
				{
					currentLabel.Value.text = Access.Count(Container.GetInventory(), currentLabel.Key).ToString();
				}
			}
		}

		internal void Select(Vector2i pos)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0096: 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)
			if (Object.op_Implicit((Object)(object)Container) && pos.x >= 0 && pos.y >= 0 && pos.x < Layout.width && pos.y < Layout.height)
			{
				Selected = pos.y * Layout.width + pos.x;
				Filter filter = Layout.At(pos.x, pos.y);
				ItemData itemAt = Container.GetInventory().GetItemAt(pos.x, pos.y);
				selection = new Filter
				{
					item = filter.item,
					category = filter.category,
					strict = filter.strict
				};
				if (filter.item.Length == 0 && filter.category.Length == 0 && itemAt != null)
				{
					selection.item = Access.Id(itemAt);
				}
				Diagnostics.Detail("Filter slot selected: (" + pos.x + "," + pos.y + ") item=" + selection.item + " category=" + selection.category + " strict=" + selection.strict);
				picking = false;
				rebuild = true;
			}
		}

		private void Change(Action<ContainerRules> edit)
		{
			if (Object.op_Implicit((Object)(object)Container) && Layout != null)
			{
				ContainerRules containerRules = Clone(Layout);
				edit(containerRules);
				Diagnostics.Detail("RULE MUTATION layoutIdentity=" + RuntimeHelpers.GetHashCode(containerRules) + " stockRules=" + containerRules.stock.Count);
				Plugin.Shared.Write(Container, containerRules, Layout.revision, Layout.sharedToken);
				Layout = containerRules;
				status = "Saved to chest.";
				rebuild = true;
				Diagnostics.Detail("UI refresh requested after committed rule change.");
			}
		}

		private void ToggleEditing()
		{
			if (Plugin.Shared.CanEdit(Container))
			{
				if (!Editing && Access.Field<ItemData>(InventoryGui.instance, "m_dragItem") != null)
				{
					status = "Finish the current item drag first.";
					rebuild = true;
					return;
				}
				Editing = !Editing;
				picking = false;
				rebuild = true;
				Diagnostics.Info("Filter edit mode: " + Editing);
			}
		}

		private void Build(InventoryGui gui)
		{
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0631: Unknown result type (might be due to invalid IL or missing references)
			//IL_0638: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0661: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				stockModel = ((Layout == null) ? Array.Empty<string>() : StockTableModel.Keys(PresentItems(), Layout.stock));
			}
			catch (Exception error)
			{
				Diagnostics.Error("UIModel", error);
				throw;
			}
			if (Diagnostics.Verbose)
			{
				Diagnostics.Capture("InventoryRead", delegate
				{
					Diagnostics.Physical(Container);
				});
				Diagnostics.Capture("Aggregate", delegate
				{
					Diagnostics.Aggregate(Container);
				});
				Diagnostics.Capture("UIModel", LogModel);
			}
			controlSnapshots.Clear();
			EventSystem events = EventSystem.current;
			int num = ((Object.op_Implicit((Object)(object)root) && Object.op_Implicit((Object)(object)events)) ? Array.FindIndex(((Component)root).GetComponentsInChildren<Selectable>(), (Selectable s) => (Object)(object)((Component)s).gameObject == (Object)(object)events.currentSelectedGameObject) : (-1));
			float[] array = (Object.op_Implicit((Object)(object)root) ? (from s in ((Component)root).GetComponentsInChildren<ScrollRect>()
				select s.verticalNormalizedPosition).ToArray() : Array.Empty<float>());
			if (Object.op_Implicit((Object)(object)root))
			{
				((Component)root).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)root).gameObject);
			}
			NativeUi.Font = gui.m_containerName.font;
			NativeUi.ButtonSource = gui.m_takeAllButton;
			root = NativeUi.Rect("HearthLogisticsChest", (Transform)(object)gui.m_container);
			((Component)root).gameObject.AddComponent<CanvasGroup>().ignoreParentGroups = true;
			((Transform)root).SetAsLastSibling();
			LogParents();
			RectTransform obj = root;
			RectTransform obj2 = root;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			obj2.anchorMax = val;
			Vector2 anchorMin = val;
			obj.anchorMin = anchorMin;
			root.pivot = new Vector2(0f, 1f);
			NativeUi.PanelBackground(root, (Transform)(object)gui.m_container);
			NativeUi.Vertical(root, 10);
			currentLabels.Clear();
			NativeUi.Label((Transform)(object)root, "HEARTH LOGISTICS", 0f, 22f);
			if (!Object.op_Implicit((Object)(object)downloadShortcut))
			{
				downloadShortcut = DownloadShortcut.Create(gui.m_container, delegate
				{
					DownloadUI.Open(Container);
				}, "Download to this container");
			}
			((Selectable)(object)downloadShortcut).SetInteractable(canEdit, EditReason);
			body = NativeUi.Scroll((Transform)(object)root, 393f, 180f, scrollbar: true);
			((Component)root).gameObject.AddComponent<ChestPanelWheel>();
			bool ignored = ContainerParticipation.I