Decompiled source of Inventory Tweaks v1.1.2

InventoryTweaks.dll

Decompiled 20 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Inventory Tweaks")]
[assembly: AssemblyDescription("Inventory stack consolidation and persistent slot bindings for Valheim")]
[assembly: AssemblyCompany("xtasy")]
[assembly: AssemblyProduct("Inventory Tweaks")]
[assembly: ComVisible(false)]
[assembly: Guid("9c1dc60f-8ea0-4971-9429-388f029bcc43")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.2.0")]
namespace InventoryTweaks;

[Serializable]
[DataContract]
public sealed class SlotPin
{
	[DataMember]
	public int x;

	[DataMember]
	public int y;

	[DataMember]
	public string prefab;

	[DataMember]
	public bool matchCreator;

	[DataMember]
	public long crafterId;

	[DataMember]
	public string crafterName;

	[DataMember]
	public int variant;

	[DataMember]
	public int quality = 1;

	[DataMember]
	public string displayName;

	[OnDeserializing]
	private void BeforeDeserialize(StreamingContext context)
	{
		quality = 1;
	}

	public bool Matches(ItemState item)
	{
		if (item != null && string.Equals(prefab, item.Prefab, StringComparison.Ordinal))
		{
			if (matchCreator)
			{
				if (crafterId == item.CrafterId && (crafterId != 0L || string.Equals(crafterName ?? "", item.CrafterName ?? "", StringComparison.Ordinal)))
				{
					if (Rules.MatchCraftedQuality)
					{
						return quality == item.Quality;
					}
					return true;
				}
				return false;
			}
			return true;
		}
		return false;
	}
}
[Serializable]
[DataContract]
public sealed class PinDocument
{
	[DataMember(IsRequired = true)]
	public int version = 1;

	[DataMember]
	public List<SlotPin> pins = new List<SlotPin>();

	[DataMember]
	public CharacterSettings settings;

	[DataMember]
	public List<PickupFilterEntry> filters = new List<PickupFilterEntry>();
}
[Serializable]
[DataContract]
public sealed class PickupFilterEntry
{
	[DataMember]
	public string prefab;

	[DataMember]
	public int variant;

	[DataMember]
	public string displayName;
}
[Serializable]
[DataContract]
public sealed class CharacterSettings
{
	[DataMember]
	public bool useCraftedQuality;

	[DataMember]
	public bool allowManualPlacement = true;

	[DataMember]
	public bool strictAutoPickup = true;

	[DataMember]
	public bool autoCombineOnPickup = true;

	[DataMember]
	public bool showPickupFilter = true;

	[DataMember]
	public bool showPinnedSlotBorder = true;

	[DataMember]
	public bool showControlHints = true;

	[DataMember]
	public float buttonOffsetX = -5f;

	[DataMember]
	public int buttonLayoutVersion = 1;

	[DataMember]
	public float buttonOffsetY = -10f;

	[DataMember]
	public float ghostOpacity = 0.35f;

	[OnDeserializing]
	private void BeforeDeserialize(StreamingContext context)
	{
		allowManualPlacement = (strictAutoPickup = (autoCombineOnPickup = true));
		showPickupFilter = true;
		showPinnedSlotBorder = true;
		showControlHints = true;
		buttonOffsetX = -5f;
		buttonLayoutVersion = 0;
		buttonOffsetY = -10f;
		ghostOpacity = 0.35f;
	}
}
public sealed class ItemState
{
	public int X;

	public int Y;

	public int Count;

	public int Max;

	public int Quality;

	public int Variant;

	public int WorldLevel;

	public string Prefab;

	public string CrafterName;

	public long CrafterId;

	public float Durability;

	public bool UsesDurability;

	public bool Equipped;

	public bool Cheated;

	public bool IsAmmo;

	public Dictionary<string, string> Data = new Dictionary<string, string>();
}
public static class Rules
{
	public static bool MatchCraftedQuality;

	public static bool StrictAutomaticPlacement = true;

	public static bool BlocksPickup(IEnumerable<PickupFilterEntry> filters, string prefab, bool automatic)
	{
		if (automatic && !string.IsNullOrEmpty(prefab))
		{
			return filters.Any((PickupFilterEntry entry) => string.Equals(entry.prefab, prefab, StringComparison.Ordinal));
		}
		return false;
	}

	public static SlotPin PinAt(IEnumerable<SlotPin> pins, int x, int y)
	{
		return pins.FirstOrDefault((SlotPin p) => p.x == x && p.y == y);
	}

	public static bool ProtectsFromBulkTransfer(IEnumerable<SlotPin> pins, ItemState item)
	{
		if (item == null)
		{
			return false;
		}
		return PinAt(pins, item.X, item.Y)?.Matches(item) ?? false;
	}

	public static bool InBounds(SlotPin pin, int width, int height)
	{
		if (pin.x >= 0 && pin.y >= 0 && pin.x < width)
		{
			return pin.y < height;
		}
		return false;
	}

	public static bool Allows(IEnumerable<SlotPin> pins, int x, int y, ItemState item)
	{
		return PinAt(pins, x, y)?.Matches(item) ?? true;
	}

	public static bool AllowsManual(IEnumerable<SlotPin> pins, int x, int y, ItemState item, bool allowOtherItems)
	{
		if (!allowOtherItems)
		{
			return Allows(pins, x, y, item);
		}
		return true;
	}

	public static bool SameStack(ItemState a, ItemState b)
	{
		if (a == null || b == null || a.Max <= 1 || b.Max <= 1 || a.Max != b.Max || (a.Equipped && !a.IsAmmo) || (b.Equipped && !b.IsAmmo) || a.IsAmmo != b.IsAmmo || a.Prefab == null || b.Prefab == null || a.Prefab != b.Prefab || a.Quality != b.Quality || a.Variant != b.Variant || a.WorldLevel != b.WorldLevel || a.CrafterId != b.CrafterId || a.Cheated != b.Cheated || (a.CrafterId == 0L && (a.CrafterName ?? "") != (b.CrafterName ?? "")) || a.UsesDurability != b.UsesDurability || (a.UsesDurability && a.Durability != b.Durability))
		{
			return false;
		}
		if (a.Data.Count != b.Data.Count)
		{
			return false;
		}
		foreach (KeyValuePair<string, string> datum in a.Data)
		{
			if (!b.Data.TryGetValue(datum.Key, out var value) || value != datum.Value)
			{
				return false;
			}
		}
		return true;
	}

	public static int[] Consolidate(IList<ItemState> items, IList<SlotPin> pins)
	{
		int[] array = items.Select((ItemState i) => i.Count).ToArray();
		bool[] array2 = new bool[items.Count];
		for (int num = 0; num < items.Count; num++)
		{
			ItemState itemState = items[num];
			if (array2[num] || itemState.Max <= 1 || itemState.Count <= 0 || itemState.Count > itemState.Max || (itemState.Equipped && !itemState.IsAmmo))
			{
				continue;
			}
			List<int> list = new List<int>();
			for (int num2 = num; num2 < items.Count; num2++)
			{
				if (!array2[num2] && items[num2].Count > 0 && items[num2].Count <= items[num2].Max && SameStack(itemState, items[num2]))
				{
					array2[num2] = true;
					list.Add(num2);
				}
			}
			if (list.Count < 2)
			{
				continue;
			}
			list = (from j in list
				orderby items[j].Equipped && items[j].IsAmmo descending, PinAt(pins, items[j].X, items[j].Y)?.Matches(items[j]) ?? false descending, items[j].Y, items[j].X
				select j).ToList();
			long num3 = ((IEnumerable<int>)list).Sum((Func<int, long>)((int j) => items[j].Count));
			foreach (int item in list)
			{
				array[item] = (int)Math.Min(items[item].Max, num3);
				num3 -= array[item];
			}
		}
		return array;
	}

	public static Tuple<int, int> FindEmpty(IList<ItemState> items, IList<SlotPin> pins, int width, int height, bool topFirst, ItemState incoming)
	{
		if (incoming != null)
		{
			foreach (SlotPin pin in from p in pins
				orderby p.y, p.x
				select p)
			{
				if (InBounds(pin, width, height) && pin.Matches(incoming) && !items.Any((ItemState i) => i.X == pin.x && i.Y == pin.y))
				{
					return Tuple.Create(pin.x, pin.y);
				}
			}
		}
		for (int num = 0; num < height; num++)
		{
			int y = (topFirst ? num : (height - 1 - num));
			int x;
			for (x = 0; x < width; x++)
			{
				if ((!StrictAutomaticPlacement || PinAt(pins, x, y) == null) && !items.Any((ItemState i) => i.X == x && i.Y == y))
				{
					return Tuple.Create(x, y);
				}
			}
		}
		return Tuple.Create(-1, -1);
	}

	public static long Capacity(IList<ItemState> items, IList<SlotPin> pins, int width, int height, ItemState incoming)
	{
		long num = 0L;
		for (int y = 0; y < height; y++)
		{
			int x;
			for (x = 0; x < width; x++)
			{
				if (!StrictAutomaticPlacement || Allows(pins, x, y, incoming))
				{
					ItemState itemState = items.FirstOrDefault((ItemState i) => i.X == x && i.Y == y);
					if (itemState == null)
					{
						num += incoming.Max;
					}
					else if (SameStack(itemState, incoming))
					{
						num += Math.Max(0, itemState.Max - itemState.Count);
					}
				}
			}
		}
		return num;
	}
}
public static class PickupFilterRules
{
	public static bool TryDropAndAdd(IList<PickupFilterEntry> filters, PickupFilterEntry entry, Func<bool> drop)
	{
		if (entry == null || string.IsNullOrEmpty(entry.prefab))
		{
			throw new ArgumentException("Missing item prefab");
		}
		bool flag = !Rules.BlocksPickup(filters, entry.prefab, automatic: true);
		if (flag)
		{
			filters.Add(entry);
		}
		bool flag2 = false;
		try
		{
			flag2 = drop();
			return flag2;
		}
		finally
		{
			if (!flag2 && flag)
			{
				filters.Remove(entry);
			}
		}
	}
}
public sealed class PinLayoutPlanner
{
	private readonly IList<ItemState> items;

	private readonly IList<SlotPin> pins;

	private readonly int width;

	private readonly int height;

	private int[] xs;

	private int[] ys;

	private readonly bool[] active;

	private Dictionary<Tuple<int, int>, int> occupied = new Dictionary<Tuple<int, int>, int>();

	private PinLayoutPlanner(IList<ItemState> items, int[] counts, IList<SlotPin> pins, int width, int height)
	{
		this.items = items;
		this.pins = pins;
		this.width = width;
		this.height = height;
		xs = items.Select((ItemState i) => i.X).ToArray();
		ys = items.Select((ItemState i) => i.Y).ToArray();
		active = counts.Select((int c) => c > 0).ToArray();
	}

	public static Tuple<int, int>[] Plan(IList<ItemState> items, int[] counts, IList<SlotPin> pins, int width, int height)
	{
		if (counts.Length != items.Count)
		{
			throw new ArgumentException("Item/count mismatch");
		}
		PinLayoutPlanner planner = new PinLayoutPlanner(items, counts, pins, width, height);
		for (int i = 0; i < items.Count; i++)
		{
			if (!planner.active[i])
			{
				continue;
			}
			Tuple<int, int> key = Tuple.Create(planner.xs[i], planner.ys[i]);
			if (planner.occupied.ContainsKey(key))
			{
				return items.Select((ItemState item) => Tuple.Create(item.X, item.Y)).ToArray();
			}
			planner.occupied.Add(key, i);
		}
		planner.Arrange();
		return (from num in Enumerable.Range(0, items.Count)
			select Tuple.Create(planner.xs[num], planner.ys[num])).ToArray();
	}

	private bool Inside(int x, int y)
	{
		if (x >= 0 && y >= 0 && x < width)
		{
			return y < height;
		}
		return false;
	}

	private bool Correct(int index)
	{
		return Rules.PinAt(pins, xs[index], ys[index])?.Matches(items[index]) ?? false;
	}

	private void Arrange()
	{
		for (int i = 0; i <= items.Count * 2; i++)
		{
			int[] first = (int[])xs.Clone();
			int[] first2 = (int[])ys.Clone();
			ArrangePass();
			if (first.SequenceEqual(xs) && first2.SequenceEqual(ys))
			{
				break;
			}
		}
	}

	private void ArrangePass()
	{
		foreach (SlotPin pin in from p in pins
			where Rules.InBounds(p, width, height)
			orderby p.y, p.x
			select p)
		{
			if (occupied.TryGetValue(Tuple.Create(pin.x, pin.y), out var value) && pin.Matches(items[value]))
			{
				continue;
			}
			int[] array = (from i in Enumerable.Range(0, items.Count)
				where active[i] && Inside(xs[i], ys[i]) && !Correct(i) && pin.Matches(items[i])
				orderby ys[i], xs[i]
				select i).ToArray();
			foreach (int index in array)
			{
				if (TryAssign(index, pin.x, pin.y, new HashSet<int>()))
				{
					break;
				}
			}
		}
		for (int num2 = 0; num2 < items.Count; num2++)
		{
			if (active[num2] && Inside(xs[num2], ys[num2]) && Rules.PinAt(pins, xs[num2], ys[num2]) != null && !Correct(num2))
			{
				Relocate(num2, new HashSet<int>());
			}
		}
	}

	private bool Relocate(int index, HashSet<int> chain)
	{
		foreach (SlotPin item in from p in pins
			where Rules.InBounds(p, width, height) && p.Matches(items[index])
			orderby p.y, p.x
			select p)
		{
			if ((!occupied.TryGetValue(Tuple.Create(item.x, item.y), out var value) || (!chain.Contains(value) && !item.Matches(items[value]))) && TryAssign(index, item.x, item.y, chain))
			{
				return true;
			}
		}
		for (int num = 0; num < height; num++)
		{
			for (int num2 = 0; num2 < width; num2++)
			{
				if (Rules.PinAt(pins, num2, num) == null && !occupied.ContainsKey(Tuple.Create(num2, num)))
				{
					return TryAssign(index, num2, num, chain);
				}
			}
		}
		return false;
	}

	private bool TryAssign(int index, int x, int y, HashSet<int> chain)
	{
		if (!chain.Add(index))
		{
			return false;
		}
		int[] array = (int[])xs.Clone();
		int[] array2 = (int[])ys.Clone();
		Dictionary<Tuple<int, int>, int> dictionary = new Dictionary<Tuple<int, int>, int>(occupied);
		bool flag = false;
		try
		{
			Tuple<int, int> key = Tuple.Create(x, y);
			int value;
			bool flag2 = occupied.TryGetValue(key, out value);
			if (flag2 && (value == index || chain.Contains(value)))
			{
				return false;
			}
			SlotPin slotPin = Rules.PinAt(pins, x, y);
			if (flag2 && slotPin != null && slotPin.Matches(items[value]))
			{
				return false;
			}
			Tuple<int, int> key2 = Tuple.Create(xs[index], ys[index]);
			if (occupied.TryGetValue(key2, out var value2) && value2 == index)
			{
				occupied.Remove(key2);
			}
			occupied[key] = index;
			xs[index] = x;
			ys[index] = y;
			flag = !flag2 || Relocate(value, chain);
			return flag;
		}
		finally
		{
			if (!flag)
			{
				xs = array;
				ys = array2;
				occupied = dictionary;
			}
			chain.Remove(index);
		}
	}
}
public static class PinCodec
{
	public static string Serialize(PinDocument document)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		using MemoryStream memoryStream = new MemoryStream();
		((XmlObjectSerializer)new DataContractJsonSerializer(typeof(PinDocument))).WriteObject((Stream)memoryStream, (object)document);
		return Encoding.UTF8.GetString(memoryStream.ToArray());
	}

	public static PinDocument Deserialize(string json)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		using MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json));
		PinDocument pinDocument = (PinDocument)((XmlObjectSerializer)new DataContractJsonSerializer(typeof(PinDocument))).ReadObject((Stream)memoryStream);
		if (pinDocument == null || pinDocument.version != 1)
		{
			throw new InvalidDataException("Unsupported character settings document");
		}
		if (pinDocument.pins == null)
		{
			pinDocument.pins = new List<SlotPin>();
		}
		if (pinDocument.filters == null)
		{
			pinDocument.filters = new List<PickupFilterEntry>();
		}
		if (pinDocument.pins.Any((SlotPin p) => p == null || p.x < 0 || p.y < 0 || string.IsNullOrEmpty(p.prefab)) || (from p in pinDocument.pins
			group p by Tuple.Create(p.x, p.y)).Any((IGrouping<Tuple<int, int>, SlotPin> g) => g.Count() > 1))
		{
			throw new InvalidDataException("Invalid slot bindings");
		}
		if (pinDocument.filters.Any((PickupFilterEntry f) => f == null || string.IsNullOrEmpty(f.prefab)) || pinDocument.filters.GroupBy<PickupFilterEntry, string>((PickupFilterEntry f) => f.prefab, StringComparer.Ordinal).Any((IGrouping<string, PickupFilterEntry> g) => g.Count() > 1))
		{
			throw new InvalidDataException("Invalid pickup filter");
		}
		return pinDocument;
	}
}
public sealed class PinFileStore
{
	private readonly string directory;

