Decompiled source of OdinsReach v0.1.0

OdinsReach.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("OdinsReach")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ce1fe04c1e0d3a2923c660dc5676ceccf87de5a5")]
[assembly: AssemblyProduct("OdinsReach")]
[assembly: AssemblyTitle("OdinsReach")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace OdinsMissingPatch
{
	internal static class ChestFavorites
	{
		[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
		[Serves(new Type[]
		{
			typeof(QuickStack),
			typeof(ChestButtons)
		}, Optional = true)]
		private static class ShowMarks
		{
			private static readonly FieldRef<InventoryElement, Graphic> Amount = AccessTools.FieldRefAccess<InventoryElement, Graphic>("m_amount");

			private static Container shownChest;

			private static uint shownRevision;

			private static InventoryElement shownFirst;

			private static bool tinted;

			private static Color plain;

			private static bool plainKnown;

			private static void Prepare()
			{
				PanelButtons.Add(ClearButton.Button, PanelButtons.Spot.StackAll, ClearButton.Shows, ClearButton.Refresh);
			}

			private static void Postfix(InventoryGui __instance)
			{
				//IL_0174: Unknown result type (might be due to invalid IL or missing references)
				if (PanelButtons.Closing(__instance))
				{
					return;
				}
				InventoryGrid containerGrid = __instance.m_containerGrid;
				if ((Object)(object)containerGrid == (Object)null || !KnowPlain(containerGrid))
				{
					return;
				}
				List<InventoryElement> elements = containerGrid.m_elements;
				Container currentContainer = __instance.m_currentContainer;
				ZNetView val = (((Object)(object)currentContainer != (Object)null) ? currentContainer.m_nview : null);
				if (!Used || (Object)(object)val == (Object)null || !val.IsValid() || containerGrid.m_inventory != currentContainer.GetInventory())
				{
					if (tinted)
					{
						Reset(elements);
					}
					shownChest = null;
					return;
				}
				uint dataRevision = val.GetZDO().DataRevision;
				InventoryElement val2 = ((elements.Count > 0) ? elements[0] : null);
				if ((Object)(object)currentContainer == (Object)(object)shownChest && dataRevision == shownRevision && (Object)(object)val2 == (Object)(object)shownFirst)
				{
					return;
				}
				shownChest = currentContainer;
				shownRevision = dataRevision;
				shownFirst = val2;
				Reset(elements);
				string text = Marks(currentContainer);
				if (text.Length == 0)
				{
					return;
				}
				Inventory inventory = containerGrid.m_inventory;
				int width = inventory.GetWidth();
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (Marked(text, allItem.m_shared.m_name))
					{
						InventoryElement element = containerGrid.GetElement(allItem.m_gridPos.x, allItem.m_gridPos.y, width);
						Graphic val3 = (((Object)(object)element != (Object)null) ? Amount.Invoke(element) : null);
						if ((Object)(object)val3 != (Object)null)
						{
							val3.color = Palette.ChestYellow;
							tinted = true;
						}
					}
				}
			}

			private static bool KnowPlain(InventoryGrid grid)
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				if (plainKnown)
				{
					return true;
				}
				InventoryElement val = (((Object)(object)grid.m_elementPrefab != (Object)null) ? grid.m_elementPrefab.GetComponent<InventoryElement>() : null);
				Graphic val2 = (((Object)(object)val != (Object)null) ? Amount.Invoke(val) : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				plain = val2.color;
				plainKnown = true;
				return true;
			}

			private static void Reset(List<InventoryElement> elements)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				foreach (InventoryElement element in elements)
				{
					Graphic val = (((Object)(object)element != (Object)null) ? Amount.Invoke(element) : null);
					if ((Object)(object)val != (Object)null)
					{
						val.color = plain;
					}
				}
				tinted = false;
			}
		}

		private static class ClearButton
		{
			internal static readonly PanelButtons.TextButton Button = new PanelButtons.TextButton("OMP_ClearFavorites", new UnityAction(ClearOpen));

			private static string favorites = "";

			private static int revision = -1;

			private static int count;

			private static string tooltip = "";

			internal static bool Shows(InventoryGui gui)
			{
				Container currentContainer = gui.m_currentContainer;
				if ((Object)(object)currentContainer != (Object)null && (Object)(object)gui.m_container != (Object)null && ((Component)gui.m_container).gameObject.activeSelf && Used)
				{
					return Marks(currentContainer).Length > 0;
				}
				return false;
			}

			internal static void Refresh(InventoryGui gui)
			{
				Describe(gui.m_currentContainer, Marks(gui.m_currentContainer));
				Button.SetLabel((count == 1) ? "$omp_clear_favourite" : "$omp_clear_favourites", count.ToString());
				Button.SetTooltip("$omp_favourites_topic", tooltip);
			}

			private static void Describe(Container chest, string marks)
			{
				if (!(marks == favorites) || revision != Translations.Revision)
				{
					favorites = marks;
					revision = Translations.Revision;
					count = Names(chest).Count;
					tooltip = "$omp_favourites_tip_head\n" + ChestFavorites.Describe(chest) + "\n\n$omp_favourites_tip_foot";
				}
			}

			private static void ClearOpen()
			{
				InventoryGui instance = InventoryGui.instance;
				Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null);
				if (!((Object)(object)val == (Object)null))
				{
					Clear(val);
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer != (Object)null)
					{
						((Character)localPlayer).Message((MessageType)2, "$omp_favourites_cleared", 0, (Sprite)null, false);
					}
				}
			}
		}

		private static readonly int FavoritesHash = StringExtensionMethods.GetStableHashCode("OMP_ChestFavorites");

		private const char Separator = '\n';

		internal static bool Used => Patcher.AnyServedOn(typeof(ShowMarks));

		internal static string Marks(Container chest)
		{
			ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null);
			if (!((Object)(object)val != (Object)null) || !val.IsValid())
			{
				return "";
			}
			return val.GetZDO().GetString(FavoritesHash, "");
		}

		internal static bool Marked(string marks, string itemName)
		{
			if (string.IsNullOrEmpty(marks) || string.IsNullOrEmpty(itemName))
			{
				return false;
			}
			for (int num = marks.IndexOf(itemName, StringComparison.Ordinal); num >= 0; num = marks.IndexOf(itemName, num + 1, StringComparison.Ordinal))
			{
				int num2 = num + itemName.Length;
				if (num > 0 && num2 < marks.Length && marks[num - 1] == '\n' && marks[num2] == '\n')
				{
					return true;
				}
			}
			return false;
		}

		internal static bool Accepts(Container chest, string itemName)
		{
			return Marked(Marks(chest), itemName);
		}

		internal static List<string> Names(Container chest)
		{
			List<string> list = new List<string>();
			string[] array = Marks(chest).Split(new char[1] { '\n' });
			foreach (string text in array)
			{
				if (text.Length > 0)
				{
					list.Add(text);
				}
			}
			return list;
		}

		internal static bool Toggle(Container chest, string itemName)
		{
			List<string> list = Names(chest);
			bool num = !list.Remove(itemName);
			if (num)
			{
				list.Add(itemName);
			}
			Write(chest, list);
			return num;
		}

		internal static void Clear(Container chest)
		{
			Write(chest, new List<string>());
		}

		internal static string Describe(Container chest)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in Names(chest))
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append("- ").Append(Localize(item));
			}
			return stringBuilder.ToString();
		}

		internal static string Localize(string itemName)
		{
			if (Localization.instance == null)
			{
				return itemName;
			}
			return Localization.instance.Localize(itemName);
		}

		internal static Container OpenChest(Inventory inventory)
		{
			InventoryGui instance = InventoryGui.instance;
			Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null);
			if (!((Object)(object)val != (Object)null) || inventory == null || val.m_inventory != inventory)
			{
				return null;
			}
			return val;
		}

		private static void Write(Container chest, List<string> names)
		{
			ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return;
			}
			if (!val.IsOwner())
			{
				val.ClaimOwnership();
			}
			if (!val.IsOwner())
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string name in names)
			{
				stringBuilder.Append('\n').Append(name);
			}
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Append('\n');
			}
			val.GetZDO().Set(FavoritesHash, stringBuilder.ToString());
		}
	}
	internal sealed class ChestGlow : MonoBehaviour
	{
		private const float Duration = 7f;

		private float time;

		internal static void Flash(Container chest, string text)
		{
			//IL_0057: 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)
			if (!((Object)(object)chest == (Object)null))
			{
				GameObject val = (((Object)(object)chest.m_rootObjectOverride != (Object)null) ? ((Component)chest.m_rootObjectOverride).gameObject : ((Component)chest).gameObject);
				ChestGlow chestGlow = val.GetComponent<ChestGlow>();
				if ((Object)(object)chestGlow == (Object)null)
				{
					chestGlow = val.AddComponent<ChestGlow>();
				}
				chestGlow.time = 0f;
				if (text != null)
				{
					ShowText(((Component)chest).transform.position + Vector3.up, text);
				}
			}
		}

		private static void ShowText(Vector3 position, string text)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			DamageText instance = DamageText.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				Camera mainCamera = Utils.GetMainCamera();
				float num = (((Object)(object)mainCamera != (Object)null) ? Vector3.Distance(((Component)mainCamera).transform.position, position) : 0f);
				instance.AddInworldText((TextType)7, position, num, text, false);
			}
		}

		private void Update()
		{
			//IL_0064: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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)
			time += Time.deltaTime;
			MaterialMan instance = MaterialMan.instance;
			if ((Object)(object)instance == (Object)null || time >= 7f)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			float num = Mathf.Abs(Mathf.Sin(time / 7f * (float)Math.PI * 3f));
			instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._EmissionColor, Palette.Gold * (0.6f * num), false);
			instance.SetValue<Color>(((Component)this).gameObject, ShaderProps._Color, Color.Lerp(Color.white, Palette.Gold, 0.6f * num), false);
		}

		private void OnDestroy()
		{
			MaterialMan instance = MaterialMan.instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.ResetValue(((Component)this).gameObject, ShaderProps._EmissionColor);
				instance.ResetValue(((Component)this).gameObject, ShaderProps._Color);
			}
		}
	}
	internal static class InventorySorter
	{
		internal static bool Sort(Inventory inventory, int fromRow, Func<ItemData, bool> keep)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_004f: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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)
			if (inventory == null)
			{
				return false;
			}
			List<ItemData> allItems = inventory.GetAllItems();
			int width = inventory.GetWidth();
			int height = inventory.GetHeight();
			bool[,] array = new bool[width, height];
			List<ItemData> list = new List<ItemData>();
			foreach (ItemData item in allItems)
			{
				Vector2i gridPos = item.m_gridPos;
				bool flag = gridPos.x >= 0 && gridPos.x < width && gridPos.y >= 0 && gridPos.y < height;
				if (flag && gridPos.y >= fromRow && (keep == null || !keep(item)))
				{
					list.Add(item);
				}
				else if (flag)
				{
					array[gridPos.x, gridPos.y] = true;
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			List<Vector2i> list2 = new List<Vector2i>();
			for (int i = fromRow; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					if (!array[j, i])
					{
						list2.Add(new Vector2i(j, i));
					}
				}
			}
			if (list2.Count < list.Count)
			{
				return false;
			}
			MaterialOrder.Prepare();
			list.Sort(Compare);
			List<ItemData> list3 = Merge(list, allItems);
			for (int k = 0; k < list3.Count; k++)
			{
				list3[k].m_gridPos = list2[k];
			}
			inventory.Changed(false, false);
			return true;
		}

		private static List<ItemData> Merge(List<ItemData> sorted, List<ItemData> all)
		{
			List<ItemData> list = new List<ItemData>(sorted.Count);
			foreach (ItemData item in sorted)
			{
				if (item.m_shared.m_maxStackSize > 1)
				{
					foreach (ItemData item2 in list)
					{
						if (item.m_stack <= 0)
						{
							break;
						}
						if (Merges(item2, item))
						{
							int num = Math.Min(item2.m_shared.m_maxStackSize - item2.m_stack, item.m_stack);
							item2.m_stack += num;
							item.m_stack -= num;
						}
					}
				}
				if (item.m_stack > 0)
				{
					list.Add(item);
				}
				else
				{
					all.Remove(item);
				}
			}
			return list;
		}

		internal static bool Merges(ItemData stack, ItemData item)
		{
			if (stack.m_stack < stack.m_shared.m_maxStackSize)
			{
				return SameStack(stack, item);
			}
			return false;
		}

		private static bool SameStack(ItemData a, ItemData b)
		{
			if (a.m_shared.m_name != b.m_shared.m_name || a.m_quality != b.m_quality || a.m_variant != b.m_variant || a.m_worldLevel != b.m_worldLevel || a.m_cheated != b.m_cheated)
			{
				return false;
			}
			if (Covers(a.m_customData, b.m_customData))
			{
				return Covers(b.m_customData, a.m_customData);
			}
			return false;
		}

		private static bool Covers(Dictionary<string, string> a, Dictionary<string, string> b)
		{
			foreach (KeyValuePair<string, string> item in a)
			{
				if (item.Key != "OMP_Favorite" && (!b.TryGetValue(item.Key, out var value) || value != item.Value))
				{
					return false;
				}
			}
			return true;
		}

		private static int Compare(ItemData a, ItemData b)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			int num = Rank(a.m_shared.m_itemType).CompareTo(Rank(b.m_shared.m_itemType));
			if (num != 0)
			{
				return num;
			}
			if ((int)a.m_shared.m_itemType == 1 && (int)b.m_shared.m_itemType == 1)
			{
				num = Portable(a).CompareTo(Portable(b));
				if (num != 0)
				{
					return num;
				}
				num = MaterialOrder.Compare(a, b);
				if (num != 0)
				{
					return num;
				}
			}
			num = string.Compare(DisplayName(a), DisplayName(b), StringComparison.CurrentCultureIgnoreCase);
			if (num != 0)
			{
				return num;
			}
			num = b.m_quality.CompareTo(a.m_quality);
			if (num != 0)
			{
				return num;
			}
			num = a.m_variant.CompareTo(b.m_variant);
			if (num == 0)
			{
				return b.m_stack.CompareTo(a.m_stack);
			}
			return num;
		}

		private static int Portable(ItemData item)
		{
			return (!item.m_shared.m_teleportable) ? 1 : 0;
		}

		private static string DisplayName(ItemData item)
		{
			string name = item.m_shared.m_name;
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return name;
			}
			return instance.Localize(name);
		}

		private static int Rank(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected I4, but got Unknown
			switch (type - 1)
			{
			case 2:
			case 3:
			case 13:
			case 14:
			case 19:
			case 21:
				return 0;
			case 4:
				return 1;
			case 18:
				return 2;
			case 5:
				return 3;
			case 6:
				return 4;
			case 10:
				return 5;
			case 16:
				return 6;
			case 11:
				return 7;
			case 9:
				return 8;
			case 17:
				return 9;
			case 23:
				return 10;
			case 8:
				return 11;
			case 22:
				return 12;
			case 1:
				return 13;
			case 20:
				return 14;
			case 0:
				return 15;
			case 12:
				return 16;
			case 15:
				return 17;
			default:
				return 18;
			}
		}
	}
	internal static class MaterialOrder
	{
		private struct Place
		{
			internal int Family;

			internal int Depth;
		}

		private sealed class Step
		{
			internal SharedData Result;

			internal readonly List<SharedData> Inputs = new List<SharedData>();

			internal int Station = -1;

			internal int Level;
		}

		private sealed class Group
		{
			internal readonly List<SharedData> Members = new List<SharedData>();

			internal int Low = int.MaxValue;

			internal string Name;

			internal void Note(SharedData kind, int depth)
			{
				Members.Add(kind);
				string text = Label(kind);
				if (depth < Low || (depth == Low && string.Compare(text, Name, StringComparison.CurrentCultureIgnoreCase) < 0))
				{
					Low = depth;
					Name = text;
				}
			}
		}

		private const int MaxPasses = 32;

		private static ObjectDB source;

		private static int sourceRecipes;

		private static int sourceItems;

		private static Dictionary<SharedData, Place> places;

		internal static void Prepare()
		{
			ObjectDB instance = ObjectDB.instance;
			if (!((Object)(object)instance == (Object)null) && (!((Object)(object)instance == (Object)(object)source) || instance.m_recipes.Count != sourceRecipes || instance.m_items.Count != sourceItems))
			{
				source = instance;
				sourceRecipes = instance.m_recipes.Count;
				sourceItems = instance.m_items.Count;
				places = Build(instance);
			}
		}

		internal static int Compare(ItemData a, ItemData b)
		{
			Place place = Of(a);
			Place place2 = Of(b);
			int num = place.Family.CompareTo(place2.Family);
			if (num == 0)
			{
				return place.Depth.CompareTo(place2.Depth);
			}
			return num;
		}

		private static Place Of(ItemData item)
		{
			if (places != null && item != null && item.m_shared != null && places.TryGetValue(item.m_shared, out var value))
			{
				return value;
			}
			return new Place
			{
				Family = int.MaxValue,
				Depth = 0
			};
		}

		private static Dictionary<SharedData, Place> Build(ObjectDB db)
		{
			List<Piece> allBuildPieces = db.GetAllBuildPieces(true);
			Dictionary<CraftingStation, int> stations = Stations(allBuildPieces);
			List<Step> steps = Steps(db, allBuildPieces, stations);
			int[] pieceDepth = new int[allBuildPieces.Count];
			Dictionary<SharedData, int> made = new Dictionary<SharedData, int>();
			Settle(allBuildPieces, stations, Producers(steps), pieceDepth, made);
			Dictionary<SharedData, int> dictionary = Depths(made, Uses(steps, allBuildPieces, made, pieceDepth));
			Dictionary<SharedData, SharedData> parents = Families(steps);
			Dictionary<SharedData, Group> dictionary2 = new Dictionary<SharedData, Group>();
			foreach (KeyValuePair<SharedData, int> item in dictionary)
			{
				SharedData key = Find(parents, item.Key);
				if (!dictionary2.TryGetValue(key, out var value))
				{
					value = (dictionary2[key] = new Group());
				}
				value.Note(item.Key, item.Value);
			}
			List<Group> list = new List<Group>(dictionary2.Values);
			list.Sort(CompareGroups);
			Dictionary<SharedData, Place> dictionary3 = new Dictionary<SharedData, Place>();
			for (int i = 0; i < list.Count; i++)
			{
				foreach (SharedData member in list[i].Members)
				{
					dictionary3[member] = new Place
					{
						Family = i,
						Depth = dictionary[member]
					};
				}
			}
			return dictionary3;
		}

		private static Dictionary<CraftingStation, int> Stations(List<Piece> pieces)
		{
			Dictionary<CraftingStation, int> dictionary = new Dictionary<CraftingStation, int>();
			for (int i = 0; i < pieces.Count; i++)
			{
				Piece val = pieces[i];
				if (!((Object)(object)val == (Object)null))
				{
					CraftingStation component = ((Component)val).GetComponent<CraftingStation>();
					if ((Object)(object)component != (Object)null && !dictionary.ContainsKey(component))
					{
						dictionary[component] = i;
					}
				}
			}
			return dictionary;
		}

		private static List<Step> Steps(ObjectDB db, List<Piece> pieces, Dictionary<CraftingStation, int> stations)
		{
			List<Step> list = new List<Step>();
			foreach (Recipe recipe in db.m_recipes)
			{
				if (!((Object)(object)recipe == (Object)null) && recipe.m_enabled && !((Object)(object)recipe.m_item == (Object)null))
				{
					Step step = new Step
					{
						Result = recipe.m_item.m_itemData.m_shared,
						Station = StationPiece(stations, recipe.m_craftingStation),
						Level = Math.Max(0, recipe.m_minStationLevel - 1)
					};
					Requirement[] resources = recipe.m_resources;
					foreach (Requirement val in resources)
					{
						Feed(step.Inputs, val?.m_resItem);
					}
					Keep(list, step);
				}
			}
			for (int j = 0; j < pieces.Count; j++)
			{
				Piece val2 = pieces[j];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Smelter component = ((Component)val2).GetComponent<Smelter>();
				if ((Object)(object)component != (Object)null)
				{
					foreach (ItemConversion item in component.m_conversion)
					{
						if (item != null)
						{
							Converted(list, j, item.m_from, item.m_to);
						}
					}
				}
				CookingStation component2 = ((Component)val2).GetComponent<CookingStation>();
				if ((Object)(object)component2 != (Object)null)
				{
					foreach (ItemConversion item2 in component2.m_conversion)
					{
						if (item2 != null)
						{
							Converted(list, j, item2.m_from, item2.m_to);
						}
					}
				}
				Fermenter component3 = ((Component)val2).GetComponent<Fermenter>();
				if (!((Object)(object)component3 != (Object)null))
				{
					continue;
				}
				foreach (ItemConversion item3 in component3.m_conversion)
				{
					if (item3 != null)
					{
						Converted(list, j, item3.m_from, item3.m_to);
					}
				}
			}
			return list;
		}

		private static void Converted(List<Step> steps, int station, ItemDrop from, ItemDrop to)
		{
			if (!((Object)(object)to == (Object)null))
			{
				Step step = new Step
				{
					Result = to.m_itemData.m_shared,
					Station = station
				};
				Feed(step.Inputs, from);
				Keep(steps, step);
			}
		}

		private static void Feed(List<SharedData> inputs, ItemDrop drop)
		{
			SharedData val = (((Object)(object)drop == (Object)null) ? null : drop.m_itemData.m_shared);
			if (val != null && !inputs.Contains(val))
			{
				inputs.Add(val);
			}
		}

		private static void Keep(List<Step> steps, Step step)
		{
			if (step.Result != null)
			{
				steps.Add(step);
			}
		}

		private static Dictionary<SharedData, List<Step>> Producers(List<Step> steps)
		{
			Dictionary<SharedData, List<Step>> dictionary = new Dictionary<SharedData, List<Step>>();
			foreach (Step step in steps)
			{
				if (!dictionary.TryGetValue(step.Result, out var value))
				{
					value = new List<Step>();
					dictionary[step.Result] = value;
				}
				value.Add(step);
			}
			return dictionary;
		}

		private static void Settle(List<Piece> pieces, Dictionary<CraftingStation, int> stations, Dictionary<SharedData, List<Step>> producers, int[] pieceDepth, Dictionary<SharedData, int> made)
		{
			bool flag = true;
			for (int i = 0; i < 32 && flag; i++)
			{
				flag = false;
				for (int j = 0; j < pieces.Count; j++)
				{
					Piece val = pieces[j];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					int num = StationDepth(stations, pieceDepth, val.m_craftingStation);
					Requirement[] resources = val.m_resources;
					foreach (Requirement val2 in resources)
					{
						if (val2 != null && (Object)(object)val2.m_resItem != (Object)null)
						{
							num = Math.Max(num, Depth(made, val2.m_resItem.m_itemData.m_shared));
						}
					}
					if (num + 1 > pieceDepth[j])
					{
						pieceDepth[j] = num + 1;
						flag = true;
					}
				}
				foreach (KeyValuePair<SharedData, List<Step>> producer in producers)
				{
					int num2 = int.MaxValue;
					foreach (Step item in producer.Value)
					{
						num2 = Math.Min(num2, StepDepth(item, made, pieceDepth));
					}
					if (num2 != int.MaxValue && num2 > Depth(made, producer.Key))
					{
						made[producer.Key] = num2;
						flag = true;
					}
				}
			}
		}

		private static Dictionary<SharedData, int> Uses(List<Step> steps, List<Piece> pieces, Dictionary<SharedData, int> made, int[] pieceDepth)
		{
			Dictionary<SharedData, int> dictionary = new Dictionary<SharedData, int>();
			foreach (Step step in steps)
			{
				int depth = StepDepth(step, made, pieceDepth);
				foreach (SharedData input in step.Inputs)
				{
					Lower(dictionary, input, depth);
				}
			}
			for (int i = 0; i < pieces.Count; i++)
			{
				Piece val = pieces[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Requirement[] resources = val.m_resources;
				foreach (Requirement val2 in resources)
				{
					if (val2 != null && (Object)(object)val2.m_resItem != (Object)null)
					{
						Lower(dictionary, val2.m_resItem.m_itemData.m_shared, pieceDepth[i]);
					}
				}
			}
			return dictionary;
		}

		private static Dictionary<SharedData, int> Depths(Dictionary<SharedData, int> made, Dictionary<SharedData, int> used)
		{
			Dictionary<SharedData, int> dictionary = new Dictionary<SharedData, int>();
			foreach (KeyValuePair<SharedData, int> item in used)
			{
				if (Material(item.Key))
				{
					dictionary[item.Key] = item.Value;
				}
			}
			foreach (KeyValuePair<SharedData, int> item2 in made)
			{
				if (Material(item2.Key) && !dictionary.ContainsKey(item2.Key))
				{
					dictionary[item2.Key] = item2.Value;
				}
			}
			return dictionary;
		}

		private static Dictionary<SharedData, SharedData> Families(List<Step> steps)
		{
			Dictionary<SharedData, SharedData> dictionary = new Dictionary<SharedData, SharedData>();
			foreach (Step step in steps)
			{
				if (!Material(step.Result))
				{
					continue;
				}
				foreach (SharedData input in step.Inputs)
				{
					if (Material(input))
					{
						Union(dictionary, step.Result, input);
					}
				}
			}
			return dictionary;
		}

		private static SharedData Find(Dictionary<SharedData, SharedData> parents, SharedData kind)
		{
			if (!parents.TryGetValue(kind, out var value))
			{
				parents[kind] = kind;
				return kind;
			}
			if (value == kind)
			{
				return kind;
			}
			return parents[kind] = Find(parents, value);
		}

		private static void Union(Dictionary<SharedData, SharedData> parents, SharedData a, SharedData b)
		{
			SharedData val = Find(parents, a);
			SharedData val2 = Find(parents, b);
			if (val != val2)
			{
				parents[val2] = val;
			}
		}

		private static int CompareGroups(Group a, Group b)
		{
			int num = a.Low.CompareTo(b.Low);
			if (num == 0)
			{
				return string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase);
			}
			return num;
		}

		private static int StepDepth(Step step, Dictionary<SharedData, int> made, int[] pieceDepth)
		{
			int num = ((step.Station >= 0) ? (pieceDepth[step.Station] + step.Level) : step.Level);
			foreach (SharedData input in step.Inputs)
			{
				num = Math.Max(num, Depth(made, input));
			}
			return num + 1;
		}

		private static int StationPiece(Dictionary<CraftingStation, int> stations, CraftingStation station)
		{
			if (!((Object)(object)station != (Object)null) || !stations.TryGetValue(station, out var value))
			{
				return -1;
			}
			return value;
		}

		private static int StationDepth(Dictionary<CraftingStation, int> stations, int[] pieceDepth, CraftingStation station)
		{
			int num = StationPiece(stations, station);
			if (num < 0)
			{
				return 0;
			}
			return pieceDepth[num];
		}

		private static int Depth(Dictionary<SharedData, int> depths, SharedData kind)
		{
			if (kind == null || !depths.TryGetValue(kind, out var value))
			{
				return 0;
			}
			return value;
		}

		private static void Lower(Dictionary<SharedData, int> depths, SharedData kind, int depth)
		{
			if (kind != null && (!depths.TryGetValue(kind, out var value) || depth < value))
			{
				depths[kind] = depth;
			}
		}

		private static bool Material(SharedData kind)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (kind != null)
			{
				return (int)kind.m_itemType == 1;
			}
			return false;
		}

		private static string Label(SharedData kind)
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return kind.m_name;
			}
			return instance.Localize(kind.m_name);
		}
	}
	internal static class NearbyChests
	{
		private sealed class Entry
		{
			public Container Container;

			public Piece Piece;

			public bool Tombstone;
		}

		internal readonly struct Scope : IDisposable
		{
			private readonly bool entered;

			internal Scope(Tweak tweak, Humanoid user)
			{
				entered = EnterReach(tweak, user);
			}

			public void Dispose()
			{
				LeaveReach(entered);
			}
		}

		[HarmonyPatch(typeof(Inventory), "CountItems")]
		[Serves(new Type[]
		{
			typeof(NearbyCrafting),
			typeof(StationRefill)
		})]
		private static class CountChests
		{
			private static void Postfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result)
			{
				if (InReach && name != null && IsBackpack(__instance))
				{
					__result += InChests(name, quality, matchWorldLevel);
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "HaveItem", new Type[]
		{
			typeof(string),
			typeof(bool)
		})]
		[Serves(new Type[]
		{
			typeof(NearbyCrafting),
			typeof(StationRefill)
		})]
		private static class HaveInChests
		{
			private static void Postfix(Inventory __instance, string name, bool matchWorldLevel, ref bool __result)
			{
				if (!__result && InReach && name != null && IsBackpack(__instance))
				{
					__result = InChests(name, -1, matchWorldLevel) > 0;
				}
			}
		}

		[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
		{
			typeof(string),
			typeof(int),
			typeof(int),
			typeof(bool)
		})]
		[Serves(new Type[]
		{
			typeof(NearbyCrafting),
			typeof(StationRefill)
		})]
		private static class TakeFromChests
		{
			private static void Prefix(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased)
			{
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				if (!InReach || name == null || !IsBackpack(__instance))
				{
					return;
				}
				int num = Carried(__instance, name, itemQuality, worldLevelBased);
				if (amount <= num)
				{
					return;
				}
				int num2 = amount - num;
				amount = num;
				foreach (Container item in new List<Container>(Find(((Component)Player.m_localPlayer).transform.position, ReachRange)))
				{
					if (num2 <= 0)
					{
						break;
					}
					Inventory inventory = item.GetInventory();
					if (inventory.CountItems(name, itemQuality, worldLevelBased) > 0 && Claim(item))
					{
						int num3 = Mathf.Min(num2, inventory.CountItems(name, itemQuality, worldLevelBased));
						if (num3 > 0)
						{
							inventory.RemoveItem(name, num3, itemQuality, worldLevelBased);
							num2 -= num3;
						}
					}
				}
				counts.Clear();
			}
		}

		private readonly struct CountKey : IEquatable<CountKey>
		{
			private readonly string name;

			private readonly int quality;

			private readonly bool matchWorldLevel;

			public CountKey(string name, int quality, bool matchWorldLevel)
			{
				this.name = name;
				this.quality = quality;
				this.matchWorldLevel = matchWorldLevel;
			}

			public bool Equals(CountKey other)
			{
				if (quality == other.quality && matchWorldLevel == other.matchWorldLevel)
				{
					return string.Equals(name, other.name, StringComparison.Ordinal);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is CountKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (((name.GetHashCode() * 397) ^ quality) * 397) ^ (matchWorldLevel ? 1 : 0);
			}
		}

		[HarmonyPatch(typeof(Container), "Awake")]
		[Serves(new Type[]
		{
			typeof(QuickStack),
			typeof(StationRefill),
			typeof(NearbyCrafting)
		})]
		[LoadHook]
		private static class Register
		{
			private static void Postfix(Container __instance)
			{
				if (__instance.m_inventory != null)
				{
					Registry.Add(new Entry
					{
						Container = __instance,
						Piece = ((Component)__instance).GetComponentInParent<Piece>(),
						Tombstone = ((Object)(object)((Component)__instance).GetComponent<TombStone>() != (Object)null)
					});
				}
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		[Serves(new Type[]
		{
			typeof(QuickStack),
			typeof(StationRefill),
			typeof(NearbyCrafting)
		}, Optional = true)]
		private static class HoverText
		{
			private static void Prepare()
			{
				PanelButtons.Add(NearbyUse, PanelButtons.Spot.TakeAll, ShowsNearbyUse, RefreshNearbyUse);
			}

			private static void Postfix(Container __instance, ref string __result)
			{
				if (AnyTweakOn && IsExcluded(__instance))
				{
					__result = __result + "\n<color=#a0a0a0>" + Localization.instance.Localize("$omp_nearby_off") + "</color>";
				}
			}
		}

		private static readonly int ExcludedHash = StringExtensionMethods.GetStableHashCode("OMP_NoNearbyUse");

		private static readonly List<Entry> Registry = new List<Entry>();

		private static readonly List<Container> Found = new List<Container>();

		private static int reachDepth;

		private static readonly Dictionary<CountKey, int> counts = new Dictionary<CountKey, int>();

		private static int countsFrame = -1;

		private static readonly PanelButtons.TextButton NearbyUse = new PanelButtons.TextButton("OMP_NearbyUse", new UnityAction(Toggle));

		internal static bool AnyTweakOn => Patcher.AnyServedOn(typeof(Register));

		private static bool InReach => reachDepth > 0;

		private static float ReachRange => SharedSettings.ChestRange.Value;

		internal static List<Container> Find(Vector3 origin)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Find(origin, SharedSettings.ChestRange.Value);
		}

		internal static List<Container> Find(Vector3 origin, float radius)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			Found.Clear();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return Found;
			}
			long playerID = localPlayer.GetPlayerID();
			float num = radius * radius;
			for (int num2 = Registry.Count - 1; num2 >= 0; num2--)
			{
				Entry entry = Registry[num2];
				if ((Object)(object)entry.Container == (Object)null)
				{
					Registry.RemoveAt(num2);
				}
				else
				{
					Vector3 val = ((Component)entry.Container).transform.position - origin;
					if (!(((Vector3)(ref val)).sqrMagnitude > num) && IsInReach(entry, playerID))
					{
						Found.Add(entry.Container);
					}
				}
			}
			Found.Sort(delegate(Container a, Container b)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: 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)
				Vector3 val2 = ((Component)a).transform.position - origin;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				val2 = ((Component)b).transform.position - origin;
				return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
			});
			return Found;
		}

		private static bool IsInReach(Entry entry, long playerId)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Invalid comparison between Unknown and I4
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			Container container = entry.Container;
			if (!Eligible(entry) || container.m_inventory == null)
			{
				return false;
			}
			ZNetView nview = container.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			if (nview.GetZDO().GetBool(ExcludedHash, false))
			{
				return false;
			}
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_currentContainer == (Object)(object)container))
			{
				if (container.IsInUse() || nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1)
				{
					return false;
				}
				if ((Object)(object)container.m_wagon != (Object)null && container.m_wagon.InUse())
				{
					return false;
				}
			}
			if ((int)container.m_privacy != 2 && (Object)(object)container.m_piece == (Object)null)
			{
				return false;
			}
			if (!container.CheckAccess(playerId))
			{
				return false;
			}
			if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
			{
				return false;
			}
			return true;
		}

		internal static bool Claim(Container chest)
		{
			if ((Object)(object)chest == (Object)null)
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			Entry entry = Registry.Find((Entry e) => (Object)(object)e.Container == (Object)(object)chest);
			if (entry == null || !IsInReach(entry, localPlayer.GetPlayerID()))
			{
				return false;
			}
			ZNetView nview = chest.m_nview;
			chest.Load();
			if (!nview.IsOwner())
			{
				nview.ClaimOwnership();
			}
			return nview.IsOwner();
		}

		private static bool Eligible(Container chest)
		{
			return Eligible(Registry.Find((Entry e) => (Object)(object)e.Container == (Object)(object)chest));
		}

		private static bool Eligible(Entry entry)
		{
			if (entry != null && !entry.Tombstone && (Object)(object)entry.Piece != (Object)null)
			{
				return entry.Piece.IsPlacedByPlayer();
			}
			return false;
		}

		internal static bool IsExcluded(Container chest)
		{
			ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return val.GetZDO().GetBool(ExcludedHash, false);
			}
			return false;
		}

		private static void SetExcluded(Container chest, bool excluded)
		{
			ZNetView val = (((Object)(object)chest != (Object)null) ? chest.m_nview : null);
			if (!((Object)(object)val == (Object)null) && val.IsValid())
			{
				if (!val.IsOwner())
				{
					val.ClaimOwnership();
				}
				if (val.IsOwner())
				{
					val.GetZDO().Set(ExcludedHash, excluded);
				}
			}
		}

		internal static bool EnterReach(Tweak tweak, Humanoid user)
		{
			if (!tweak.On || (Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			reachDepth++;
			return true;
		}

		internal static void LeaveReach(bool entered)
		{
			if (entered && reachDepth > 0)
			{
				reachDepth--;
			}
		}

		private static bool IsBackpack(Inventory inventory)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				return inventory == ((Humanoid)localPlayer).GetInventory();
			}
			return false;
		}

		internal static int Carried(Inventory inventory, string name, int quality, bool matchWorldLevel)
		{
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_shared.m_name == name && (quality < 0 || allItem.m_quality == quality) && (!matchWorldLevel || allItem.m_worldLevel >= Game.m_worldLevel))
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		private static int InChests(string name, int quality, bool matchWorldLevel)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (Time.frameCount != countsFrame)
			{
				counts.Clear();
				countsFrame = Time.frameCount;
			}
			CountKey key = new CountKey(name, quality, matchWorldLevel);
			if (counts.TryGetValue(key, out var value))
			{
				return value;
			}
			foreach (Container item in Find(((Component)Player.m_localPlayer).transform.position, ReachRange))
			{
				value += item.GetInventory().CountItems(name, quality, matchWorldLevel);
			}
			counts[key] = value;
			return value;
		}

		private static bool ShowsNearbyUse(InventoryGui gui)
		{
			Container currentContainer = gui.m_currentContainer;
			if ((Object)(object)currentContainer != (Object)null && (Object)(object)gui.m_container != (Object)null && ((Component)gui.m_container).gameObject.activeSelf && AnyTweakOn)
			{
				return Eligible(currentContainer);
			}
			return false;
		}

		private static void RefreshNearbyUse(InventoryGui gui)
		{
			NearbyUse.SetLabel(IsExcluded(gui.m_currentContainer) ? "$omp_nearby_off" : "$omp_nearby_on");
			NearbyUse.SetTooltip("$omp_nearby_topic", "$omp_nearby_tip");
		}

		private static void Toggle()
		{
			InventoryGui instance = InventoryGui.instance;
			Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null);
			if ((Object)(object)val != (Object)null)
			{
				SetExcluded(val, !IsExcluded(val));
			}
		}
	}
	[BepInPlugin("rauschekuh.odinsreach", "Odin's Reach", "0.1.0")]
	public class OdinsReachPlugin : BaseUnityPlugin
	{
		public const string GUID = "rauschekuh.odinsreach";

		public const string NAME = "Odin's Reach";

		public const string VERSION = "0.1.0";

		private static readonly Tweak[] Tweaks = new Tweak[5]
		{
			NearbyCrafting.Instance,
			QuickStack.Instance,
			StationRefill.Instance,
			ChestButtons.Instance,
			InventoryButtons.Instance
		};

		private void Awake()
		{
			TweakHost.Start((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config, "rauschekuh.odinsreach", Tweaks, SharedSettings.Bind);
		}
	}
	internal static class PanelButtons
	{
		internal enum Column
		{
			Inventory,
			Chest
		}

		internal enum Spot
		{
			TakeAll,
			StackAll
		}

		private sealed class IconEntry
		{
			internal Column Column;

			internal int Order;

			internal string Name;

			internal string Icon;

			internal string Title;

			internal Func<string> Tooltip;

			internal UnityAction OnClick;

			internal Func<InventoryGui, bool> Visible;

			internal Button Button;

			internal UITooltip Tip;
		}

		private sealed class TextEntry
		{
			internal TextButton Button;

			internal Spot Spot;

			internal Func<InventoryGui, bool> Visible;

			internal Action<InventoryGui> Refresh;
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
		[Serves(new Type[]
		{
			typeof(ChestButtons),
			typeof(InventoryButtons)
		})]
		private static class LayOut
		{
			private static void Postfix(InventoryGui __instance)
			{
				Arrange(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
		[Serves(new Type[]
		{
			typeof(QuickStack),
			typeof(StationRefill),
			typeof(NearbyCrafting)
		}, Optional = true)]
		private static class LayOutText
		{
			private static void Postfix(InventoryGui __instance)
			{
				Arrange(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnDestroy")]
		[Serves(new Type[]
		{
			typeof(ChestButtons),
			typeof(InventoryButtons)
		})]
		private static class ScreenDestroyed
		{
			private static void Postfix()
			{
				foreach (IconEntry iconButton in iconButtons)
				{
					iconButton.Button = null;
				}
				foreach (TextEntry textButton in textButtons)
				{
					textButton.Button.Forget();
				}
				vanillaHidden = false;
			}
		}

		internal sealed class TextButton
		{
			private const float Margin = 16f;

			private readonly string name;

			private readonly UnityAction onClick;

			private Button button;

			private UITooltip tip;

			private string label;

			private string tooltip;

			private Component labelText;

			private PropertyInfo labelWidth;

			internal TextButton(string name, UnityAction onClick)
			{
				this.name = name;
				this.onClick = onClick;
			}

			internal bool Show(InventoryGui gui)
			{
				if ((Object)(object)button == (Object)null && !Create(gui))
				{
					return false;
				}
				((Component)button).gameObject.SetActive(true);
				return true;
			}

			internal void Hide()
			{
				if ((Object)(object)button != (Object)null)
				{
					((Component)button).gameObject.SetActive(false);
				}
			}

			internal void Forget()
			{
				button = null;
			}

			internal void Place(InventoryGui gui, Button at, bool keepLeft, int slot)
			{
				//IL_001c: 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_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_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Expected O, but got Unknown
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0106: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: 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_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_014e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				RectTransform val = ((!((Object)(object)gui.m_takeAllButton != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)gui.m_takeAllButton).transform));
				if (!((Object)(object)val == (Object)null))
				{
					Rect rect = val.rect;
					float height = ((Rect)(ref rect)).height;
					rect = val.rect;
					float num = Mathf.Max(((Rect)(ref rect)).width, LabelWidth() + 32f);
					RectTransform val2 = (RectTransform)((Component)button).transform;
					val2.sizeDelta = new Vector2(num, height);
					RectTransform val3 = ((!((Object)(object)at != (Object)null)) ? ((RectTransform)null) : ((RectTransform)((Component)at).transform));
					if ((Object)(object)val3 == (Object)null)
					{
						RectTransform container = gui.m_container;
						Pin(val2, new Vector2(ColumnLeft(container) + num * 0.5f, ColumnTop(container) - height * 0.5f - (float)slot * (height + 6f)));
						return;
					}
					val2.anchorMin = val3.anchorMin;
					val2.anchorMax = val3.anchorMax;
					val2.pivot = val3.pivot;
					rect = val3.rect;
					float num2 = num - ((Rect)(ref rect)).width;
					val2.anchoredPosition = val3.anchoredPosition + new Vector2(keepLeft ? (num2 * (1f - val3.pivot.x)) : ((0f - num2) * val3.pivot.x), 0f);
				}
			}

			private float LabelWidth()
			{
				if ((Object)(object)labelText == (Object)null)
				{
					Transform val = ((Component)button).transform.Find("Text");
					if ((Object)(object)val == (Object)null)
					{
						return 0f;
					}
					Component[] components = ((Component)val).GetComponents<Component>();
					foreach (Component val2 in components)
					{
						PropertyInfo property = ((object)val2).GetType().GetProperty("preferredWidth", typeof(float));
						if (property != null && property.CanRead)
						{
							labelText = val2;
							labelWidth = property;
							break;
						}
					}
				}
				if (!((Object)(object)labelText != (Object)null))
				{
					return 0f;
				}
				return (float)labelWidth.GetValue(labelText, null);
			}

			private bool Create(InventoryGui gui)
			{
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Expected O, but got Unknown
				Button takeAllButton = gui.m_takeAllButton;
				if ((Object)(object)takeAllButton == (Object)null)
				{
					return false;
				}
				GameObject val = Object.Instantiate<GameObject>(((Component)takeAllButton).gameObject, ((Component)takeAllButton).transform.parent);
				((Object)val).name = name;
				button = val.GetComponent<Button>();
				if ((Object)(object)button == (Object)null)
				{
					Object.Destroy((Object)(object)val);
					return false;
				}
				button.onClick = new ButtonClickedEvent();
				((UnityEvent)button.onClick).AddListener(onClick);
				val.transform.SetSiblingIndex(((Component)takeAllButton).transform.GetSiblingIndex());
				tip = Tooltip(gui, val);
				label = null;
				tooltip = null;
				labelText = null;
				labelWidth = null;
				return true;
			}

			internal void SetLabel(string text, params string[] words)
			{
				if (Localization.instance != null)
				{
					text = Localization.instance.Localize(text, words);
				}
				if (text == label)
				{
					return;
				}
				label = text;
				Component[] componentsInChildren = ((Component)button).GetComponentsInChildren<Component>(true);
				foreach (Component val in componentsInChildren)
				{
					PropertyInfo property = ((object)val).GetType().GetProperty("text", typeof(string));
					if (property != null && property.CanWrite)
					{
						property.SetValue(val, text, null);
					}
				}
			}

			internal void SetTooltip(string topic, string text)
			{
				if (!(text == tooltip) && !((Object)(object)tip == (Object)null))
				{
					tooltip = text;
					tip.m_topic = topic;
					tip.m_text = text;
				}
			}
		}

		private const float Gap = 6f;

		private static readonly List<IconEntry> iconButtons = new List<IconEntry>();

		private static readonly List<TextEntry> textButtons = new List<TextEntry>();

		private static bool vanillaHidden;

		private static int arrangedFrame = -1;

		internal static void Add(Column column, int order, string name, string icon, string title, string tooltip, UnityAction onClick, Func<InventoryGui, bool> visible)
		{
			Add(column, order, name, icon, title, () => tooltip, onClick, visible);
		}

		internal static void Add(Column column, int order, string name, string icon, string title, Func<string> tooltip, UnityAction onClick, Func<InventoryGui, bool> visible)
		{
			iconButtons.Add(new IconEntry
			{
				Column = column,
				Order = order,
				Name = name,
				Icon = icon,
				Title = title,
				Tooltip = tooltip,
				OnClick = onClick,
				Visible = visible
			});
			iconButtons.Sort((IconEntry a, IconEntry b) => (a.Column == b.Column) ? a.Order.CompareTo(b.Order) : a.Column.CompareTo(b.Column));
		}

		internal static void Add(TextButton button, Spot spot, Func<InventoryGui, bool> visible, Action<InventoryGui> refresh)
		{
			if (!textButtons.Exists((TextEntry e) => e.Button == button))
			{
				textButtons.Add(new TextEntry
				{
					Button = button,
					Spot = spot,
					Visible = visible,
					Refresh = refresh
				});
				textButtons.Sort((TextEntry a, TextEntry b) => a.Spot.CompareTo(b.Spot));
			}
		}

		private static float Size(InventoryGui gui)
		{
			//IL_0028: 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)
			Button val = (((Object)(object)gui != (Object)null) ? gui.m_takeAllButton : null);
			if (!((Object)(object)val != (Object)null))
			{
				return 32f;
			}
			Rect rect = ((RectTransform)((Component)val).transform).rect;
			return ((Rect)(ref rect)).height;
		}

		private static Button Create(InventoryGui gui, Transform parent, string name, string icon, string title, string tooltip, UnityAction onClick)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0080: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			Button val = (((Object)(object)gui != (Object)null) ? gui.m_takeAllButton : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
			((Object)val2).name = "OMP_" + name;
			Button component = val2.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener(onClick);
			((Selectable)component).interactable = true;
			float num = Size(gui);
			((RectTransform)val2.transform).sizeDelta = new Vector2(num, num);
			AddIcon(val2, icon, BlankLabel(val2), num);
			UITooltip val3 = Tooltip(gui, val2);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.m_topic = title;
				val3.m_text = tooltip;
			}
			val2.SetActive(false);
			return component;
		}

		internal static bool Closing(InventoryGui gui)
		{
			Animator val = (((Object)(object)gui != (Object)null) ? gui.m_animator : null);
			if ((Object)(object)val != (Object)null)
			{
				return !val.GetBool("visible");
			}
			return false;
		}

		private static void Arrange(InventoryGui gui)
		{
			if (Closing(gui) || arrangedFrame == Time.frameCount)
			{
				return;
			}
			arrangedFrame = Time.frameCount;
			bool flag = false;
			foreach (IconEntry iconButton in iconButtons)
			{
				bool flag2 = iconButton.Visible(gui) && ((Object)(object)iconButton.Button != (Object)null || Build(gui, iconButton));
				if ((Object)(object)iconButton.Button != (Object)null)
				{
					((Component)iconButton.Button).gameObject.SetActive(flag2);
				}
				if (flag2 && (Object)(object)iconButton.Tip != (Object)null)
				{
					string text = iconButton.Tooltip();
					if ((object)iconButton.Tip.m_text != text)
					{
						iconButton.Tip.m_text = text;
					}
				}
				flag |= flag2 && iconButton.Column == Column.Chest;
			}
			SetVanilla(gui, !flag);
			int num = LayoutChestColumn(gui);
			LayoutInventoryColumn(gui);
			foreach (TextEntry textButton in textButtons)
			{
				if (!textButton.Visible(gui) || !textButton.Button.Show(gui))
				{
					textButton.Button.Hide();
					continue;
				}
				textButton.Refresh(gui);
				Button val = ((!vanillaHidden) ? null : ((textButton.Spot == Spot.TakeAll) ? gui.m_takeAllButton : gui.m_stackAllButton));
				textButton.Button.Place(gui, val, textButton.Spot == Spot.TakeAll, num);
				if ((Object)(object)val == (Object)null)
				{
					num++;
				}
			}
		}

		private static bool Build(InventoryGui gui, IconEntry entry)
		{
			Transform val = (Transform)(object)((entry.Column == Column.Chest) ? gui.m_container : gui.m_player);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			entry.Button = Create(gui, val, entry.Name, entry.Icon, entry.Title, entry.Tooltip(), entry.OnClick);
			if ((Object)(object)entry.Button == (Object)null)
			{
				return false;
			}
			entry.Tip = ((Component)entry.Button).GetComponent<UITooltip>();
			return true;
		}

		private static void SetVanilla(InventoryGui gui, bool active)
		{
			if (active != !vanillaHidden)
			{
				vanillaHidden = !active;
				if ((Object)(object)gui.m_takeAllButton != (Object)null)
				{
					((Component)gui.m_takeAllButton).gameObject.SetActive(active);
				}
				if ((Object)(object)gui.m_stackAllButton != (Object)null)
				{
					((Component)gui.m_stackAllButton).gameObject.SetActive(active);
				}
			}
		}

		private static void Pin(RectTransform rect, Vector2 center)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.zero;
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.anchoredPosition = center;
		}

		private static Vector2 Overhang(RectTransform panel)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = ((Transform)panel).Find("Bkg");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val != (Object)null && val.anchorMin == Vector2.zero && val.anchorMax == Vector2.one)
			{
				return Vector2.Max(Vector2.zero, val.sizeDelta * 0.5f);
			}
			return new Vector2(10f, 10f);
		}

		private static float ColumnLeft(RectTransform panel)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = panel.rect;
			return ((Rect)(ref rect)).width + Overhang(panel).x + 6f;
		}

		private static float ColumnTop(RectTransform panel)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = panel.rect;
			return ((Rect)(ref rect)).height + Overhang(panel).y;
		}

		private static RectTransform Box(InventoryGui gui, string field, RectTransform panel, string name)
		{
			FieldInfo field2 = typeof(InventoryGui).GetField(field, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			Component val = (Component)((field2 != null) ? /*isinst with value type is only supported in some contexts*/: null);
			RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val2 == (Object)null && (Object)(object)panel != (Object)null)
			{
				Transform obj = ((Transform)panel).Find(name);
				val2 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			}
			return val2;
		}

		private static Rect InPanel(RectTransform panel, RectTransform rect)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_004c: 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_0054: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0090: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			Rect rect2 = rect.rect;
			Vector3 val = ((Transform)panel).InverseTransformPoint(((Transform)rect).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect2)).min)));
			rect2 = rect.rect;
			Vector3 val2 = ((Transform)panel).InverseTransformPoint(((Transform)rect).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect2)).max)));
			Vector2 pivot = panel.pivot;
			rect2 = panel.rect;
			Vector2 val3 = Vector2.Scale(pivot, ((Rect)(ref rect2)).size);
			return Rect.MinMaxRect(Mathf.Min(val.x, val2.x) + val3.x, Mathf.Min(val.y, val2.y) + val3.y, Mathf.Max(val.x, val2.x) + val3.x, Mathf.Max(val.y, val2.y) + val3.y);
		}

		private static bool Showing(IconEntry entry, Column column)
		{
			if (entry.Column == column && (Object)(object)entry.Button != (Object)null)
			{
				return ((Component)entry.Button).gameObject.activeSelf;
			}
			return false;
		}

		private static void LayoutInventoryColumn(InventoryGui gui)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			RectTransform val = (((Object)(object)gui != (Object)null) ? gui.m_player : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float num = Size(gui);
			int num2 = 0;
			foreach (IconEntry iconButton in iconButtons)
			{
				if (Showing(iconButton, Column.Inventory))
				{
					num2++;
				}
			}
			if (num2 == 0)
			{
				return;
			}
			RectTransform val2 = Box(gui, "m_armor", val, "Armor");
			RectTransform val3 = Box(gui, "m_weight", val, "Weight");
			Rect val4;
			float num3;
			if (!((Object)(object)val2 != (Object)null))
			{
				val4 = val.rect;
				num3 = ((Rect)(ref val4)).height;
			}
			else
			{
				val4 = InPanel(val, val2);
				num3 = ((Rect)(ref val4)).yMin;
			}
			float num4;
			if (!((Object)(object)val3 != (Object)null))
			{
				num4 = 0f;
			}
			else
			{
				val4 = InPanel(val, val3);
				num4 = ((Rect)(ref val4)).yMax;
			}
			float num5 = num4;
			float num6 = (float)num2 * num + (float)(num2 - 1) * 6f;
			float num7 = ColumnLeft(val) + num * 0.5f;
			float num8 = (num3 + num5) * 0.5f + num6 * 0.5f - num * 0.5f;
			foreach (IconEntry iconButton2 in iconButtons)
			{
				if (Showing(iconButton2, Column.Inventory))
				{
					RectTransform val5 = (RectTransform)((Component)iconButton2.Button).transform;
					val5.sizeDelta = new Vector2(num, num);
					Pin(val5, new Vector2(num7, num8));
					num8 -= num + 6f;
				}
			}
		}

		private static int LayoutChestColumn(InventoryGui gui)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_0091: Expected O, but got Unknown
			RectTransform val = (((Object)(object)gui != (Object)null) ? gui.m_container : null);
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			float num = Size(gui);
			float num2 = ColumnLeft(val) + num * 0.5f;
			float num3 = ColumnTop(val) - num * 0.5f;
			int num4 = 0;
			foreach (IconEntry iconButton in iconButtons)
			{
				if (Showing(iconButton, Column.Chest))
				{
					RectTransform val2 = (RectTransform)((Component)iconButton.Button).transform;
					val2.sizeDelta = new Vector2(num, num);
					Pin(val2, new Vector2(num2, num3));
					num3 -= num + 6f;
					num4++;
				}
			}
			return num4;
		}

		private static Color BlankLabel(GameObject go)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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)
			Color result = Color.white;
			Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				PropertyInfo property = ((object)val).GetType().GetProperty("text", typeof(string));
				if (!(property == null) && property.CanWrite)
				{
					Graphic val2 = (Graphic)(object)((val is Graphic) ? val : null);
					if (val2 != null)
					{
						result = val2.color;
					}
					property.SetValue(val, "", null);
				}
			}
			return result;
		}

		private static void AddIcon(GameObject go, string icon, Color tint, float size)
		{
			//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_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val.transform.SetParent(go.transform, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			float num = size * 0.2f;
			val2.offsetMin = new Vector2(num, num);
			val2.offsetMax = new Vector2(0f - num, 0f - num);
			Image component = val.GetComponent<Image>();
			component.sprite = UiAssets.Icon(icon);
			((Graphic)component).color = tint;
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = false;
			((Behaviour)component).enabled = (Object)(object)component.sprite != (Object)null;
		}

		internal static UITooltip Tooltip(InventoryGui gui, GameObject go)
		{
			UITooltip val = go.GetComponent<UITooltip>();
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = UiAssets.TooltipPrefab(gui);
				if ((Object)(object)val2 == (Object)null)
				{
					return null;
				}
				val = go.AddComponent<UITooltip>();
				val.m_tooltipPrefab = val2;
			}
			else if ((Object)(object)val.m_tooltipPrefab == (Object)null)
			{
				val.m_tooltipPrefab = UiAssets.TooltipPrefab(gui);
			}
			return val;
		}
	}
	internal static class SharedSettings
	{
		internal const string Section = "General";

		internal static ConfigEntry<float> ChestRange;

		internal static ConfigEntry<bool> KeepHotbar;

		internal static void Bind(ConfigFile config)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			ChestRange = config.Bind<float>("General", "ChestRange", 20f, new ConfigDescription("How far from you a chest may stand, in metres, for nearby crafting, quick stack and station refill to use it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			KeepHotbar = config.Bind<bool>("General", "KeepHotbar", true, "Quick stack, Place all, Fill the chest and Sort leave the hotbar row alone. Off lets them move it too.");
		}

		internal static bool OnKeptHotbar(ItemData item)
		{
			if (KeepHotbar.Value)
			{
				return item.m_gridPos.y == 0;
			}
			return false;
		}
	}
	internal static class Stash
	{
		internal static bool StaysPut(Player player, ItemData item)
		{
			if (!item.m_equipped && !((Humanoid)player).IsItemEquiped(item))
			{
				return QuickStack.IsFavorite(item);
			}
			return true;
		}

		internal static bool MayLeave(Player player, ItemData item)
		{
			if (!StaysPut(player, item))
			{
				return !SharedSettings.OnKeptHotbar(item);
			}
			return false;
		}

		internal static bool Takes(Inventory chest, string marks, string itemName)
		{
			if (!chest.ContainsItemByName(itemName))
			{
				return ChestFavorites.Marked(marks, itemName);
			}
			return true;
		}

		internal static int Move(ItemData item, Inventory from, Inventory to)
		{
			if (!to.HaveEmptySlot() && to.FindFreeStackSpace(item.m_shared.m_name, (float)item.m_worldLevel) <= 0)
			{
				return 0;
			}
			int stack = item.m_stack;
			if (to.AddItem(item))
			{
				from.RemoveItem(item);
				return stack;
			}
			int num = stack - item.m_stack;
			if (num > 0)
			{
				from.Changed(false, false);
			}
			return num;
		}

		internal static int TopUp(Inventory target, Inventory source, Func<ItemData, bool> fills = null)
		{
			int num = 0;
			foreach (ItemData item in new List<ItemData>(source.GetAllItems()))
			{
				if (item.m_shared.m_maxStackSize <= 1)
				{
					continue;
				}
				int stack = item.m_stack;
				foreach (ItemData allItem in target.GetAllItems())
				{
					if (item.m_stack <= 0)
					{
						break;
					}
					if (InventorySorter.Merges(allItem, item) && (fills == null || fills(allItem)))
					{
						int num2 = Mathf.Min(allItem.m_shared.m_maxStackSize - allItem.m_stack, item.m_stack);
						allItem.m_stack += num2;
						item.m_stack -= num2;
					}
				}
				if (item.m_stack != stack)
				{
					num += stack - item.m_stack;
					if (item.m_stack <= 0)
					{
						source.RemoveItem(item);
					}
				}
			}
			if (num > 0)
			{
				target.Changed(false, false);
				source.Changed(false, false);
			}
			return num;
		}
	}
	internal sealed class ChestButtons : Tweak
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__FillInventory;

			public static Func<InventoryGui, bool> <1>__ChestShown;

			public static UnityAction <2>__TakeAll;

			public static UnityAction <3>__PlaceAll;

			public static UnityAction <4>__FillChest;

			public static UnityAction <5>__SortChest;
		}

		internal static readonly ChestButtons Instance = new ChestButtons();

		internal override string Section => "Chest Buttons";

		protected override string Summary => "Replaces the chest panel's Take all and Stack all with icon buttons beside the panels: fill your stacks from the chest in the column beside the inventory; take all, place all, fill the chest's stacks from your backpack and sort the chest in a column down the side of the chest.";

		private ChestButtons()
		{
			//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_0051: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_018a: 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_0195: Expected O, but got Unknown
			Func<string> tooltip = () => QuickStack.Instance.FillInventoryTip();
			object obj = <>O.<0>__FillInventory;
			if (obj == null)
			{
				UnityAction val = FillInventory;
				<>O.<0>__FillInventory = val;
				obj = (object)val;
			}
			PanelButtons.Add(PanelButtons.Column.Inventory, 0, "FillInventory", "fill_inventory", "$omp_fill_inventory", tooltip, (UnityAction)obj, ChestShown);
			object obj2 = <>O.<2>__TakeAll;
			if (obj2 == null)
			{
				UnityAction val2 = TakeAll;
				<>O.<2>__TakeAll = val2;
				obj2 = (object)val2;
			}
			PanelButtons.Add(PanelButtons.Column.Chest, 0, "TakeAll", "take_all", "$omp_take_all", "$omp_take_all_tip", (UnityAction)obj2, ChestShown);
			object obj3 = <>O.<3>__PlaceAll;
			if (obj3 == null)
			{
				UnityAction val3 = PlaceAll;
				<>O.<3>__PlaceAll = val3;
				obj3 = (object)val3;
			}
			PanelButtons.Add(PanelButtons.Column.Chest, 1, "PlaceAll", "place_all", "$omp_place_all", "$omp_place_all_tip", (UnityAction)obj3, ChestShown);
			object obj4 = <>O.<4>__FillChest;
			if (obj4 == null)
			{
				UnityAction val4 = FillChest;
				<>O.<4>__FillChest = val4;
				obj4 = (object)val4;
			}
			PanelButtons.Add(PanelButtons.Column.Chest, 2, "FillChest", "fill_chest", "$omp_fill_chest", "$omp_fill_chest_tip", (UnityAction)obj4, ChestShown);
			object obj5 = <>O.<5>__SortChest;
			if (obj5 == null)
			{
				UnityAction val5 = SortChest;
				<>O.<5>__SortChest = val5;
				obj5 = (object)val5;
			}
			PanelButtons.Add(PanelButtons.Column.Chest, 3, "Sort", "sort", "$omp_sort_chest", "$omp_sort_chest_tip", (UnityAction)obj5, ChestShown);
		}

		private static bool ChestShown(InventoryGui gui)
		{
			RectTransform container = gui.m_container;
			if (Instance.On && (Object)(object)gui.m_currentContainer != (Object)null && (Object)(object)container != (Object)null)
			{
				return ((Component)container).gameObject.activeSelf;
			}
			return false;
		}

		private static InventoryGui Ready(out Player player, out Container chest)
		{
			InventoryGui instance = InventoryGui.instance;
			player = Player.m_localPlayer;
			chest = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null);
			if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null || ((Character)player).IsTeleporting() || (Object)(object)chest == (Object)null || !chest.IsOwner())
			{
				return null;
			}
			return instance;
		}

		private static void TakeAll()
		{
			Player player;
			Container chest;
			InventoryGui val = Ready(out player, out chest);
			if ((Object)(object)val != (Object)null)
			{
				val.OnTakeAll();
			}
		}

		private static void FillInventory()
		{
			Player player;
			Container chest;
			InventoryGui val = Ready(out player, out chest);
			if (!((Object)(object)val == (Object)null))
			{
				val.SetupDragItem((ItemData)null, (Inventory)null, 1);
				int moved = Stash.TopUp(((Humanoid)player).GetInventory(), chest.GetInventory());
				Report(val, player, moved, "$omp_took", "$omp_took_none");
			}
		}

		private static void FillChest()
		{
			Player player;
			Container chest;
			InventoryGui val = Ready(out player, out chest);
			if (!((Object)(object)val == (Object)null))
			{
				val.SetupDragItem((ItemData)null, (Inventory)null, 1);
				int moved = MoveToChest(player, chest, onlyExisting: true);
				Report(val, player, moved, "$omp_stacked_chest", "$omp_stacked_chest_none");
			}
		}

		private static void PlaceAll()
		{
			Player player;
			Container chest;
			InventoryGui val = Ready(out player, out chest);
			if (!((Object)(object)val == (Object)null))
			{
				val.SetupDragItem((ItemData)null, (Inventory)null, 1);
				int moved = MoveToChest(player, chest, onlyExisting: false);
				Report(val, player, moved, "$omp_placed", "$omp_placed_none");
			}
		}

		private static void SortChest()
		{
			Player player;
			Container chest;
			InventoryGui val = Ready(out player, out chest);
			if (!((Object)(object)val == (Object)null))
			{
				val.SetupDragItem((ItemData)null, (Inventory)null, 1);
				InventorySorter.Sort(chest.GetInventory(), 0, null);
			}
		}

		private static void Report(InventoryGui gui, Player player, int moved, string done, string nothing)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			if (moved > 0)
			{
				gui.m_moveItemEffects.Create(((Component)gui).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			((Character)player).Message((MessageType)2, (moved > 0) ? Localization.instance.Localize(done, new string[1] { moved.ToString() }) : nothing, 0, (Sprite)null, false);
		}

		private static int MoveToChest(Player player, Container container, bool onlyExisting)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			Inventory inventory2 = container.GetInventory();
			string marks = ChestFavorites.Marks(container);
			int num = 0;
			foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
			{
				if (Stash.MayLeave(player, item) && (!onlyExisting || Stash.Takes(inventory2, marks, item.m_shared.m_name)))
				{
					num += Stash.Move(item, inventory, inventory2);
				}
			}
			return num;
		}
	}
	internal sealed class InventoryButtons : Tweak
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__StackNearby;

			public static UnityAction <1>__SortInventory;
		}

		internal static readonly InventoryButtons Instance = new InventoryButtons();

		internal override string Section => "Inventory Buttons";

		protected override string Summary => "Two icon buttons beside the inventory panel: stack nearby (quick stacking by click, while Quick Stack is on and no chest is open) and sort.";

		private InventoryButtons()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			Func<string> tooltip = () => QuickStack.Instance.StackNearbyTip();
			object obj = <>O.<0>__StackNearby;
			if (obj == null)
			{
				UnityAction val = StackNearby;
				<>O.<0>__StackNearby = val;
				obj = (object)val;
			}
			PanelButtons.Add(PanelButtons.Column.Inventory, 10, "StackNearby", "stack_nearby", "$omp_stack_nearby", tooltip, (UnityAction)obj, (InventoryGui gui) => Instance.On && QuickStack.Instance.On && (Object)(object)gui.m_currentContainer == (Object)null);
			object obj2 = <>O.<1>__SortInventory;
			if (obj2 == null)
			{
				UnityAction val2 = SortInventory;
				<>O.<1>__SortInventory = val2;
				obj2 = (object)val2;
			}
			PanelButtons.Add(PanelButtons.Column.Inventory, 11, "SortInventory", "sort", "$omp_sort", "$omp_sort_tip", (UnityAction)obj2, (InventoryGui gui) => Instance.On);
		}

		private static void StackNearby()
		{
			InventoryGui instance = InventoryGui.instance;
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsTeleporting() && QuickStack.Instance.On)
			{
				instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
				QuickStack.Instance.Stack(localPlayer);
			}
		}

		private static void SortInventory()
		{
			InventoryGui instance = InventoryGui.instance;
			Player player = Player.m_localPlayer;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)player == (Object)null) && !((Character)player).IsTeleporting())
			{
				instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
				InventorySorter.Sort(((Humanoid)player).GetInventory(), SharedSettings.KeepHotbar.Value ? 1 : 0, (ItemData item) => Stash.StaysPut(player, item));
			}
		}
	}
	internal sealed class NearbyCrafting : Tweak
	{
		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		private static class RecipeScope
		{
			private static void Prefix(Player __instance, Recipe piece, out bool __state)
			{
				__state = (Object)(object)piece != (Object)null && !piece.m_requireOnlyOneIngredient && Enter(__instance);
			}

			private static void Finalizer(bool __state)
			{
				Leave(__state);
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		private static class BuildScope
		{
			private static void Prefix(Player __instance, out bool __state)
			{
				__state = Enter(__instance);
			}

			private static void Finalizer(bool __state)
			{
				Leave(__state);
			}
		}

		[HarmonyPatch(typeof(Player), "ConsumeResources")]
		private static class SpendScope
		{
			private static void Prefix(Player __instance, out bool __state)
			{
				__state = Enter(__instance);
			}

			private static void Finalizer(bool __state)
			{
				Leave(__state);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
		private static class RowScope
		{
			internal struct State
			{
				public bool Entered;

				public int Carried;
			}

			private static void Prefix(Requirement req, Player player, bool craft, out State __state)
			{
				__state = default(State);
				if (req != null && !((Object)(object)req.m_resItem == (Object)null) && (!craft || !SelectedRecipeTakesAnyOne()))
				{
					__state.Carried = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetInventory().CountItems(req.m_resItem.m_itemData.m_shared.m_name, -1, true) : 0);
					__state.Entered = Enter(player);
				}
			}

			private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier, bool __result, State __state)
			{
				//IL_0149: Unknown result type (might be due to invalid IL or missing references)
				if (!__state.Entered || !__result || (Object)(object)elementRoot == (Object)null)
				{
					return;
				}
				string name = req.m_resItem.m_itemData.m_shared.m_name;
				int num = ((Humanoid)player).GetInventory().CountItems(name, -1, true) - __state.Carried;
				if (num < 0)
				{
					num = 0;
				}
				UITooltip component = ((Component)elementRoot).GetComponent<UITooltip>();
				if ((Object)(object)component != (Object)null)
				{
					Localization instance = Localization.instance;
					component.m_text = instance.Localize(name) + "\n" + instance.Localize("$omp_carried", new string[1] { __state.Carried.ToString() }) + "\n<color=#ffd64d>" + instance.Localize("$omp_from_chests", new string[1] { num.ToString() }) + "</color>";
				}
				int num2 = req.GetAmount(quality) * craftMultiplier;
				if (!(craft ? ZoneSystem.instance.GetGlobalKey((GlobalKeys)25) : ZoneSystem.instance.GetGlobalKey((GlobalKeys)24)) && __state.Carried < num2 && __state.Carried + num >= num2)
				{
					Transform val = elementRoot.Find("res_amount");
					Graphic val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Graphic>() : null);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.color = Palette.ChestYellow;
					}
				}
			}

			private static void Finalizer(State __state)
			{
				Leave(__state.Entered);
			}

			private static bool SelectedRecipeTakesAnyOne()
			{
				InventoryGui instance = InventoryGui.instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe != (Object)null)
				{
					return ((RecipeDataPair)(ref instance.m_selectedRecipe)).Recipe.m_requireOnlyOneIngredient;
				}
				return false;
			}
		}

		internal static readonly NearbyCrafting Instance = new NearbyCrafting();

		internal override string Section => "Nearby Crafting";

		protected override string Summary => "Crafting, upgrading and building take their materials from chests around you (General.ChestRange), without opening them. Only chests placed by a player, and not chests switched off with the Nearby use button in their panel.";

		private NearbyCrafting()
		{
		}

		private static bool Enter(Player player)
		{
			return NearbyChests.EnterReach(Instance, (Humanoid)(object)player);
		}

		private static void Leave(bool entered)
		{
			NearbyChests.LeaveReach(entered);
		}
	}
	internal sealed class QuickStack : Tweak
	{
		[HarmonyPatch(typeof(Player), "Update")]
		private static class Hotkey
		{
			private static void Postfix(Player __instance)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: 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_005c: Unknown result type (might be due to invalid IL or missing references)
				if (Instance.On && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && CanTakeHotkey(__instance) && Hotkeys.Pressed(Instance.hotkey.Value))
				{
					KeyboardShortcut value = Instance.topUpModifier.Value;
					if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && Hotkeys.Held(Instance.topUpModifier.Value))
					{
						Instance.TopUp(__instance);
					}
					else
					{
						Instance.Stack(__instance);
					}
				}
			}

			private static bool CanTakeHotkey(Player player)
			{
				if (((Character)player).TakeInput())
				{
					return true;
				}
				if (InventoryGui.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !UnifiedPopup.IsVisible() && !((Character)player).IsDead())
				{
					return !((Character)player).IsTeleporting();
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "OnLeftDown")]
		private static class ToggleFavorite
		{
			private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: 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_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || __instance.m_inventory == null || !Hotkeys.Held(Instance.favoriteModifier.Value))
				{
					return true;
				}
				bool flag = __instance.m_inventory == ((Humanoid)localPlayer).GetInventory();
				if (flag ? (!Instance.On) : (!ChestFavorites.Used))
				{
					return true;
				}
				Vector2i buttonPos = __instance.GetButtonPos(((Component)clickHandler).gameObject);
				ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y);
				if (itemAt == null)
				{
					return true;
				}
				if (!flag)
				{
					return MarkChest(localPlayer, __instance.m_inventory, itemAt);
				}
				SetFavorite(itemAt, !IsFavorite(itemAt));
				__instance.m_inventory.Changed(false, false);
				return false;
			}

			private static bool MarkChest(Player player, Inventory inventory, ItemData item)
			{
				Container val = ChestFavorites.OpenChest(inventory);
				if ((Object)(object)val == (Object)null)
				{
					((Character)player).Message((MessageType)2, "$omp_favourites_inventory", 0, (Sprite)null, false);
					return false;
				}
				string name = item.m_shared.m_name;
				bool flag = ChestFavorites.Toggle(val, name);
				((Character)player).Message((MessageType)2, Localization.instance.Localize(flag ? "$omp_chest_takes" : "$omp_chest_takes_not", new string[1] { ChestFavorites.Localize(name) }), 0, (Sprite)null, false);
				return false;
			}
		}

		[HarmonyPatch(typeof(Inventory), "Changed")]
		private static class ClearOutsideBackpack
		{
			private static void Prefix(Inventory __instance)
			{
				Player localPlayer = Player.m_localPlayer;
				if (!Instance.On || (Object)(object)localPlayer == (Object)null || __instance == ((Humanoid)localPlayer).GetInventory())
				{
					return;
				}
				foreach (ItemData allItem in __instance.GetAllItems())
				{
					if (IsFavorite(allItem))
					{
						SetFavorite(allItem, favorite: false);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "DropItem")]
		private static class ClearOnDrop
		{
			private static void Postfix(ItemDrop __result)
			{
				if (Instance.On && !((Object)(object)__result == (Object)null) && __result.m_itemData != null && IsFavorite(__result.m_itemData))
				{
					SetFavorite(__result.m_itemData, favorite: false);
					__result.Save();
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		private static class ShowFavorites
		{
			private const float Thickness = 3f;

			private static readonly Dictionary<InventoryElement, GameObject> borders = new Dictionary<InventoryElement, GameObject>();

			private static void Postfix(InventoryGrid __instance)
			{
				Inventory inventory = __instance.m_inventory;
				if (inventory == null)
				{
					return;
				}
				foreach (InventoryElement element2 in __instance.m_elements)
				{
					if (borders.TryGetValue(element2, out var value) && (Object)(object)value != (Object)null)
					{
						value.SetActive(false);
					}
				}
				if (!Instance.On)
				{
					return;
				}
				int width = inventory.GetWidth();
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (IsFavorite(allItem))
					{
						InventoryElement element = __instance.GetElement(allItem.m_gridPos.x, allItem.m_gridPos.y, width);
						GameObject val = (((Object)(object)element != (Object)null) ? BorderFor(element) : null);
						if ((Object)(object)val != (Object)null)
						{
							val.SetActive(true);
						}
					}
				}
			}

			private static GameObject BorderFor(InventoryElement element)
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Expected O, but got Unknown
				//IL_0068: 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_007a: 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)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: 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_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: 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_00c4: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f6: 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_010f: Expected O, but got Unknown
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0129: 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_0142: Expected O, but got Unknown
				//IL_0142: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_015c: Unknown result type (might be due to invalid IL or missing references)
				//IL_016b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0175: Expected O, but got Unknown
				//IL_017f: Unknown result type (might be due to invalid IL or missing references)
				//IL_018e: Unknown result type (might be due to invalid IL or missing references)
				//IL_019d: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a7: Expected O, but got Unknown
				if (borders.TryGetValue(element, out var value) && (Object)(object)value != (Object)null)
				{
					return value;
				}
				Image equiped = element.m_equiped;
				if ((Object)(object)equiped == (Object)null)
				{
					return null;
				}
				RectTransform rectTransform = ((Graphic)equiped).rectTransform;
				value = new GameObject("OMP_Favorite", new Type[1] { typeof(RectTransform) });
				value.layer = ((Component)rectTransform).gameObject.layer;
				RectTransform val = (RectTransform)value.transform;
				((Transform)val).SetParent(((Transform)rectTransform).parent, false);
				val.anchorMin = rectTransform.anchorMin;
				val.anchorMax = rectTransform.anchorMax;
				val.pivot = rectTransform.pivot;
				val.anchoredPosition = rectTransform.anchoredPosition;
				val.sizeDelta = rectTransform.sizeDelta;
				((Transform)val).localScale = ((Transform)rectTransform).localScale;
				((Transform)val).localRotation = ((Transform)rectTransform).localRotation;
				((Transform)val).SetSiblingIndex(((Transform)rectTransform).GetSiblingIndex() + 1);
				Bar(val, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, 3f));
				Bar(val, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 3f));
				Bar(val, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(3f, 0f));
				Bar(val, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(3f, 0f));
				borders[elemen