	public PinFileStore(string directory)
	{
		this.directory = directory;
	}

	public string FilePath(long characterId)
	{
		if (characterId == 0L)
		{
			throw new ArgumentException("Character ID is not ready");
		}
		return Path.Combine(directory, characterId.ToString(CultureInfo.InvariantCulture) + ".json");
	}

	public PinDocument Load(long characterId, string characterJson)
	{
		string text = FilePath(characterId);
		Exception ex = null;
		if (File.Exists(text))
		{
			try
			{
				return PinCodec.Deserialize(File.ReadAllText(text, Encoding.UTF8));
			}
			catch (Exception ex2)
			{
				ex = ex2;
			}
		}
		if (!string.IsNullOrEmpty(characterJson))
		{
			try
			{
				return PinCodec.Deserialize(characterJson);
			}
			catch (Exception ex3)
			{
				ex = ex3;
			}
		}
		if (File.Exists(text + ".bak"))
		{
			try
			{
				return PinCodec.Deserialize(File.ReadAllText(text + ".bak", Encoding.UTF8));
			}
			catch (Exception ex4)
			{
				ex = ex4;
			}
		}
		if (ex != null)
		{
			throw new InvalidDataException("Cannot restore character bindings", ex);
		}
		return new PinDocument();
	}

	public void Save(long characterId, string json)
	{
		PinCodec.Deserialize(json);
		string text = FilePath(characterId);
		Directory.CreateDirectory(directory);
		if (File.Exists(text) && File.ReadAllText(text, Encoding.UTF8) == json)
		{
			return;
		}
		string text2 = text + "." + Guid.NewGuid().ToString("N") + ".tmp";
		try
		{
			using (FileStream fileStream = new FileStream(text2, FileMode.CreateNew, FileAccess.Write, FileShare.None))
			{
				byte[] bytes = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false).GetBytes(json);
				fileStream.Write(bytes, 0, bytes.Length);
				fileStream.Flush(flushToDisk: true);
			}
			if (File.Exists(text))
			{
				File.Replace(text2, text, text + ".bak");
			}
			else
			{
				File.Move(text2, text);
			}
		}
		finally
		{
			if (File.Exists(text2))
			{
				File.Delete(text2);
			}
		}
	}
}
internal static class ModText
{
	internal static bool Russian
	{
		get
		{
			if (Localization.instance != null)
			{
				return string.Equals(Localization.instance.GetSelectedLanguage(), "Russian", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}
	}

	internal static string Combine => Choose("Объединить", "Combine");

	internal static string Reset => Choose("Сброс", "Reset");

	internal static string ResetHint => Choose("Снять все закрепления и очистить фильтр автоподбора текущего персонажа. Остальные настройки и другие персонажи не изменяются.", "Clear all slot bindings and the automatic pickup filter for this character. Other settings and other characters are unchanged.");

	internal static string PinsReset => Choose("Закрепления и фильтр автоподбора этого персонажа сброшены.", "Slot bindings and the automatic pickup filter for this character have been reset.");

	internal static string FilterHint => Choose("Автоподбор отключён для этого типа предмета. ЛКМ — удалить из фильтра. Добавить: Ctrl + СКМ по предмету в инвентаре.", "Automatic pickup is blocked for this item type. Left-click to remove from the filter. Add items with Ctrl + middle-click in the inventory.");

	internal static string InventoryHints => Choose("СКМ - закрепить предмет в ячейке\nКонтрол + СКМ - добавить в фильтр автоподбора", "Middle mouse - pin item to slot\nCtrl + middle mouse - add to automatic pickup filter");

	internal static string FilterVisibilityTitle => Choose("Отображение фильтра", "Filter visibility");

	internal static string PinBorderTitle => Choose("Обводка закреплённых ячеек", "Pinned slot borders");

	internal static string FilterVisibilityHint => Choose("Показывает или скрывает иконки под кнопками. Фильтр автоподбора продолжает работать, даже когда иконки скрыты. Сохраняется для текущего персонажа.", "Show or hide the icons below the buttons. Automatic pickup filtering stays active while the icons are hidden. Saved for this character.");

	internal static string CombineHint => Choose("Объединяет стопки и расставляет предметы по закреплённым ячейкам. Чужие предметы перемещаются в свободные ячейки, если есть место.", "Combines stacks and places items into their pinned cells. Foreign occupants move to free suitable cells when space is available.");

	internal static string CombiningModeTitle => Choose("Режим объединения", "Stack combining mode");

	internal static string CombiningModeHint => Choose("A — автоматическое объединение после подбора предметов.\nM — ручное объединение кнопкой «Объединить».\nНажмите, чтобы переключить. По умолчанию: A.", "A — combine automatically after picking up items.\nM — combine manually with the Combine button.\nClick to switch. Default: A.");

	internal static string ModeTitle => Choose("Режим автоподбора", "Automatic pickup mode");

	internal static string ModeHint => Choose("Строго: закреплённые ячейки принимают только подходящие предметы.\nСвободно: автоподбор может занять их другими предметами.\nНажмите, чтобы переключить режим.", "Strict: pinned slots only accept matching pickups.\nFree: other pickups can also occupy these slots.\nClick to switch mode.");

	internal static string PinnedHint => Choose("Закреплённая ячейка. Средняя кнопка мыши — снять закрепление.", "Pinned slot. Middle-click to unpin.");

	internal static string InvalidPins => Choose("Не удалось прочитать сохранённые закрепления.", "Could not read saved slot bindings.");

	internal static string SaveFailed => Choose("Не удалось записать закрепления персонажа на диск. Подробности в логе.", "Could not save character bindings to disk. See the log for details.");

	internal static string PutDownItem => Choose("Сначала положите переносимый предмет.", "Put down the dragged item first.");

	internal static string NothingToCombine => Choose("Нет стопок для объединения или доступных перемещений.", "No stacks to combine or available item moves.");

	internal static string CannotPlace => Choose("Предметы нельзя объединить или ячейка закреплена за другим предметом. Средняя кнопка мыши — снять закрепление.", "These items cannot be stacked, or the slot is pinned to another item. Middle-click to unpin.");

	internal static string Creator => Choose("Создатель: ", "Crafter: ");

	internal static string Quality => Choose("Качество: ", "Quality: ");

	internal static string Choose(string russian, string english)
	{
		if (!Russian)
		{
			return english;
		}
		return russian;
	}

	internal static string FilterVisibility(bool shown)
	{
		if (!shown)
		{
			return Choose("Показать фильтр", "Show filter");
		}
		return Choose("Скрыть фильтр", "Hide filter");
	}

	internal static string PinBorderHint(bool enabled)
	{
		return (enabled ? Choose("Жёлтая кнопка: обводка включена. Нажмите, чтобы скрыть рамки.", "Yellow button: borders are on. Click to hide them.") : Choose("Коричневая кнопка: обводка выключена. Нажмите, чтобы показать рамки.", "Brown button: borders are off. Click to show them.")) + Choose(" Значки закрепления остаются. Настройка сохраняется для персонажа.", " Lock icons remain. Saved for this character.");
	}

	internal static string Mode(bool strict)
	{
		if (!strict)
		{
			return Choose("Свободно", "Free");
		}
		return Choose("Строго", "Strict");
	}

	internal static string Combined(int freed, int moved)
	{
		return Choose("Освобождено ячеек: ", "Slots freed: ") + freed + Choose(". Перемещено: ", ". Items moved: ") + moved;
	}
}
[BepInPlugin("com.xtasy.InventoryTweaks", "Inventory Tweaks", "1.1.2")]
public sealed class InventoryTweaksPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.xtasy.InventoryTweaks";

	public const string PluginName = "Inventory Tweaks";

	public const string PluginVersion = "1.1.2";

	internal const string SaveKey = "com.xtasy.InventoryTweaks.pins.v1";

	internal static InventoryTweaksPlugin Instance;

	internal static ConfigEntry<Vector2> ButtonOffset;

	internal static ConfigEntry<float> GhostOpacity;

	internal static ConfigEntry<bool> UseCraftedItemQualityForPinning;

	internal static ConfigEntry<bool> AllowManualPlacementIntoOtherPinnedSlots;

	internal static ConfigEntry<bool> StrictAutoPickup;

	internal static ConfigEntry<bool> AutoCombineOnPickup;

	internal static ConfigEntry<bool> ShowPickupFilter;

	internal static ConfigEntry<bool> ShowPinnedSlotBorder;

	internal static ConfigEntry<bool> ShowControlHints;

	private static Player pendingPickupOwner;

	internal static List<SlotPin> Pins = new List<SlotPin>();

	internal static List<PickupFilterEntry> PickupFilters = new List<PickupFilterEntry>();

	internal static int FilterRevision;

	internal static Player Owner;

	private static string loadedJson;

	private static long ownerId;

	private static PinFileStore pinStore;

	private static bool applyingCharacterSettings;

	private static bool invalidSave;

	private Harmony harmony;

	private DateTime configWriteTime;

	private float nextConfigCheck;

	[ThreadStatic]
	internal static ItemData Incoming;

	[ThreadStatic]
	internal static int LoadDepth;

	[ThreadStatic]
	internal static int ManualDepth;

	[ThreadStatic]
	internal static int CraftDepth;

	[ThreadStatic]
	internal static int AutoPickupDepth;

	internal static bool Busy;

	internal static readonly MethodInfo Changed = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
	{
		typeof(bool),
		typeof(bool)
	}, (Type[])null);

	internal static readonly FieldInfo DragItem = AccessTools.Field(typeof(InventoryGui), "m_dragItem");

	private void Awake()
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Expected O, but got Unknown
		Instance = this;
		pinStore = new PinFileStore(Path.Combine(Paths.ConfigPath, "InventoryTweaks", "pins"));
		ShowControlHints = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowControlHints", true, "Show control hints below the buttons when the pickup filter is empty. Default true; saved per character; applies live. / Показывать подсказки под кнопками, когда фильтр автоподбора пуст. По умолчанию включено; сохраняется для персонажа; применяется без перезапуска.");
		ShowPickupFilter = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowPickupFilter", true, "Show pickup-filter icons below the buttons. Hiding the icons keeps the filter active. Saved per character; applies live. / Показывать иконки фильтра под кнопками. При скрытии фильтр продолжает работать. Сохраняется для персонажа; применяется без перезапуска.");
		ShowPinnedSlotBorder = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowPinnedSlotBorder", true, "Show the yellow border around pinned inventory slots. The lock icon stays visible when disabled. Default true; saved per character; applies live. / Показывать жёлтую обводку закреплённых ячеек. При отключении значок закрепления остаётся. По умолчанию включено; сохраняется для персонажа; применяется без перезапуска.");
		ButtonOffset = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Interface", "CombineButtonOffset", new Vector2(-5f, -10f), "Button and filter offset from the inventory panel's bottom-left edge. Default X=-5, Y=-10. / Смещение кнопок и фильтра от нижнего левого края инвентаря. По умолчанию X=-5, Y=-10.");
		GhostOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "GhostOpacity", 0.35f, new ConfigDescription("Empty pinned slot icon opacity. / Прозрачность иконки пустой закреплённой ячейки.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.8f), Array.Empty<object>()));
		UseCraftedItemQualityForPinning = ((BaseUnityPlugin)this).Config.Bind<bool>("Pinning", "UseCraftedItemQualityForPinning", false, "Match crafted item quality as well as prefab and creator. Durability is always ignored. Changes apply live. / Учитывать качество созданного предмета при закреплении. Прочность всегда игнорируется. Применяется без перезапуска.");
		AllowManualPlacementIntoOtherPinnedSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("Pinning", "AllowManualPlacementIntoOtherPinnedSlots", true, "Allow manual placement of a different item into a pinned slot, retaining its binding. Automatic pickup still respects pins. Changes apply live. / Разрешить вручную положить другой предмет в закреплённую ячейку, сохранив закрепление. Автоподбор соблюдает закрепления. Применяется без перезапуска.");
		StrictAutoPickup = ((BaseUnityPlugin)this).Config.Bind<bool>("Pinning", "StrictAutoPickup", true, "True: automatic placement reserves pinned cells for matching items. False: other pickups can use them. Toggled by the Strict/Free button. / Строго: автоподбор соблюдает закрепления. Свободно: другие предметы тоже могут занимать эти ячейки. Переключается кнопкой в инвентаре.");
		AutoCombineOnPickup = ((BaseUnityPlugin)this).Config.Bind<bool>("Combining", "AutoCombineOnPickup", true, "A: combine after picking up items. M: combine only by clicking Combine. Default A. Changes apply live. / A: объединять после подбора предметов. M: объединять только кнопкой. По умолчанию A. Применяется без перезапуска.");
		Rules.MatchCraftedQuality = UseCraftedItemQualityForPinning.Value;
		Rules.StrictAutomaticPlacement = StrictAutoPickup.Value;
		((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged;
		configWriteTime = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath);
		harmony = new Harmony("com.xtasy.InventoryTweaks");
		harmony.PatchAll(typeof(InventoryTweaksPlugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Inventory Tweaks 1.1.2 loaded");
	}

	private void LateUpdate()
	{
		ReloadConfiguration();
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && LoadDepth <= 0 && EnsurePins())
		{
			if (!AutoCombineOnPickup.Value || (Object.op_Implicit((Object)(object)pendingPickupOwner) && pendingPickupOwner != Player.m_localPlayer))
			{
				pendingPickupOwner = null;
			}
			if (Object.op_Implicit((Object)(object)pendingPickupOwner) && !Busy && !IsDragging() && !((Character)Player.m_localPlayer).IsTeleporting())
			{
				pendingPickupOwner = null;
				Combine(showMessage: false, arrangePins: false);
			}
		}
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		InventoryUi.Cleanup();
		Pins.Clear();
		PickupFilters.Clear();
		FilterRevision++;
		Owner = null;
		ownerId = 0L;
		loadedJson = null;
		pendingPickupOwner = null;
		Instance = null;
	}

	private void OnSettingChanged(object sender, SettingChangedEventArgs args)
	{
		Rules.MatchCraftedQuality = UseCraftedItemQualityForPinning.Value;
		Rules.StrictAutomaticPlacement = StrictAutoPickup.Value;
		if (!AutoCombineOnPickup.Value)
		{
			pendingPickupOwner = null;
		}
		if (!applyingCharacterSettings && Object.op_Implicit((Object)(object)Owner))
		{
			SavePins();
		}
	}

	private void ReloadConfiguration()
	{
		if (Time.unscaledTime < nextConfigCheck)
		{
			return;
		}
		nextConfigCheck = Time.unscaledTime + 0.75f;
		try
		{
			DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath);
			if (!(lastWriteTimeUtc == configWriteTime) && File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
			{
				configWriteTime = lastWriteTimeUtc;
				applyingCharacterSettings = true;
				try
				{
					((BaseUnityPlugin)this).Config.Reload();
				}
				finally
				{
					applyingCharacterSettings = false;
				}
				Rules.MatchCraftedQuality = UseCraftedItemQualityForPinning.Value;
				Rules.StrictAutomaticPlacement = StrictAutoPickup.Value;
				if (Object.op_Implicit((Object)(object)Owner))
				{
					SavePins();
				}
				configWriteTime = File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuration reloaded");
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Cannot reload configuration: " + ex.Message));
		}
	}

	internal static bool IsDragging()
	{
		if (Object.op_Implicit((Object)(object)InventoryGui.instance))
		{
			return DragItem.GetValue(InventoryGui.instance) != null;
		}
		return false;
	}

	internal static bool IsLocal(Inventory inventory)
	{
		if (LoadDepth == 0 && Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			return ((Humanoid)Player.m_localPlayer).GetInventory() == inventory;
		}
		return false;
	}

	internal static bool HasPins(Inventory inventory)
	{
		if (!IsLocal(inventory))
		{
			return false;
		}
		if (!EnsurePins())
		{
			return false;
		}
		if (!invalidSave)
		{
			return Pins.Count != 0;
		}
		return false;
	}

	internal static bool EnsurePins()
	{
		Player localPlayer = Player.m_localPlayer;
		if (!Object.op_Implicit((Object)(object)localPlayer) || LoadDepth > 0 || applyingCharacterSettings)
		{
			return false;
		}
		long playerID = localPlayer.GetPlayerID();
		if (playerID == 0L)
		{
			return false;
		}
		localPlayer.m_customData.TryGetValue("com.xtasy.InventoryTweaks.pins.v1", out var value);
		if (Owner == localPlayer && ownerId == playerID && value == loadedJson)
		{
			return true;
		}
		Owner = localPlayer;
		ownerId = playerID;
		loadedJson = value;
		Pins = new List<SlotPin>();
		PickupFilters = new List<PickupFilterEntry>();
		FilterRevision++;
		invalidSave = false;
		try
		{
			PinDocument pinDocument = pinStore.Load(playerID, value);
			Pins = pinDocument.pins;
			PickupFilters = pinDocument.filters;
			ApplyCharacterSettings(pinDocument.settings ?? (string.IsNullOrEmpty(value) ? new CharacterSettings() : CaptureSettings()));
			SavePins();
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Restored " + Pins.Count + " slot bindings for character " + playerID));
			return true;
		}
		catch (Exception ex)
		{
			invalidSave = true;
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Cannot read saved pins; original data has been preserved. Stack combining remains available. " + ex));
			return true;
		}
	}

	private static CharacterSettings CaptureSettings()
	{
		//IL_007b: 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)
		return new CharacterSettings
		{
			useCraftedQuality = UseCraftedItemQualityForPinning.Value,
			allowManualPlacement = AllowManualPlacementIntoOtherPinnedSlots.Value,
			strictAutoPickup = StrictAutoPickup.Value,
			autoCombineOnPickup = AutoCombineOnPickup.Value,
			showPickupFilter = ShowPickupFilter.Value,
			showPinnedSlotBorder = ShowPinnedSlotBorder.Value,
			showControlHints = ShowControlHints.Value,
			buttonOffsetX = ButtonOffset.Value.x,
			buttonOffsetY = ButtonOffset.Value.y,
			ghostOpacity = GhostOpacity.Value
		};
	}

	private static void ApplyCharacterSettings(CharacterSettings settings)
	{
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		if (settings.buttonLayoutVersion < 1)
		{
			if (Mathf.Approximately(settings.buttonOffsetX, 8f) && Mathf.Approximately(settings.buttonOffsetY, -6f))
			{
				settings.buttonOffsetX = -5f;
				settings.buttonOffsetY = -10f;
			}
			settings.buttonLayoutVersion = 1;
		}
		bool saveOnConfigSet = ((BaseUnityPlugin)Instance).Config.SaveOnConfigSet;
		applyingCharacterSettings = true;
		((BaseUnityPlugin)Instance).Config.SaveOnConfigSet = false;
		try
		{
			UseCraftedItemQualityForPinning.Value = settings.useCraftedQuality;
			AllowManualPlacementIntoOtherPinnedSlots.Value = settings.allowManualPlacement;
			StrictAutoPickup.Value = settings.strictAutoPickup;
			AutoCombineOnPickup.Value = settings.autoCombineOnPickup;
			ShowPickupFilter.Value = settings.showPickupFilter;
			ShowPinnedSlotBorder.Value = settings.showPinnedSlotBorder;
			ShowControlHints.Value = settings.showControlHints;
			ButtonOffset.Value = new Vector2(settings.buttonOffsetX, settings.buttonOffsetY);
			GhostOpacity.Value = settings.ghostOpacity;
		}
		finally
		{
			((BaseUnityPlugin)Instance).Config.SaveOnConfigSet = saveOnConfigSet;
			applyingCharacterSettings = false;
		}
		Rules.MatchCraftedQuality = UseCraftedItemQualityForPinning.Value;
		Rules.StrictAutomaticPlacement = StrictAutoPickup.Value;
		((BaseUnityPlugin)Instance).Config.Save();
		Instance.configWriteTime = File.GetLastWriteTimeUtc(((BaseUnityPlugin)Instance).Config.ConfigFilePath);
	}

	internal static void SavePins()
	{
		if (!Object.op_Implicit((Object)(object)Owner) || Owner != Player.m_localPlayer || invalidSave || ownerId == 0L || ownerId != Owner.GetPlayerID() || applyingCharacterSettings)
		{
			return;
		}
		loadedJson = PinCodec.Serialize(new PinDocument
		{
			pins = Pins,
			settings = CaptureSettings(),
			filters = PickupFilters
		});
		Owner.m_customData["com.xtasy.InventoryTweaks.pins.v1"] = loadedJson;
		try
		{
			pinStore.Save(ownerId, loadedJson);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)("Cannot persist character bindings to disk: " + ex.Message));
			Notify(ModText.SaveFailed);
		}
	}

	internal static string Prefab(ItemData item)
	{
		if (item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab))
		{
			return null;
		}
		return ((Object)item.m_dropPrefab).name;
	}

	internal static ItemState Describe(ItemData item)
	{
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Invalid comparison between Unknown and I4
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Invalid comparison between Unknown and I4
		if (item == null)
		{
			return null;
		}
		return new ItemState
		{
			X = item.m_gridPos.x,
			Y = item.m_gridPos.y,
			Count = item.m_stack,
			Max = item.m_shared.m_maxStackSize,
			Prefab = Prefab(item),
			CrafterId = item.m_crafterID,
			CrafterName = item.m_crafterName,
			Quality = item.m_quality,
			Variant = item.m_variant,
			WorldLevel = item.m_worldLevel,
			UsesDurability = item.m_shared.m_useDurability,
			Durability = item.m_durability,
			Equipped = item.m_equipped,
			Cheated = item.m_cheated,
			IsAmmo = ((int)item.m_shared.m_itemType == 9 || (int)item.m_shared.m_itemType == 23),
			Data = (item.m_customData ?? new Dictionary<string, string>())
		};
	}

	internal static List<ItemState> Describe(Inventory inventory)
	{
		return inventory.GetAllItems().Select(Describe).ToList();
	}

	internal static bool Allows(Inventory inventory, ItemData item, int x, int y)
	{
		ItemData val = CurrentUpgrade();
		if (val != null && IsLocal(inventory) && Prefab(val) == Prefab(item) && val.m_gridPos.x == x && val.m_gridPos.y == y)
		{
			return true;
		}
		if (ManualDepth > 0)
		{
			return AllowsManual(inventory, item, x, y);
		}
		if (!StrictAutoPickup.Value)
		{
			return true;
		}
		if (HasPins(inventory))
		{
			return Rules.Allows(Pins, x, y, Describe(item));
		}
		return true;
	}

	internal static bool AllowsManual(Inventory inventory, ItemData item, int x, int y)
	{
		if (HasPins(inventory))
		{
			return Rules.AllowsManual(Pins, x, y, Describe(item), AllowManualPlacementIntoOtherPinnedSlots.Value);
		}
		return true;
	}

	internal static ItemData CurrentUpgrade()
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		if (CraftDepth <= 0 || !Object.op_Implicit((Object)(object)InventoryGui.instance))
		{
			return null;
		}
		return (ItemData)AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem").GetValue(InventoryGui.instance);
	}

	internal static void ToggleMode()
	{
		StrictAutoPickup.Value = !StrictAutoPickup.Value;
		((BaseUnityPlugin)Instance).Config.Save();
	}

	internal static void ToggleAutomaticCombine()
	{
		AutoCombineOnPickup.Value = !AutoCombineOnPickup.Value;
		((BaseUnityPlugin)Instance).Config.Save();
	}

	internal static void TogglePickupFilterVisibility()
	{
		ShowPickupFilter.Value = !ShowPickupFilter.Value;
		((BaseUnityPlugin)Instance).Config.Save();
		if (Object.op_Implicit((Object)(object)InventoryGui.instance))
		{
			InventoryUi.EnsureButton(InventoryGui.instance);
		}
	}

	internal static void TogglePinnedSlotBorder()
	{
		ShowPinnedSlotBorder.Value = !ShowPinnedSlotBorder.Value;
		((BaseUnityPlugin)Instance).Config.Save();
		if (Object.op_Implicit((Object)(object)InventoryGui.instance))
		{
			InventoryUi.EnsureButton(InventoryGui.instance);
		}
	}

	internal static void QueuePickupCombine()
	{
		if (AutoCombineOnPickup.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer) && LoadDepth == 0)
		{
			pendingPickupOwner = Player.m_localPlayer;
		}
	}

	internal static void ResetPins()
	{
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && LoadDepth <= 0 && EnsurePins())
		{
			invalidSave = false;
			Pins.Clear();
			PickupFilters.Clear();
			FilterRevision++;
			SavePins();
			Notify(ModText.PinsReset);
		}
	}

	internal static bool IsPickupFiltered(ItemData item)
	{
		if (AutoPickupDepth > 0 && EnsurePins())
		{
			return Rules.BlocksPickup(PickupFilters, Prefab(item), automatic: true);
		}
		return false;
	}

	internal static void DropAndFilter(int x, int y)
	{
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || LoadDepth > 0 || IsDragging() || ((Character)Player.m_localPlayer).IsTeleporting() || !EnsurePins())
		{
			return;
		}
		if (invalidSave)
		{
			Notify(ModText.InvalidPins);
			return;
		}
		Inventory inventory = ((Humanoid)Owner).GetInventory();
		ItemData item = inventory.GetItemAt(x, y);
		string text = Prefab(item);
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		PickupFilterEntry entry = new PickupFilterEntry
		{
			prefab = text,
			variant = item.m_variant,
			displayName = item.m_shared.m_name
		};
		bool flag = false;
		try
		{
			flag = PickupFilterRules.TryDropAndAdd(PickupFilters, entry, () => ((Humanoid)Owner).DropItem(inventory, item, item.m_stack));
		}
		finally
		{
			FilterRevision++;
			if (flag)
			{
				SavePins();
			}
		}
	}

	internal static void RemovePickupFilter(string prefab)
	{
		if (EnsurePins() && !invalidSave && PickupFilters.RemoveAll((PickupFilterEntry entry) => string.Equals(entry.prefab, prefab, StringComparison.Ordinal)) != 0)
		{
			FilterRevision++;
			SavePins();
		}
	}

	internal static void TogglePin(int x, int y)
	{
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || IsDragging() || ((Character)Player.m_localPlayer).IsTeleporting() || !EnsurePins())
		{
			return;
		}
		if (invalidSave)
		{
			Notify(ModText.InvalidPins);
			return;
		}
		SlotPin slotPin = Rules.PinAt(Pins, x, y);
		if (slotPin != null)
		{
			Pins.Remove(slotPin);
			SavePins();
			return;
		}
		ItemData itemAt = ((Humanoid)Owner).GetInventory().GetItemAt(x, y);
		string text = Prefab(itemAt);
		if (!string.IsNullOrEmpty(text))
		{
			Pins.Add(new SlotPin
			{
				x = x,
				y = y,
				prefab = text,
				matchCreator = (itemAt.m_crafterID != 0L || !string.IsNullOrEmpty(itemAt.m_crafterName) || (Object.op_Implicit((Object)(object)ObjectDB.instance) && (Object)(object)ObjectDB.instance.GetRecipe(itemAt) != (Object)null)),
				crafterId = itemAt.m_crafterID,
				crafterName = itemAt.m_crafterName,
				variant = itemAt.m_variant,
				quality = itemAt.m_quality,
				displayName = itemAt.m_shared.m_name
			});
			SavePins();
		}
	}

	internal static void Notify(string message)
	{
		if (Object.op_Implicit((Object)(object)MessageHud.instance))
		{
			MessageHud.instance.ShowMessage((MessageType)1, message, 0, (Sprite)null, false, true);
		}
	}

	internal void LoggerForUi(string message)
	{
		((BaseUnityPlugin)this).Logger.LogWarning((object)message);
	}

	internal static void Signal(Inventory inventory)
	{
		Changed.Invoke(inventory, new object[2] { false, false });
	}

	internal static void Combine()
	{
		Combine(showMessage: true, arrangePins: true);
	}

	private static void Combine(bool showMessage, bool arrangePins)
	{
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || Busy || LoadDepth > 0 || ((Character)Player.m_localPlayer).IsTeleporting())
		{
			return;
		}
		if (IsDragging())
		{
			if (showMessage)
			{
				Notify(ModText.PutDownItem);
			}
		}
		else
		{
			if (!EnsurePins())
			{
				return;
			}
			Inventory inventory = ((Humanoid)Owner).GetInventory();
			List<ItemData> list = inventory.GetAllItems().ToList();
			List<ItemState> items = list.Select(Describe).ToList();
			int[] array = Rules.Consolidate(items, Pins);
			Tuple<int, int>[] array2 = (arrangePins ? PinLayoutPlanner.Plan(items, array, Pins, inventory.GetWidth(), inventory.GetHeight()) : null);
			int num = 0;
			int num2 = 0;
			bool flag = false;
			Busy = true;
			try
			{
				for (int i = 0; i < list.Count; i++)
				{
					if (array[i] == 0)
					{
						inventory.GetAllItems().Remove(list[i]);
						num++;
						flag = true;
						continue;
					}
					if (list[i].m_stack != array[i])
					{
						list[i].m_stack = array[i];
						flag = true;
					}
					if (array2 != null && (list[i].m_gridPos.x != array2[i].Item1 || list[i].m_gridPos.y != array2[i].Item2))
					{
						list[i].m_gridPos = new Vector2i(array2[i].Item1, array2[i].Item2);
						num2++;
						flag = true;
					}
				}
				if (flag)
				{
					Signal(inventory);
				}
			}
			finally
			{
				Busy = false;
			}
			if (showMessage)
			{
				Notify(flag ? ModText.Combined(num, num2) : ModText.NothingToCombine);
			}
		}
	}
}
[HarmonyPatch(typeof(Player), "AutoPickup")]
internal static class AutoPickupContextPatch
{
	private static void Prefix(Player __instance, out int __state)
	{
		__state = InventoryTweaksPlugin.AutoPickupDepth;
		if (__instance == Player.m_localPlayer)
		{
			InventoryTweaksPlugin.AutoPickupDepth++;
		}
	}

	private static Exception Finalizer(Exception __exception, int __state)
	{
		InventoryTweaksPlugin.AutoPickupDepth = __state;
		return __exception;
	}
}
[HarmonyPatch]
internal static class CraftingContextPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		yield return AccessTools.Method(typeof(InventoryGui), "OnCraftPressed", (Type[])null, (Type[])null);
		yield return AccessTools.Method(typeof(InventoryGui), "DoCrafting", (Type[])null, (Type[])null);
	}

	private static void Prefix(out int __state)
	{
		__state = InventoryTweaksPlugin.CraftDepth;
		InventoryTweaksPlugin.CraftDepth++;
	}

	private static Exception Finalizer(Exception __exception, int __state)
	{
		InventoryTweaksPlugin.CraftDepth = __state;
		return __exception;
	}
}
[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
{
	typeof(GameObject),
	typeof(int)
})]
internal static class CraftingCapacityPatch
{
	private static bool Prefix(Inventory __instance, GameObject prefab, int stack, ref bool __result)
	{
		if (!InventoryTweaksPlugin.HasPins(__instance) || InventoryTweaksPlugin.CraftDepth == 0)
		{
			return true;
		}
		ItemDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			__result = false;
			return false;
		}
		ItemData val2 = val.m_itemData.Clone();
		val2.m_dropPrefab = prefab;
		val2.m_crafterID = Player.m_localPlayer.GetPlayerID();
		val2.m_crafterName = Player.m_localPlayer.GetPlayerName();
		val2.m_quality = 1;
		val2.m_durability = val2.GetMaxDurability();
		val2.m_worldLevel = Game.m_worldLevel;
		if (Object.op_Implicit((Object)(object)InventoryGui.instance))
		{
			val2.m_variant = (int)AccessTools.Field(typeof(InventoryGui), "m_craftVariant").GetValue(InventoryGui.instance);
		}
		__result = __instance.CanAddItem(val2, stack);
		return false;
	}
}
[HarmonyPatch]
internal static class LoadingPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return (from m in AccessTools.GetDeclaredMethods(typeof(Inventory))
			where m.Name == "Load"
			select m).Concat(from m in AccessTools.GetDeclaredMethods(typeof(Player))
			where m.Name == "Load"
			select m).Concat(from m in AccessTools.GetDeclaredMethods(typeof(PlayerProfile))
			where m.Name == "LoadPlayerData"
			select m);
	}

	private static void Prefix(out int __state)
	{
		__state = InventoryTweaksPlugin.LoadDepth;
		InventoryTweaksPlugin.LoadDepth++;
	}

	private static Exception Finalizer(Exception __exception, int __state)
	{
		InventoryTweaksPlugin.LoadDepth = __state;
		return __exception;
	}
}
[HarmonyPatch]
internal static class IncomingPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return AccessTools.GetDeclaredMethods(typeof(Inventory)).Where(delegate(MethodInfo m)
		{
			ParameterInfo[] parameters = m.GetParameters();
			return m.Name == "AddItem" && parameters.Length != 0 && (parameters[0].ParameterType == typeof(ItemData) || (parameters[0].ParameterType == typeof(string) && parameters.Any((ParameterInfo a) => a.Name == "crafterID") && parameters.Length >= 6 && parameters[2].ParameterType == typeof(int)));
		});
	}

	private static void Prefix(Inventory __instance, object[] __args, out ItemData __state)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		__state = InventoryTweaksPlugin.Incoming;
		InventoryTweaksPlugin.Incoming = null;
		if (!InventoryTweaksPlugin.HasPins(__instance))
		{
			return;
		}
		if (__args[0] is ItemData)
		{
			InventoryTweaksPlugin.Incoming = (ItemData)__args[0];
		}
		else if (__args[0] is string && Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab((string)__args[0]);
			if (Object.op_Implicit((Object)(object)itemPrefab) && Object.op_Implicit((Object)(object)itemPrefab.GetComponent<ItemDrop>()))
			{
				ItemData obj = itemPrefab.GetComponent<ItemDrop>().m_itemData.Clone();
				obj.m_dropPrefab = itemPrefab;
				obj.m_stack = (int)__args[1];
				obj.m_quality = (int)__args[2];
				obj.m_variant = (int)__args[3];
				obj.m_crafterID = (long)__args[4];
				obj.m_crafterName = (string)__args[5];
				obj.m_worldLevel = Game.m_worldLevel;
				InventoryTweaksPlugin.Incoming = obj;
			}
		}
	}

	private static Exception Finalizer(Exception __exception, ItemData __state)
	{
		InventoryTweaksPlugin.Incoming = __state;
		return __exception;
	}
}
[HarmonyPatch(typeof(Inventory), "FindEmptySlot")]
internal static class EmptySlotPatch
{
	private static bool Prefix(Inventory __instance, bool topFirst, ref Vector2i __result)
	{
		//IL_008b: 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_004a: 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)
		if (!InventoryTweaksPlugin.HasPins(__instance))
		{
			return true;
		}
		ItemData val = InventoryTweaksPlugin.CurrentUpgrade();
		if (val != null && __instance.GetItemAt(val.m_gridPos.x, val.m_gridPos.y) == null && InventoryTweaksPlugin.Prefab(val) == InventoryTweaksPlugin.Prefab(InventoryTweaksPlugin.Incoming))
		{
			__result = val.m_gridPos;
			return false;
		}
		Tuple<int, int> tuple = Rules.FindEmpty(InventoryTweaksPlugin.Describe(__instance), InventoryTweaksPlugin.Pins, __instance.GetWidth(), __instance.GetHeight(), topFirst, InventoryTweaksPlugin.Describe(InventoryTweaksPlugin.Incoming));
		__result = new Vector2i(tuple.Item1, tuple.Item2);
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "FindFreeStackItem")]
internal static class FreeStackPatch
{
	private static bool Prefix(Inventory __instance, ref ItemData __result)
	{
		if (!InventoryTweaksPlugin.HasPins(__instance) || InventoryTweaksPlugin.Incoming == null)
		{
			return true;
		}
		ItemState incoming = InventoryTweaksPlugin.Describe(InventoryTweaksPlugin.Incoming);
		__result = (from i in __instance.GetAllItems()
			where i.m_stack < i.m_shared.m_maxStackSize && Rules.SameStack(InventoryTweaksPlugin.Describe(i), incoming) && InventoryTweaksPlugin.Allows(__instance, InventoryTweaksPlugin.Incoming, i.m_gridPos.x, i.m_gridPos.y)
			orderby Rules.PinAt(InventoryTweaksPlugin.Pins, i.m_gridPos.x, i.m_gridPos.y)?.Matches(incoming) ?? false descending, i.m_gridPos.y, i.m_gridPos.x
			select i).FirstOrDefault();
		if (__result != null && Rules.PinAt(InventoryTweaksPlugin.Pins, __result.m_gridPos.x, __result.m_gridPos.y) == null && InventoryTweaksPlugin.Pins.Any((SlotPin p) => Rules.InBounds(p, __instance.GetWidth(), __instance.GetHeight()) && p.Matches(incoming) && __instance.GetItemAt(p.x, p.y) == null))
		{
			__result = null;
		}
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
{
	typeof(ItemData),
	typeof(Vector2i)
})]
internal static class ExplicitSlotPatch
{
	private static bool Prefix(Inventory __instance, ItemData item, Vector2i pos, ref bool __result)
	{
		//IL_0002: 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)
		if (InventoryTweaksPlugin.Allows(__instance, item, pos.x, pos.y))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
{
	typeof(ItemData),
	typeof(int),
	typeof(int),
	typeof(int),
	typeof(bool)
})]
internal static class PositionedAddPatch
{
	private static bool Prefix(Inventory __instance, ItemData item, int x, int y, ref bool __result)
	{
		if (!InventoryTweaksPlugin.HasPins(__instance))
		{
			return true;
		}
		ItemData itemAt = __instance.GetItemAt(x, y);
		if (InventoryTweaksPlugin.Allows(__instance, item, x, y) && (itemAt == null || Rules.SameStack(InventoryTweaksPlugin.Describe(itemAt), InventoryTweaksPlugin.Describe(item))))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
{
	typeof(ItemData),
	typeof(int)
})]
internal static class CapacityPatch
{
	private static bool Prefix(Inventory __instance, ItemData item, int stack, ref bool __result)
	{
		if (InventoryTweaksPlugin.IsLocal(__instance) && InventoryTweaksPlugin.IsPickupFiltered(item))
		{
			__result = false;
			return false;
		}
		if (!InventoryTweaksPlugin.HasPins(__instance))
		{
			return true;
		}
		__result = Rules.Capacity(InventoryTweaksPlugin.Describe(__instance), InventoryTweaksPlugin.Pins, __instance.GetWidth(), __instance.GetHeight(), InventoryTweaksPlugin.Describe(item)) >= ((stack <= 0) ? item.m_stack : stack);
		return false;
	}
}
[HarmonyPatch(typeof(Inventory), "GetEmptySlots")]
internal static class EmptyCountPatch
{
	private static void Postfix(Inventory __instance, ref int __result)
	{
		if (InventoryTweaksPlugin.HasPins(__instance) && InventoryTweaksPlugin.StrictAutoPickup.Value)
		{
			__result -= InventoryTweaksPlugin.Pins.Count((SlotPin p) => Rules.InBounds(p, __instance.GetWidth(), __instance.GetHeight()) && __instance.GetItemAt(p.x, p.y) == null);
			__result = Math.Max(0, __result);
		}
	}
}
[HarmonyPatch(typeof(Inventory), "HaveEmptySlot")]
internal static class HaveEmptyPatch
{
	private static void Postfix(Inventory __instance, ref bool __result)
	{
		if (InventoryTweaksPlugin.HasPins(__instance))
		{
			__result = __instance.GetEmptySlots() > 0;
		}
	}
}
internal static class DropGuard
{
	internal static bool Allows(InventoryGrid grid, Inventory source, ItemData item, int amount, Vector2i pos)
	{
		//IL_0009: 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_0021: 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)
		Inventory inventory = grid.GetInventory();
		if (!InventoryTweaksPlugin.AllowsManual(inventory, item, pos.x, pos.y))
		{
			return false;
		}
		ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
		if (itemAt == null || itemAt == item)
		{
			return true;
		}
		if ((itemAt.m_shared.m_name != item.m_shared.m_name || (item.m_shared.m_maxQuality > 1 && itemAt.m_quality != item.m_quality) || itemAt.m_shared.m_maxStackSize == 1) && item.m_stack == amount)
		{
			return InventoryTweaksPlugin.AllowsManual(source, itemAt, item.m_gridPos.x, item.m_gridPos.y);
		}
		if (InventoryTweaksPlugin.HasPins(inventory))
		{
			return Rules.SameStack(InventoryTweaksPlugin.Describe(itemAt), InventoryTweaksPlugin.Describe(item));
		}
		return true;
	}
}
[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
internal static class DropPatch
{
	private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result, out int __state)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		__state = InventoryTweaksPlugin.ManualDepth;
		if (DropGuard.Allows(__instance, fromInventory, item, amount, pos))
		{
			InventoryTweaksPlugin.ManualDepth++;
			return true;
		}
		__result = false;
		return false;
	}

	private static Exception Finalizer(Exception __exception, int __state)
	{
		InventoryTweaksPlugin.ManualDepth = __state;
		return __exception;
	}
}
[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
internal static class SelectionPatch
{
	private static bool Prefix(InventoryGui __instance, InventoryGrid grid, Vector2i pos, ItemData ___m_dragItem, Inventory ___m_dragInventory, int ___m_dragAmount)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (___m_dragItem == null || DropGuard.Allows(grid, ___m_dragInventory, ___m_dragItem, ___m_dragAmount, pos))
		{
			return true;
		}
		InventoryTweaksPlugin.Notify(ModText.CannotPlace);
		return false;
	}
}
[HarmonyPatch(typeof(Humanoid), "Pickup", new Type[]
{
	typeof(GameObject),
	typeof(bool),
	typeof(bool)
})]
internal static class PickupPatch
{
	private static bool Prefix(Humanoid __instance, GameObject go, ref bool __result, out int __state)
	{
		__state = (((object)__instance == Player.m_localPlayer) ? __instance.GetInventory().NrOfItemsIncludingStacks() : (-1));
		if (__state >= 0 && InventoryTweaksPlugin.AutoPickupDepth > 0)
		{
			ItemDrop val = (Object.op_Implicit((Object)(object)go) ? go.GetComponent<ItemDrop>() : null);
			if (Object.op_Implicit((Object)(object)val) && InventoryTweaksPlugin.IsPickupFiltered(val.m_itemData))
			{
				__result = false;
				return false;
			}
		}
		return true;
	}

	private static void Postfix(Humanoid __instance, int __state)
	{
		if (__state >= 0 && (object)__instance == Player.m_localPlayer && __instance.GetInventory().NrOfItemsIncludingStacks() > __state)
		{
			InventoryTweaksPlugin.QueuePickupCombine();
		}
	}
}
[HarmonyPatch(typeof(Player), "Save")]
internal static class CharacterSavePatch
{
	private static void Prefix(Player __instance)
	{
		if (__instance == Player.m_localPlayer && InventoryTweaksPlugin.EnsurePins())
		{
			InventoryTweaksPlugin.SavePins();
		}
	}
}
[HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")]
internal static class GridPatch
{
	private static void Postfix(InventoryGrid __instance, Inventory inventory, List<InventoryElement> ___m_elements)
	{
		if (InventoryTweaksPlugin.IsLocal(inventory))
		{
			InventoryUi.UpdateGrid(__instance, ___m_elements);
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "Awake")]
internal static class GuiAwakePatch
{
	private static void Postfix(InventoryGui __instance)
	{
		InventoryUi.EnsureButton(__instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "UpdateInventory")]
internal static class GuiUpdatePatch
{
	private static void Postfix(InventoryGui __instance)
	{
		InventoryUi.EnsureButton(__instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "Show")]
internal static class GuiShowVisibilityPatch
{
	private static void Postfix(InventoryGui __instance)
	{
		InventoryUi.UpdateVisibility(__instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
internal static class GuiContainerVisibilityPatch
{
	private static void Postfix(InventoryGui __instance)
	{
		InventoryUi.UpdateVisibility(__instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "CloseContainer")]
internal static class GuiCloseContainerVisibilityPatch
{
	private static void Postfix(InventoryGui __instance)
	{
		InventoryUi.UpdateVisibility(__instance);
	}
}
internal sealed class BulkTransferContext
{
	internal Inventory Source;

	internal Inventory Target;
}
[HarmonyPatch(typeof(Inventory), "StackAll", new Type[]
{
	typeof(Inventory),
	typeof(bool)
})]
internal static class BulkTransferContextPatch
{
	[ThreadStatic]
	internal static BulkTransferContext Current;

	internal static void Prefix(Inventory __instance, Inventory fromInventory, out BulkTransferContext __state)
	{
		__state = Current;
		Current = ((InventoryTweaksPlugin.IsLocal(fromInventory) && __instance != fromInventory) ? new BulkTransferContext
		{
			Source = fromInventory,
			Target = __instance
		} : null);
	}

	internal static Exception Finalizer(Exception __exception, BulkTransferContext __state)
	{
		Current = __state;
		return __exception;
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
internal static class PinnedBulkTransferPatch
{
	internal static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
	{
		BulkTransferContext current = BulkTransferContextPatch.Current;
		if (current == null || item == null || __instance != current.Target || !current.Source.ContainsItem(item) || !InventoryTweaksPlugin.HasPins(current.Source) || !Rules.ProtectsFromBulkTransfer(InventoryTweaksPlugin.Pins, InventoryTweaksPlugin.Describe(item)))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
internal static class InventoryUi
{
	private sealed class FilterIconView
	{
		internal PickupFilterEntry entry;

		internal InventoryActionButton button;

		internal UITooltip tooltip;

		internal Image icon;

		internal RectTransform visual;

		internal RectTransform crossA;

		internal RectTransform crossB;
	}

	private static InventoryGui owner;

	private static Button combineButton;

	private static Button modeButton;

	private static Button automaticButton;

	private static TMP_Text automaticLabel;

	private static Button pinBorderButton;

	private static Image pinBorderFill;

	private static Button resetButton;

	private static TMP_Text resetLabel;

	private static Button filterVisibilityButton;

	private static TMP_Text filterVisibilityLabel;

	private static TMP_Text modeLabel;

	private static TMP_Text combineLabel;

	private static TMP_Text inventoryHints;

	private static GameObject filterRoot;

	private static Image inventoryBackground;

	private static int renderedFilterRevision = -1;

	private static readonly List<FilterIconView> filterIcons = new List<FilterIconView>();

	private static readonly List<SlotDecoration> decorations = new List<SlotDecoration>();

	private static readonly Dictionary<Sprite, Sprite> grayIcons = new Dictionary<Sprite, Sprite>();

	internal static void EnsureButton(InventoryGui gui)
	{
		//IL_07d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0806: Unknown result type (might be due to invalid IL or missing references)
		//IL_0811: Unknown result type (might be due to invalid IL or missing references)
		//IL_081b: Unknown result type (might be due to invalid IL or missing references)
		//IL_081c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0827: Unknown result type (might be due to invalid IL or missing references)
		//IL_082c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0840: Unknown result type (might be due to invalid IL or missing references)
		//IL_0875: Unknown result type (might be due to invalid IL or missing references)
		//IL_087a: Unknown result type (might be due to invalid IL or missing references)
		//IL_087b: Unknown result type (might be due to invalid IL or missing references)
		//IL_088d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0894: Unknown result type (might be due to invalid IL or missing references)
		//IL_089b: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_08bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Invalid comparison between Unknown and I4
		//IL_012f: 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_099b: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_09af: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_09cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_09dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a61: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a66: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a67: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a68: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a6d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a6e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a75: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a7c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a87: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a91: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a92: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a9d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab6: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0397: Expected O, but got Unknown
		//IL_0b18: Unknown result type (might be due to invalid IL or missing references)
		//IL_0afd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0424: Unknown result type (might be due to invalid IL or missing references)
		//IL_042e: Expected O, but got Unknown
		//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04df: Expected O, but got Unknown
		//IL_0b6e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b73: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b74: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b75: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b7a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b7b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b82: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b89: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b94: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b9e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b9f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0baa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0baf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bc3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0537: Unknown result type (might be due to invalid IL or missing references)
		//IL_053c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_0558: Unknown result type (might be due to invalid IL or missing references)
		//IL_055d: Unknown result type (might be due to invalid IL or missing references)
		//IL_055e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0568: Unknown result type (might be due to invalid IL or missing references)
		//IL_0569: Unknown result type (might be due to invalid IL or missing references)
		//IL_0573: Unknown result type (might be due to invalid IL or missing references)
		//IL_057e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0592: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c3a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c3f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c40: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c41: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c46: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c47: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c4e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c55: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c60: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c6a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c6b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c76: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c7b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c8f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0628: Unknown result type (might be due to invalid IL or missing references)
		//IL_0632: Expected O, but got Unknown
		//IL_06bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c9: Expected O, but got Unknown
		//IL_0756: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b8: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)gui) || !Object.op_Implicit((Object)(object)gui.m_player))
		{
			return;
		}
		if ((Object)(object)owner != (Object)(object)gui || !Object.op_Implicit((Object)(object)combineButton))
		{
			if (Object.op_Implicit((Object)(object)combineButton))
			{
				Object.Destroy((Object)(object)((Component)combineButton).gameObject);
			}
			if (Object.op_Implicit((Object)(object)filterRoot))
			{
				Object.Destroy((Object)(object)filterRoot);
			}
			filterRoot = null;
			filterIcons.Clear();
			renderedFilterRevision = -1;
			owner = gui;
			inventoryBackground = FindInventoryBackground(gui);
			Button val = (Object.op_Implicit((Object)(object)gui.m_takeAllButton) ? gui.m_takeAllButton : gui.m_craftButton);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			GameObject val2 = new GameObject("InventoryTweaks_Combine", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(InventoryActionButton)
			});
			val2.transform.SetParent((Transform)(object)gui.m_player, false);
			Image component = val2.GetComponent<Image>();
			Graphic targetGraphic = ((Selectable)val).targetGraphic;
			Image val3 = (Image)(object)((targetGraphic is Image) ? targetGraphic : null);
			if (Object.op_Implicit((Object)(object)val3))
			{
				component.sprite = val3.sprite;
				component.type = val3.type;
				((Graphic)component).color = ((Graphic)val3).color;
				((Graphic)component).material = ((Graphic)val3).material;
				component.pixelsPerUnitMultiplier = val3.pixelsPerUnitMultiplier;
			}
			combineButton = val2.GetComponent<Button>();
			((Selectable)combineButton).targetGraphic = (Graphic)(object)component;
			((Selectable)combineButton).colors = ((Selectable)val).colors;
			((Selectable)combineButton).spriteState = ((Selectable)val).spriteState;
			((Selectable)combineButton).transition = (Transition)(((int)((Selectable)val).transition == 3) ? 1 : ((int)((Selectable)val).transition));
			Navigation navigation = ((Selectable)combineButton).navigation;
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)combineButton).navigation = navigation;
			((InventoryActionButton)(object)combineButton).Command = InventoryButtonAction.Combine;
			GameObject val4 = new GameObject("Text", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			val4.transform.SetParent(val2.transform, false);
			TMP_Text val5 = (combineLabel = val4.GetComponent<TMP_Text>());
			TMP_Text componentInChildren = ((Component)val).GetComponentInChildren<TMP_Text>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				val5.font = componentInChildren.font;
				val5.fontSharedMaterial = componentInChildren.fontSharedMaterial;
				val5.fontStyle = componentInChildren.fontStyle;
				((Graphic)val5).color = ((Graphic)componentInChildren).color;
				val5.fontSize = Mathf.Min(18f, componentInChildren.fontSize);
			}
			val5.text = ModText.Combine;
			val5.alignment = (TextAlignmentOptions)514;
			((Graphic)val5).raycastTarget = false;
			val5.enableAutoSizing = true;
			val5.fontSizeMin = 12f;
			val5.fontSizeMax = 18f;
			RectTransform val6 = (RectTransform)val4.transform;
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = new Vector2(7f, 2f);
			val6.offsetMax = new Vector2(-7f, -2f);
			UITooltip obj = val2.AddComponent<UITooltip>();
			ConfigureTooltip(obj, gui, val);
			obj.m_topic = ModText.Combine;
			obj.m_text = ModText.CombineHint;
			if (Object.op_Implicit((Object)(object)modeButton))
			{
				Object.Destroy((Object)(object)((Component)modeButton).gameObject);
			}
			modeButton = Object.Instantiate<Button>(combineButton, (Transform)(object)gui.m_player, false);
			((Object)modeButton).name = "InventoryTweaks_Mode";
			modeButton.onClick = new ButtonClickedEvent();
			((InventoryActionButton)(object)modeButton).Command = InventoryButtonAction.TogglePlacement;
			modeLabel = ((Component)modeButton).GetComponentInChildren<TMP_Text>(true);
			UITooltip component2 = ((Component)modeButton).GetComponent<UITooltip>();
			ConfigureTooltip(component2, gui, val);
			component2.m_topic = ModText.ModeTitle;
			component2.m_text = ModText.ModeHint;
			if (Object.op_Implicit((Object)(object)automaticButton))
			{
				Object.Destroy((Object)(object)((Component)automaticButton).gameObject);
			}
			automaticButton = Object.Instantiate<Button>(combineButton, (Transform)(object)gui.m_player, false);
			((Object)automaticButton).name = "InventoryTweaks_AutomaticCombine";
			automaticButton.onClick = new ButtonClickedEvent();
			((InventoryActionButton)(object)automaticButton).Command = InventoryButtonAction.ToggleAutomaticCombine;
			automaticLabel = ((Component)automaticButton).GetComponentInChildren<TMP_Text>(true);
			automaticLabel.enableAutoSizing = false;
			automaticLabel.fontSize = 18f;
			UITooltip component3 = ((Component)automaticButton).GetComponent<UITooltip>();
			ConfigureTooltip(component3, gui, val);
			component3.m_topic = ModText.CombiningModeTitle;
			component3.m_text = ModText.CombiningModeHint;
			if (Object.op_Implicit((Object)(object)pinBorderButton))
			{
				Object.Destroy((Object)(object)((Component)pinBorderButton).gameObject);
			}
			pinBorderButton = Object.Instantiate<Button>(combineButton, (Transform)(object)gui.m_player, false);
			((Object)pinBorderButton).name = "InventoryTweaks_PinBorder";
			pinBorderButton.onClick = new ButtonClickedEvent();
			((InventoryActionButton)(object)pinBorderButton).Command = InventoryButtonAction.TogglePinnedSlotBorder;
			TMP_Text componentInChildren2 = ((Component)pinBorderButton).GetComponentInChildren<TMP_Text>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren2))
			{
				((Component)componentInChildren2).gameObject.SetActive(false);
			}
			GameObject val7 = new GameObject("StateColor", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val7.transform.SetParent(((Component)pinBorderButton).transform, false);
			RectTransform val8 = (RectTransform)val7.transform;
			val8.anchorMin = Vector2.zero;
			val8.anchorMax = Vector2.one;
			val8.offsetMin = new Vector2(5f, 5f);
			val8.offsetMax = new Vector2(-5f, -5f);
			pinBorderFill = val7.GetComponent<Image>();
			((Graphic)pinBorderFill).raycastTarget = false;
			UITooltip component4 = ((Component)pinBorderButton).GetComponent<UITooltip>();
			ConfigureTooltip(component4, gui, val);
			component4.m_topic = ModText.PinBorderTitle;
			component4.m_text = ModText.PinBorderHint(InventoryTweaksPlugin.ShowPinnedSlotBorder.Value);
			if (Object.op_Implicit((Object)(object)resetButton))
			{
				Object.Destroy((Object)(object)((Component)resetButton).gameObject);
			}
			resetButton = Object.Instantiate<Button>(combineButton, (Transform)(object)gui.m_player, false);
			((Object)resetButton).name = "InventoryTweaks_Reset";
			resetButton.onClick = new ButtonClickedEvent();
			((InventoryActionButton)(object)resetButton).Command = InventoryButtonAction.ResetPins;
			resetLabel = ((Component)resetButton).GetComponentInChildren<TMP_Text>(true);
			UITooltip component5 = ((Component)resetButton).GetComponent<UITooltip>();
			ConfigureTooltip(component5, gui, val);
			component5.m_topic = ModText.Reset;
			component5.m_text = ModText.ResetHint;
			if (Object.op_Implicit((Object)(object)filterVisibilityButton))
			{
				Object.Destroy((Object)(object)((Component)filterVisibilityButton).gameObject);
			}
			filterVisibilityButton = Object.Instantiate<Button>(combineButton, (Transform)(object)gui.m_player, false);
			((Object)filterVisibilityButton).name = "InventoryTweaks_FilterVisibility";
			filterVisibilityButton.onClick = new ButtonClickedEvent();
			((InventoryActionButton)(object)filterVisibilityButton).Command = InventoryButtonAction.TogglePickupFilterVisibility;
			filterVisibilityLabel = ((Component)filterVisibilityButton).GetComponentInChildren<TMP_Text>(true);
			UITooltip component6 = ((Component)filterVisibilityButton).GetComponent<UITooltip>();
			ConfigureTooltip(component6, gui, val);
			component6.m_topic = ModText.FilterVisibilityTitle;
			component6.m_text = ModText.FilterVisibilityHint;
			if (Object.op_Implicit((Object)(object)inventoryHints))
			{
				Object.Destroy((Object)(object)((Component)inventoryHints).gameObject);
			}
			inventoryHints = Object.Instantiate<TMP_Text>(combineLabel, (Transform)(object)gui.m_player, false);
			((Object)inventoryHints).name = "InventoryTweaks_ControlHints";
			((Graphic)inventoryHints).color = Color.white;
			inventoryHints.alignment = (TextAlignmentOptions)257;
			inventoryHints.enableAutoSizing = false;
			inventoryHints.fontSize = combineLabel.fontSize;
			inventoryHints.textWrappingMode = (TextWrappingModes)0;
			((Graphic)inventoryHints).raycastTarget = false;
			inventoryHints.lineSpacing = 4f;
			inventoryHints.margin = Vector4.zero;
		}
		if (UpdateVisibility(gui))
		{
			Vector2 value = InventoryTweaksPlugin.ButtonOffset.Value;
			RectTransform val9 = (RectTransform)((Component)combineButton).transform;
			Vector2 val10 = default(Vector2);
			((Vector2)(ref val10))..ctor(0f, 0f);
			val9.anchorMax = val10;
			val9.anchorMin = val10;
			val9.pivot = new Vector2(0f, 1f);
			val9.anchoredPosition = value + new Vector2(76f, 0f);
			val9.sizeDelta = new Vector2(140f, 30f);
			((Selectable)combineButton).interactable = Object.op_Implicit((Object)(object)Player.m_localPlayer) && !InventoryTweaksPlugin.IsDragging();
			RectTransform val11 = (RectTransform)((Component)modeButton).transform;
			((Vector2)(ref val10))..ctor(0f, 0f);
			val11.anchorMax = val10;
			val11.anchorMin = val10;
			val11.pivot = new Vector2(0f, 1f);
			val11.anchoredPosition = value + new Vector2(224f, 0f);
			val11.sizeDelta = new Vector2(112f, 30f);
			((Selectable)modeButton).interactable = Object.op_Implicit((Object)(object)Player.m_localPlayer);
			modeLabel.text = ModText.Mode(InventoryTweaksPlugin.StrictAutoPickup.Value);
			combineLabel.text = ModText.Combine;
			UITooltip component7 = ((Component)combineButton).GetComponent<UITooltip>();
			if (!Object.op_Implicit((Object)(object)component7.m_tooltipPrefab))
			{
				ConfigureTooltip(component7, gui, gui.m_takeAllButton);
			}
			component7.m_topic = ModText.Combine;
			component7.m_text = ModText.CombineHint;
			UITooltip component8 = ((Component)modeButton).GetComponent<UITooltip>();
			if (!Object.op_Implicit((Object)(object)component8.m_tooltipPrefab))
			{
				ConfigureTooltip(component8, gui, gui.m_takeAllButton);
			}
			component8.m_topic = ModText.ModeTitle;
			component8.m_text = ModText.ModeHint;
			RectTransform val12 = (RectTransform)((Component)automaticButton).transform;
			val10 = (val12.anchorMin = (val12.anchorMax = Vector2.zero));
			val12.pivot = new Vector2(0f, 1f);
			val12.anchoredPosition = value;
			val12.sizeDelta = new Vector2(30f, 30f);
			((Selectable)automaticButton).interactable = Object.op_Implicit((Object)(object)Player.m_localPlayer);
			automaticLabel.text = (InventoryTweaksPlugin.AutoCombineOnPickup.Value ? "A" : "M");
			UITooltip component9 = ((Component)automaticButton).GetComponent<UITooltip>();
			if (!Object.op_Implicit((Object)(object)component9.m_tooltipPrefab))
			{
				ConfigureTooltip(component9, gui, gui.m_takeAllButton);
			}
			component9.m_topic = ModText.CombiningModeTitle;
			component9.m_text = ModText.CombiningModeHint;
			RectTransform val14 = (RectTransform)((Component)pinBorderButton).transform;
			val10 = (val14.anchorMin = (val14.anchorMax = Vector2.zero));
			val14.pivot = new Vector2(0f, 1f);
			val14.anchoredPosition = value + new Vector2(38f, 0f);
			val14.sizeDelta = new Vector2(30f, 30f);
			((Selectable)pinBorderButton).interactable = Object.op_Implicit((Object)(object)Player.m_localPlayer);
			bool value2 = InventoryTweaksPlugin.ShowPinnedSlotBorder.Value;
			((Graphic)pinBorderFill).color = (value2 ? new Color(1f, 0.78f, 0.12f, 1f) : new Color(0.32f, 0.2f, 0.12f, 1f));
			UITooltip component10 = ((Component)pinBorderButton).GetComponent<UITooltip>();
			if (!Object.op_Implicit((Object)(object)component10.m_tooltipPrefab))
			{
				ConfigureTooltip(component10, gui, gui.m_takeAllButton);
			}
			component10.m_topic = ModText.PinBorderTitle;
			component10.m_text = ModText.PinBorderHint(value2);
			RectTransform val16 = (RectTransform)((Component)resetButton).transform;
			val10 = (val16.anchorMin = (val16.anchorMax = Vector2.zero));
			val16.pivot = new Vector2(0f, 1f);
			val16.anchoredPosition = value + new Vector2(344f, 0f);
			val16.sizeDelta = new Vector2(80f, 30f);
			((Selectable)resetButton).interactable = Object.op_Implicit((Object)(object)Player.m_localPlayer);
			resetLabel.text = ModText.Reset;
			UITooltip component11 = ((Component)resetButton).GetComponent<UITooltip>();
			if (!Object.op_Implicit((Object)(object)component11.m_tooltipPrefab))
			{
				ConfigureTooltip(component11, gui, gui.m_takeAllButton);
			}
			component11.m_topic = ModText.Reset;
			component11.m_text = ModText.ResetHint;
			RectTransform val18 = (RectTransform)((Component)filterVisibilityButton).transform;
			val10 = (val18.anchorMin = (val18.anchorMax = Vector2.zero));
			val18.pivot = new Vector2(0f, 1f);
			val18.anchoredPosition = value + new Vector2(432f, 0f);
			val18.sizeDelta = new Vector2(140f, 30f);
			((Selectable)filterVisibilityButton).interactable = Object.op_Implicit((Object)(object)Player.m_localPlayer);
			filterVisibilityLabel.text = ModText.FilterVisibility(InventoryTweaksPlugin.ShowPickupFilter.Value);
			UITooltip component12 = ((Component)filterVisibilityButton).GetComponent<UITooltip>();
			if (!Object.op_Implicit((Object)(object)component12.m_tooltipPrefab))
			{
				ConfigureTooltip(component12, gui, gui.m_takeAllButton);
			}
			component12.m_topic = ModText.FilterVisibilityTitle;
			component12.m_text = ModText.FilterVisibilityHint;
			UpdateFilterIcons(gui);
			UpdateHints(gui);
		}
	}

	private static void UpdateHints(InventoryGui gui)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: 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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)inventoryHints))
		{
			RectTransform val = (RectTransform)inventoryHints.transform;
			Vector2 anchorMin = (val.anchorMax = Vector2.zero);
			val.anchorMin = anchorMin;
			val.pivot = new Vector2(0f, 1f);
			val.anchoredPosition = InventoryTweaksPlugin.ButtonOffset.Value + new Vector2(0f, -38f);
			Rect rect = gui.m_player.rect;
			val.sizeDelta = new Vector2(Mathf.Max(0f, ((Rect)(ref rect)).width - InventoryTweaksPlugin.ButtonOffset.Value.x), Mathf.Max(48f, combineLabel.fontSize * 3f));
			inventoryHints.fontSize = combineLabel.fontSize;
			inventoryHints.text = ModText.InventoryHints;
		}
	}

	internal static bool UpdateVisibility(InventoryGui gui)
	{
		if (!Object.op_Implicit((Object)(object)gui) || (Object)(object)owner != (Object)(object)gui)
		{
			return false;
		}
		bool flag = !gui.IsContainerOpen() && (!Object.op_Implicit((Object)(object)gui.m_container) || !((Component)gui.m_container).gameObject.activeSelf);
		if (Object.op_Implicit((Object)(object)combineButton))
		{
			((Component)combineButton).gameObject.SetActive(flag);
		}
		if (Object.op_Implicit((Object)(object)automaticButton))
		{
			((Component)automaticButton).gameObject.SetActive(flag);
		}
		if (Object.op_Implicit((Object)(object)pinBorderButton))
		{
			((Component)pinBorderButton).gameObject.SetActive(flag);
		}
		if (Object.op_Implicit((Object)(object)modeButton))
		{
			((Component)modeButton).gameObject.SetActive(flag);
		}
		if (Object.op_Implicit((Object)(object)resetButton))
		{
			((Component)resetButton).gameObject.SetActive(flag);
		}
		if (Object.op_Implicit((Object)(object)filterVisibilityButton))
		{
			((Component)filterVisibilityButton).gameObject.SetActive(flag);
		}
		if (Object.op_Implicit((Object)(object)inventoryHints))
		{
			((Component)inventoryHints).gameObject.SetActive(flag && InventoryTweaksPlugin.ShowControlHints.Value && InventoryTweaksPlugin.PickupFilters.Count == 0);
		}
		if (Object.op_Implicit((Object)(object)filterRoot))
		{
			filterRoot.SetActive(flag && InventoryTweaksPlugin.ShowPickupFilter.Value && filterIcons.Count > 0 && InventoryTweaksPlugin.PickupFilters.Count > 0);
		}
		return flag;
	}

	private static Image FindInventoryBackground(InventoryGui gui)
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: 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)
		Image result = null;
		float num = 0f;
		Image[] componentsInChildren = ((Component)gui.m_player).GetComponentsInChildren<Image>(true);
		foreach (Image val in componentsInChildren)
		{
			if (!Object.op_Implicit((Object)(object)val.sprite) || (Object.op_Implicit((Object)(object)filterRoot) && ((Component)val).transform.IsChildOf(filterRoot.transform)) || (Object.op_Implicit((Object)(object)gui.m_playerGrid) && ((Component)val).transform.IsChildOf(((Component)gui.m_playerGrid).transform)))
			{
				continue;
			}
			Rect rect = ((Graphic)val).rectTransform.rect;
			float width = ((Rect)(ref rect)).width;
			Rect rect2 = gui.m_player.rect;
			if (width < ((Rect)(ref rect2)).width * 0.7f)
			{
				continue;
			}
			float height = ((Rect)(ref rect)).height;
			rect2 = gui.m_player.rect;
			if (!(height < ((Rect)(ref rect2)).height * 0.7f))
			{
				float num2 = ((Rect)(ref rect)).width * ((Rect)(ref rect)).height;
				if (!(num2 <= num))
				{
					result = val;
					num = num2;
				}
			}
		}
		return result;
	}

	private static void ConfigureFilterBackground(Image background, InventoryGui gui)
	{
		//IL_0057: 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_0091: 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)
		Image val = (Object.op_Implicit((Object)(object)inventoryBackground) ? inventoryBackground : FindInventoryBackground(gui));
		((Graphic)background).raycastTarget = false;
		if (!Object.op_Implicit((Object)(object)val))
		{
			((Graphic)background).color = new Color(0.32f, 0.2f, 0.12f, 0.96f);
			return;
		}
		background.sprite = val.sprite;
		background.type = val.type;
		((Graphic)background).color = ((Graphic)val).color;
		((Graphic)background).material = ((Graphic)val).material;
		background.pixelsPerUnitMultiplier = val.pixelsPerUnitMultiplier;
		((Graphic)background).canvasRenderer.SetColor(((Graphic)val).canvasRenderer.GetColor());
	}

	private static void UpdateFilterIcons(InventoryGui gui)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		//IL_0532: Unknown result type (might be due to invalid IL or missing references)
		//IL_0537: Unknown result type (might be due to invalid IL or missing references)
		//IL_053b: Unknown result type (might be due to invalid IL or missing references)
		//IL_052a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0540: Unknown result type (might be due to invalid IL or missing references)
		//IL_055c: Unknown result type (might be due to invalid IL or missing references)
		//IL_056e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0575: Unknown result type (might be due to invalid IL or missing references)
		//IL_057a: Unknown result type (might be due to invalid IL or missing references)
		//IL_057e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0584: Unknown result type (might be due to invalid IL or missing references)
		//IL_0591: Unknown result type (might be due to invalid IL or missing references)
		//IL_0597: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05be: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0569: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0600: Unknown result type (might be due to invalid IL or missing references)
		//IL_060d: Unknown result type (might be due to invalid IL or missing references)
		//IL_061c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0633: Unknown result type (might be due to invalid IL or missing references)
		//IL_0638: Unknown result type (might be due to invalid IL or missing references)
		//IL_063a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0647: Unknown result type (might be due to invalid IL or missing references)
		//IL_064c: Unknown result type (might be due to invalid IL or missing references)
		//IL_065a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0677: Unknown result type (might be due to invalid IL or missing references)
		//IL_067f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0687: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0722: Unknown result type (might be due to invalid IL or missing references)
		//IL_072a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0731: Unknown result type (might be due to invalid IL or missing references)
		//IL_0747: Unknown result type (might be due to invalid IL or missing references)
		//IL_074f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0756: Unknown result type (might be due to invalid IL or missing references)
		//IL_0764: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_07cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0800: Unknown result type (might be due to invalid IL or missing references)
		//IL_080a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0818: Unknown result type (might be due to invalid IL or missing references)
		//IL_0825: Unknown result type (might be due to invalid IL or missing references)
		//IL_082e: Unknown result type (might be due to invalid IL or missing refer