Decompiled source of SmartContainers v1.8.2

plugins\SmartContainers.dll

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

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Flueno / community port")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("SmartContainers port for Valheim 1.0 (Unity 6)")]
[assembly: AssemblyFileVersion("1.8.0.0")]
[assembly: AssemblyInformationalVersion("1.8.0")]
[assembly: AssemblyProduct("SmartContainers")]
[assembly: AssemblyTitle("SmartContainers")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SmartContainers
{
	public enum ConcurrentChestModificationWorkaround
	{
		None,
		ExcludeContainersOpenedByOthers,
		BlockIfOtherContainersAreOpened
	}
	internal static class ConcurrentChestModificationWorkaroundMethods
	{
		public static bool SkipOpenedOthers(this ConcurrentChestModificationWorkaround option)
		{
			return option == ConcurrentChestModificationWorkaround.ExcludeContainersOpenedByOthers;
		}

		public static bool Ignore(this ConcurrentChestModificationWorkaround option)
		{
			return option == ConcurrentChestModificationWorkaround.None;
		}

		public static bool BlockIfAnyOtherOpened(this ConcurrentChestModificationWorkaround option)
		{
			return option == ConcurrentChestModificationWorkaround.BlockIfOtherContainersAreOpened;
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;
	}
	public static class ContainersTracker
	{
		public static ICollection<Container> containerList = new List<Container>();

		public static bool isRearrangingItem;

		public static bool teleportingInProgress;

		public static List<Container> GetNearbyContainers(Vector3 center, bool all = false)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			List<Container> list = new List<Container>();
			int num = (all ? (Mod.range.Value * 2) : Mod.range.Value);
			foreach (Container container in containerList)
			{
				if (!((Object)(object)container == (Object)null) && !((Object)(object)((Component)container).transform == (Object)null) && container.GetInventory() != null && !((Object)(object)((Component)container).GetComponentInParent<Piece>() == (Object)null))
				{
					float num2 = Vector3.Distance(center, ((Component)container).transform.position);
					if ((num <= 0 || num2 < (float)num) && container.CheckAccess(Player.m_localPlayer.GetPlayerID()))
					{
						list.Add(container);
					}
				}
			}
			return list;
		}

		public static void Init()
		{
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			Mod.log.LogDebug((object)$"tracking {array.Length} discovered containers.");
			Container[] array2 = array;
			foreach (Container val in array2)
			{
				if (!((Object)val).name.StartsWith("Treasure") && val.GetInventory() != null && val.m_nview.IsValid() && val.m_nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0L)
				{
					containerList.Add(val);
				}
			}
		}

		public static void CleanupContainersList()
		{
			Mod.log.LogDebug((object)$"cleanup containerList. size before: {containerList.Count}");
			foreach (Container item in containerList.ToList())
			{
				if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).transform == (Object)null || item.GetInventory() == null)
				{
					containerList.Remove(item);
				}
			}
			Mod.log.LogDebug((object)$"cleanup containerList. size after: {containerList.Count}");
		}
	}
	internal static class EnumerableMethods
	{
		public static IEnumerable<R> Map<T, R>(this IEnumerable<T> self, Func<T, R> selector)
		{
			return self.Select(selector);
		}

		public static T Reduce<T>(this IEnumerable<T> self, Func<T, T, T> func)
		{
			return self.Aggregate(func);
		}

		public static T Reduce<T>(this IEnumerable<T> self, T seed, Func<T, T, T> func)
		{
			return self.Aggregate(seed, func);
		}

		public static IEnumerable<R> FlatMap<T, R>(this IEnumerable<T> self, Func<T, IEnumerable<R>> func)
		{
			return self.SelectMany(func);
		}

		public static IEnumerable<T> Filter<T>(this IEnumerable<T> self, Func<T, bool> predicate)
		{
			return self.Where(predicate);
		}
	}
	public static class GuiFactory
	{
		public static void CreateMrgDialog(out GameObject dialogObj, string dlgUid, string label1, string label2, string label3, UnityAction onFirst, UnityAction onSecond, UnityAction onThird)
		{
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Expected O, but got Unknown
			//IL_02d5: 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_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Expected O, but got Unknown
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Expected O, but got Unknown
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: 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_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ca: 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_05f6: 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_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06eb: Expected O, but got Unknown
			SplitDialog splitDialog = InventoryGui.instance.m_splitDialog;
			if ((Object)(object)splitDialog == (Object)null)
			{
				throw new InvalidOperationException("InventoryGui.m_splitDialog is missing");
			}
			Transform clone = Object.Instantiate<Transform>(((Component)splitDialog).transform, ((Component)splitDialog).transform.parent);
			((Object)clone).name = dlgUid;
			dialogObj = ((Component)clone).gameObject;
			dialogObj.SetActive(false);
			SplitDialog component = dialogObj.GetComponent<SplitDialog>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			Transform panel = FindChildRecursive(clone, "Panel") ?? clone;
			HideIfExists(panel, "Slider");
			HideIfExists(panel, "splitSlider");
			HideIfExists(clone, "Slider");
			if ((Object)(object)dialogObj.GetComponentInChildren<SplitDialog>() == (Object)null)
			{
				FindButton(dialogObj, "Cancel", "Button_cancel", "splitCancel");
			}
			Button val = FindButton(dialogObj, "Cancel", "Button_cancel", "m_splitCancelButton", "splitCancel");
			Button val2 = FindButton(dialogObj, "Ok", "OK", "Button_ok", "m_splitOkButton", "splitOk");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				Button[] componentsInChildren = dialogObj.GetComponentsInChildren<Button>(true);
				if (componentsInChildren.Length >= 2)
				{
					if (val == null)
					{
						val = componentsInChildren[0];
					}
					if (val2 == null)
					{
						val2 = componentsInChildren[1];
					}
				}
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("Could not locate SplitDialog action buttons for merge prompt");
			}
			if ((Object)(object)((Component)val).GetComponent<UIGamePad>() == (Object)null)
			{
				((Component)val).gameObject.AddComponent<UIGamePad>();
			}
			if ((Object)(object)((Component)val2).GetComponent<UIGamePad>() == (Object)null)
			{
				((Component)val2).gameObject.AddComponent<UIGamePad>();
			}
			Transform obj = Object.Instantiate<Transform>(((Component)val2).transform, ((Component)val2).transform.parent);
			((Object)obj).name = "Button_3";
			Button component2 = ((Component)obj).GetComponent<Button>();
			if ((Object)(object)((Component)component2).GetComponent<UIGamePad>() == (Object)null)
			{
				((Component)component2).gameObject.AddComponent<UIGamePad>();
			}
			SetButtonLabel(val, label1);
			SetButtonLabel(val2, label2);
			SetButtonLabel(component2, label3);
			Transform transform = ((Component)val).transform;
			RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Transform transform2 = ((Component)val2).transform;
			RectTransform val4 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
			Transform transform3 = ((Component)component2).transform;
			RectTransform val5 = (RectTransform)(object)((transform3 is RectTransform) ? transform3 : null);
			if ((Object)(object)val3 != (Object)null)
			{
				val3.anchoredPosition = new Vector2(-160f, val3.anchoredPosition.y);
			}
			if ((Object)(object)val4 != (Object)null)
			{
				val4.anchoredPosition = new Vector2(0f, val4.anchoredPosition.y);
			}
			if ((Object)(object)val5 != (Object)null)
			{
				val5.anchoredPosition = new Vector2(160f, val5.anchoredPosition.y);
			}
			InitJoyKey(((Component)val).transform, "JoyTabLeft", "(LB)");
			InitJoyKey(((Component)val2).transform, "JoyTabRight", "(RB)");
			InitJoyKey(((Component)component2).transform, "", "");
			GameObject val6 = new GameObject("TextArea", new Type[1] { typeof(RectTransform) });
			val6.transform.SetParent(((Object)(object)panel != (Object)null) ? panel : clone, false);
			RectTransform component3 = val6.GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.5f, 0.5f);
			component3.anchorMax = new Vector2(0.5f, 0.5f);
			component3.sizeDelta = new Vector2(520f, 220f);
			component3.anchoredPosition = new Vector2(0f, 40f);
			GameObject val7 = new GameObject("ScrollArea", new Type[1] { typeof(RectTransform) });
			val7.transform.SetParent(val6.transform, false);
			RectTransform component4 = val7.GetComponent<RectTransform>();
			component4.anchorMin = Vector2.zero;
			component4.anchorMax = Vector2.one;
			component4.offsetMin = Vector2.zero;
			component4.offsetMax = Vector2.zero;
			GameObject val8 = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			val8.transform.SetParent(val7.transform, false);
			RectTransform component5 = val8.GetComponent<RectTransform>();
			component5.anchorMin = Vector2.zero;
			component5.anchorMax = Vector2.one;
			component5.offsetMin = Vector2.zero;
			component5.offsetMax = Vector2.zero;
			RectTransform rectTransform = ((TMP_Text)CreateTmp("Name", val8.transform, 18f, new Color(0.79f, 0.75f, 0.28f, 1f))).rectTransform;
			rectTransform.anchorMin = new Vector2(0f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.sizeDelta = new Vector2(0f, 48f);
			rectTransform.anchoredPosition = Vector2.zero;
			RectTransform rectTransform2 = ((TMP_Text)CreateTmp("Description", val8.transform, 16f, new Color(0.8f, 0.8f, 0.8f, 1f))).rectTransform;
			rectTransform2.anchorMin = new Vector2(0f, 0f);
			rectTransform2.anchorMax = new Vector2(1f, 1f);
			rectTransform2.offsetMin = new Vector2(0f, 0f);
			rectTransform2.offsetMax = new Vector2(0f, -52f);
			Transform val9 = CreateButton("Selector", "--select--", val6.transform, new Vector2(380f, 24f), new Vector2(0.5f, -0.1f));
			((RectTransform)((val9 is RectTransform) ? val9 : null)).anchoredPosition = new Vector2(0f, -130f);
			GameObject val10 = Find("RecipeList");
			if ((Object)(object)val10 != (Object)null)
			{
				GameObject obj2 = Object.Instantiate<GameObject>(val10, ((Object)(object)panel != (Object)null) ? panel : clone);
				((Object)obj2).name = "SelectorDlg";
				obj2.SetActive(false);
				Transform transform4 = obj2.transform;
				RectTransform val11 = (RectTransform)(object)((transform4 is RectTransform) ? transform4 : null);
				if ((Object)(object)val11 != (Object)null)
				{
					val11.anchoredPosition = new Vector2(220f, 0f);
					val11.SetSizeWithCurrentAnchors((Axis)1, 150f);
				}
				Transform val12 = obj2.transform.Find("Recipes/ListRoot");
				if ((Object)(object)val12 != (Object)null)
				{
					for (int num = val12.childCount - 1; num >= 0; num--)
					{
						Object.Destroy((Object)(object)((Component)val12.GetChild(num)).gameObject);
					}
				}
				((UnityEvent)((Component)val9).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					Transform obj4 = (((Object)(object)panel != (Object)null) ? panel : clone).Find("SelectorDlg");
					GameObject val14 = ((obj4 != null) ? ((Component)obj4).gameObject : null);
					if ((Object)(object)val14 != (Object)null)
					{
						val14.SetActive(!val14.activeSelf);
					}
				});
			}
			Transform obj3 = Object.Instantiate<Transform>(((Component)InventoryGui.instance.m_takeAllButton).transform.Find("Text"), val6.transform);
			((Object)obj3).name = "TargetGroupLabel";
			TextMeshProUGUI component6 = ((Component)obj3).GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component6 != (Object)null)
			{
				((TMP_Text)component6).text = "Target group:";
			}
			RectTransform val13 = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null);
			if ((Object)(object)val13 != (Object)null)
			{
				val13.anchoredPosition = new Vector2(-180f, -130f);
			}
			InitJoyKey(val9, "", "");
			((UnityEventBase)val.onClick).RemoveAllListeners();
			((UnityEventBase)val2.onClick).RemoveAllListeners();
			((UnityEventBase)component2.onClick).RemoveAllListeners();
			((UnityEvent)val.onClick).AddListener(onFirst);
			((UnityEvent)val2.onClick).AddListener(onSecond);
			((UnityEvent)component2.onClick).AddListener(onThird);
		}

		public static Transform AddContainerGuiButton(string btnObjName, string text, Vector2 size, Vector2 pos)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			return CreateButton(btnObjName, text, ((Component)InventoryGui.instance.m_takeAllButton).transform.parent, size, pos);
		}

		public static Transform CreateButton(string btnObjName, string text, Transform parent, Vector2 size, Vector2 pos)
		{
			//IL_0023: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = Object.Instantiate<Transform>(((Component)InventoryGui.instance.m_takeAllButton).transform, parent);
			((Object)obj).name = btnObjName;
			Transform obj2 = ((obj is RectTransform) ? obj : null);
			((RectTransform)obj2).SetSizeWithCurrentAnchors((Axis)0, size.x);
			((RectTransform)obj2).SetSizeWithCurrentAnchors((Axis)1, size.y);
			Transform obj3 = obj2.Find("Text");
			RectTransform val = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null);
			if ((Object)(object)val != (Object)null)
			{
				val.SetSizeWithCurrentAnchors((Axis)0, size.x);
				val.SetSizeWithCurrentAnchors((Axis)1, size.y);
				TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					((TMP_Text)component).text = text;
				}
			}
			((RectTransform)obj2).pivot = pos;
			return obj2;
		}

		public static void InitJoyKey(Transform btnComponent, string joyKeyCode, string tooltip)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			UIGamePad val = ((Component)btnComponent).GetComponent<UIGamePad>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)btnComponent).gameObject.AddComponent<UIGamePad>();
			}
			Transform val2 = btnComponent.Find("Text");
			if (!((Object)(object)val2 == (Object)null))
			{
				Transform val3 = Object.Instantiate<Transform>(val2, ((Component)val).transform);
				TextMeshProUGUI component = ((Component)val3).GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					((TMP_Text)component).text = tooltip;
					((Graphic)component).color = new Color(0.8f, 0.8f, 0.8f, 1f);
					((Behaviour)component).enabled = ZInput.IsGamepadActive();
				}
				val3.position += new Vector3(0f, 13f, 0f);
				if ((Object)(object)val.m_hint != (Object)null)
				{
					Object.Destroy((Object)(object)val.m_hint);
				}
				val.m_hint = ((Component)val3).gameObject;
				val.m_zinputKey = joyKeyCode;
			}
		}

		public static void FillResList(RectTransform parent, ICollection<string> names, ICollection<Object> m_resObjects, Action<string> cb)
		{
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			foreach (Object m_resObject in m_resObjects)
			{
				Object.Destroy(m_resObject);
			}
			m_resObjects.Clear();
			float num = 0f;
			GameObject val = Find("RecipeList/Recipes/RecipeElement");
			if ((Object)(object)val == (Object)null)
			{
				Mod.log.LogWarning((object)"RecipeElement not found; merge group selector list unavailable.");
				return;
			}
			foreach (string name in names)
			{
				GameObject val2 = Object.Instantiate<GameObject>(val, (Transform)(object)parent);
				Transform val3 = val2.transform.Find("icon");
				Transform val4 = val2.transform.Find("Durability");
				Transform val5 = val2.transform.Find("QualityLevel");
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val3).gameObject);
				}
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val4).gameObject);
				}
				if ((Object)(object)val5 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val5).gameObject);
				}
				val2.SetActive(true);
				string captured = name;
				Button componentInChildren = val2.GetComponentInChildren<Button>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((UnityEvent)componentInChildren.onClick).AddListener((UnityAction)delegate
					{
						cb(captured);
					});
				}
				Transform transform = val2.transform;
				RectTransform val6 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if ((Object)(object)val6 != (Object)null)
				{
					val6.anchoredPosition = new Vector2(0f, num * -20f);
				}
				TextMeshProUGUI componentInChildren2 = val2.GetComponentInChildren<TextMeshProUGUI>();
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					((TMP_Text)componentInChildren2).text = name;
				}
				m_resObjects.Add((Object)(object)val2);
				num += 1f;
			}
			Rect rect = parent.rect;
			parent.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(((Rect)(ref rect)).height, num * 20f));
		}

		private static GameObject Find(string name)
		{
			GameObject val = GameObject.Find("_GameMain/LoadingGUI/PixelFix/IngameGui/Inventory_screen/root/Crafting/" + name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Mod.log.LogWarning((object)("Failed to locate '" + name + "' GameObject - fallback to IngameGui lookup.."));
			GameObject val2 = GameObject.Find("IngameGui");
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Transform val3 = val2.transform.Find("Inventory_screen/root/Crafting/" + name);
			if (!((Object)(object)val3 != (Object)null))
			{
				return null;
			}
			return ((Component)val3).gameObject;
		}

		private static TextMeshProUGUI CreateTmp(string name, Transform parent, float size, Color color)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).fontSize = size;
			((Graphic)val2).color = color;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)1;
			((TMP_Text)val2).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)257;
			TextMeshProUGUI componentInChildren = ((Component)InventoryGui.instance.m_takeAllButton).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null)
			{
				((TMP_Text)val2).font = ((TMP_Text)componentInChildren).font;
			}
			return val2;
		}

		private static void SetButtonLabel(Button button, string text)
		{
			TextMeshProUGUI componentInChildren = ((Component)button).GetComponentInChildren<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)componentInChildren).text = text;
			}
		}

		private static Button FindButton(GameObject root, params string[] nameHints)
		{
			Button[] componentsInChildren = root.GetComponentsInChildren<Button>(true);
			foreach (Button val in componentsInChildren)
			{
				string name = ((Object)((Component)val).gameObject).name;
				foreach (string value in nameHints)
				{
					if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static Transform FindChildRecursive(Transform root, string name)
		{
			if (((Object)root).name.Equals(name, StringComparison.OrdinalIgnoreCase))
			{
				return root;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform val = FindChildRecursive(root.GetChild(i), name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static void HideIfExists(Transform root, string name)
		{
			Transform val = FindChildRecursive(root, name);
			if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
			Slider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Slider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	public static class Gui_Patch
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<Tuple<string, List<string>>, string> <>9__8_3;

			public static UnityAction <>9__8_0;

			public static Func<Tuple<string, List<string>>, string> <>9__8_4;

			public static UnityAction <>9__8_1;

			public static Func<Tuple<string, List<string>>, string> <>9__8_5;

			public static UnityAction <>9__8_2;

			public static Func<Tuple<string, List<string>>, string> <>9__10_0;

			public static Func<Tuple<string, List<string>>, IEnumerable<string>> <>9__10_1;

			public static Func<TextMeshProUGUI, bool> <>9__10_3;

			public static Func<TextMeshProUGUI, bool> <>9__10_4;

			public static Func<ItemData, bool> <>9__10_6;

			public static Func<ItemData, string> <>9__10_7;

			public static Func<Tuple<string, List<string>>, string> <>9__10_9;

			public static Func<RectTransform, bool> <>9__10_5;

			public static Func<Tuple<string, List<string>>, string> <>9__10_12;

			public static Func<Transform, bool> <>9__11_0;

			internal void <InitButtons>b__8_0()
			{
				if (containersUniqueItems != null && intersectedGroups != null)
				{
					ItemGroupUtils.ExtendGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
				}
				groupsDialogObj.SetActive(false);
			}

			internal string <InitButtons>b__8_3(Tuple<string, List<string>> _)
			{
				return _.Item1;
			}

			internal void <InitButtons>b__8_1()
			{
				if (containersUniqueItems != null)
				{
					ItemGroupUtils.ExtendAndMerge(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
				}
				groupsDialogObj.SetActive(false);
			}

			internal string <InitButtons>b__8_4(Tuple<string, List<string>> _)
			{
				return _.Item1;
			}

			internal void <InitButtons>b__8_2()
			{
				if (containersUniqueItems != null && intersectedGroups != null)
				{
					ItemGroupUtils.MergeAllToSingleGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
				}
				groupsDialogObj.SetActive(false);
			}

			internal string <InitButtons>b__8_5(Tuple<string, List<string>> _)
			{
				return _.Item1;
			}

			internal string <InitMergePromptDlg>b__10_0(Tuple<string, List<string>> _)
			{
				return _.Item1;
			}

			internal IEnumerable<string> <InitMergePromptDlg>b__10_1(Tuple<string, List<string>> _)
			{
				return _.Item2;
			}

			internal bool <InitMergePromptDlg>b__10_3(TextMeshProUGUI t)
			{
				return ((Object)t).name == "Name";
			}

			internal bool <InitMergePromptDlg>b__10_4(TextMeshProUGUI t)
			{
				return ((Object)t).name == "Description";
			}

			internal bool <InitMergePromptDlg>b__10_6(ItemData i)
			{
				return intersectedGroups[0].Item2.Contains(i.SCName());
			}

			internal string <InitMergePromptDlg>b__10_7(ItemData _)
			{
				return Localization.instance.Localize(_.m_shared.m_name);
			}

			internal string <InitMergePromptDlg>b__10_9(Tuple<string, List<string>> _)
			{
				return _.Item1;
			}

			internal bool <InitMergePromptDlg>b__10_5(RectTransform t)
			{
				return ((Object)t).name == "Selector";
			}

			internal string <InitMergePromptDlg>b__10_12(Tuple<string, List<string>> _)
			{
				return _.Item1;
			}

			internal bool <SelectedTargetGroupId>b__11_0(Transform t)
			{
				return ((Object)t).name == "Selector";
			}
		}

		public static bool initialized;

		private static Transform createGroupButton;

		private static Transform storeAllButton;

		public static GameObject groupsDialogObj;

		private static readonly ICollection<Object> groupSelectorItems = new List<Object>();

		private static List<Tuple<string, List<string>>> intersectedGroups;

		private static List<string> containersUniqueItems;

		private static void Postfix(InventoryGui __instance)
		{
			if (Mod.modEnabled.Value && Mod.groupingEnabled.Value && (Object)(object)__instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && !initialized && __instance.IsContainerOpen())
			{
				InitButtons(__instance);
			}
		}

		private static void InitButtons(InventoryGui __instance)
		{
			//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_0091: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			if (!Mod.modEnabled.Value)
			{
				return;
			}
			try
			{
				if ((Mod.groupingEnabled.Value || Mod.unloadAllEnabled.Value) && Mod.createGroupBtnEnabled.Value)
				{
					AddCreateGroupBtn(__instance);
					if (Mod.groupingEnabled.Value && Mod.mergePromptEnabled.Value)
					{
						object obj = <>c.<>9__8_0;
						if (obj == null)
						{
							UnityAction val = delegate
							{
								if (containersUniqueItems != null && intersectedGroups != null)
								{
									ItemGroupUtils.ExtendGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
								}
								groupsDialogObj.SetActive(false);
							};
							<>c.<>9__8_0 = val;
							obj = (object)val;
						}
						object obj2 = <>c.<>9__8_1;
						if (obj2 == null)
						{
							UnityAction val2 = delegate
							{
								if (containersUniqueItems != null)
								{
									ItemGroupUtils.ExtendAndMerge(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
								}
								groupsDialogObj.SetActive(false);
							};
							<>c.<>9__8_1 = val2;
							obj2 = (object)val2;
						}
						object obj3 = <>c.<>9__8_2;
						if (obj3 == null)
						{
							UnityAction val3 = delegate
							{
								if (containersUniqueItems != null && intersectedGroups != null)
								{
									ItemGroupUtils.MergeAllToSingleGroup(SelectedTargetGroupId(), intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList(), containersUniqueItems);
								}
								groupsDialogObj.SetActive(false);
							};
							<>c.<>9__8_2 = val3;
							obj3 = (object)val3;
						}
						GuiFactory.CreateMrgDialog(out groupsDialogObj, "mrgToGroupDialog", "Extend", "Extend&Merge", "Merge All", (UnityAction)obj, (UnityAction)obj2, (UnityAction)obj3);
					}
				}
				if (Mod.unloadAllEnabled.Value && !Mod.unloadAllInsteadStackBtn.Value)
				{
					AddStoreAllBtn(__instance);
				}
				initialized = true;
			}
			catch (Exception ex)
			{
				Mod.log.LogError((object)("Failed to properly patch GUI with additional buttons: " + ex));
				Clean();
			}
			finally
			{
				Mod.log.LogInfo((object)"Initialized UI extensions.");
			}
		}

		private static void AddCreateGroupBtn(InventoryGui __instance)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			createGroupButton = GuiFactory.AddContainerGuiButton("createGroupBtn", "+", new Vector2(45f, 30f), Mod.createGroupBtnPos.Value);
			GuiFactory.InitJoyKey(createGroupButton, "JoyMap", "(RS)");
			((UnityEvent)((Component)createGroupButton).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				//IL_0055: 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_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)__instance.m_playerGrid == (Object)null) && !((Object)(object)__instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting())
				{
					Inventory inventory = __instance.m_containerGrid.GetInventory();
					KeyboardShortcut value;
					if (Mod.unloadAllEnabled.Value)
					{
						value = Mod.unloadAllItemsGroupKeyModifier.Value;
						if (((KeyboardShortcut)(ref value)).IsPressed() || ZInput.GetButton("JoyRTrigger"))
						{
							UnloadItems.AddToUnloadAllItemsFilter(inventory);
							return;
						}
					}
					if (Mod.unloadAllEnabled.Value)
					{
						value = Mod.unloadAllSkipItemsGroupKeyModifier.Value;
						if (((KeyboardShortcut)(ref value)).IsPressed() || ZInput.GetButton("JoyLTrigger"))
						{
							UnloadItems.AddToUnloadAllItemsSkipList(inventory);
							return;
						}
					}
					if (Mod.groupingEnabled.Value)
					{
						containersUniqueItems = ItemGroupUtils.ExtractUniqueItemNames(inventory);
						if (containersUniqueItems.Count >= 2)
						{
							if (Mod.mergePromptEnabled.Value)
							{
								InitMergePromptDlg(inventory);
							}
							else
							{
								ItemGroupUtils.RegisterNewGroup(inventory);
							}
						}
					}
				}
			});
		}

		private static void InitMergePromptDlg(Inventory inventory)
		{
			intersectedGroups = ItemGroupUtils.FindIntersections(containersUniqueItems);
			if (!intersectedGroups.Any())
			{
				ItemGroupUtils.RegisterNewGroup(inventory);
				return;
			}
			if ((Object)(object)groupsDialogObj == (Object)null)
			{
				ItemGroupUtils.RegisterNewGroup(inventory);
				return;
			}
			List<string> second = intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).ToList();
			HashSet<string> intersectedItemNames = intersectedGroups.FlatMap((Tuple<string, List<string>> _) => _.Item2).ToHashSet();
			List<string> nonGroupedItems = containersUniqueItems.Filter((string _) => !intersectedItemNames.Contains(_)).ToList();
			Transform obj = groupsDialogObj.transform.Find("TextArea/ScrollArea/Content/Name");
			object obj2 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			if (obj2 == null)
			{
				Transform obj3 = groupsDialogObj.transform.Find("Panel/TextArea/ScrollArea/Content/Name");
				obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<TextMeshProUGUI>() : null) ?? ((IEnumerable<TextMeshProUGUI>)groupsDialogObj.GetComponentsInChildren<TextMeshProUGUI>(true)).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI t) => ((Object)t).name == "Name"));
			}
			TextMeshProUGUI val = (TextMeshProUGUI)obj2;
			Transform obj4 = groupsDialogObj.transform.Find("TextArea/ScrollArea/Content/Description");
			object obj5 = ((obj4 != null) ? ((Component)obj4).GetComponent<TextMeshProUGUI>() : null);
			if (obj5 == null)
			{
				Transform obj6 = groupsDialogObj.transform.Find("Panel/TextArea/ScrollArea/Content/Description");
				obj5 = ((obj6 != null) ? ((Component)obj6).GetComponent<TextMeshProUGUI>() : null) ?? ((IEnumerable<TextMeshProUGUI>)groupsDialogObj.GetComponentsInChildren<TextMeshProUGUI>(true)).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI t) => ((Object)t).name == "Description"));
			}
			TextMeshProUGUI val2 = (TextMeshProUGUI)obj5;
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				Mod.log.LogWarning((object)"Merge dialog text elements missing; creating new group instead.");
				ItemGroupUtils.RegisterNewGroup(inventory);
				return;
			}
			if (intersectedGroups.Count == 1)
			{
				if (!nonGroupedItems.Any())
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Group " + intersectedGroups[0].Item1 + " already contains these items", 0, (Sprite)null, false);
					return;
				}
				List<string> list = inventory.m_inventory.Filter((ItemData i) => intersectedGroups[0].Item2.Contains(i.SCName())).Map((ItemData _) => Localization.instance.Localize(_.m_shared.m_name)).Distinct()
					.ToList();
				((TMP_Text)val).text = string.Join(",", list.Take(3)) + " " + ((list.Count > 3) ? "and others " : "") + ((list.Count > 1) ? "are already members" : "is already a member") + $" of an existing group of {ItemGroups.Groups[intersectedGroups[0].Item1].Count} items. ";
			}
			else
			{
				((TMP_Text)val).text = $"Items from {intersectedGroups.Count} different groups are already presented in this container.";
			}
			((TMP_Text)val2).text = " Please review info bellow, select target-group & action.\n You can: \n • <color=#FFA13CB7>'Extend'</color>: add previously non-grouped items \n(colored in <color=green>green</color>) to a selected  target-group.\n • <color=#FFA13CB7>'Extend & merge'</color>: add all items from this container to a selected target-group. All conflicting items (colored in <color=red>red</color>) would be removed from their current groups.\n • <color=#FFA13CB7>'Merge all'</color>: (Not recommended) move all items (from this container) & all conflicting group items to a target group.\n<color=grey>(target-group could be a new or an existing group)</color>\n";
			List<string> list2 = UnloadItems.unloadAllGroupsList.Intersect(second).ToList();
			if (Mod.unloadAllEnabled.Value && list2.Any())
			{
				((TMP_Text)val2).text = ((TMP_Text)val2).text + " \n<color=orange> ! Please note that groups [" + string.Join(",", list2) + "] are used for 'Unloading' filtering. Changing them will affect it's behaviour.</color>\n";
			}
			((TMP_Text)val2).text = ((TMP_Text)val2).text + "\n Items in the container: " + string.Join(",", containersUniqueItems.Map((string itemName) => "<color=" + (nonGroupedItems.Contains(itemName) ? "green" : "red") + ">" + itemName + "</color>")) + ".\n";
			((TMP_Text)val2).text = ((TMP_Text)val2).text + "\n Detected groups: \n";
			((TMP_Text)val2).text = ((TMP_Text)val2).text + string.Join("", intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).Map(delegate(string gKey)
			{
				IEnumerable<string> values = ItemGroups.Groups[gKey].Map((string _) => intersectedItemNames.Contains(_) ? ("<color=red>" + _ + "</color>") : _);
				return "<color=yellow>" + gKey + "</color>: [" + string.Join(", ", values) + "] \n";
			}));
			RectTransform selectorBtn = default(RectTransform);
			ref RectTransform reference = ref selectorBtn;
			Transform obj7 = groupsDialogObj.transform.Find("TextArea/Selector");
			reference = (RectTransform)(((obj7 is RectTransform) ? obj7 : null) ?? ((object)/*isinst with value type is only supported in some contexts*/) ?? ((object)((IEnumerable<RectTransform>)groupsDialogObj.GetComponentsInChildren<RectTransform>(true)).FirstOrDefault((Func<RectTransform, bool>)((RectTransform t) => ((Object)t).name == "Selector"))));
			Transform obj8 = groupsDialogObj.transform.Find("SelectorDlg/Recipes/ListRoot");
			RectTransform val3 = (RectTransform)(((object)((obj8 is RectTransform) ? obj8 : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/));
			if ((Object)(object)selectorBtn != (Object)null && (Object)(object)val3 != (Object)null)
			{
				List<string> names = intersectedGroups.Map((Tuple<string, List<string>> _) => _.Item1).Prepend("--new Group--").ToList();
				GuiFactory.FillResList(val3, names, groupSelectorItems, delegate(string selection)
				{
					TextMeshProUGUI componentInChildren2 = ((Component)selectorBtn).GetComponentInChildren<TextMeshProUGUI>();
					if ((Object)(object)componentInChildren2 != (Object)null)
					{
						((TMP_Text)componentInChildren2).text = selection;
					}
					Transform val7 = groupsDialogObj.transform.Find("SelectorDlg") ?? groupsDialogObj.transform.Find("Panel/SelectorDlg");
					if ((Object)(object)val7 != (Object)null)
					{
						((Component)val7).gameObject.SetActive(false);
					}
				});
				TextMeshProUGUI componentInChildren = ((Component)selectorBtn).GetComponentInChildren<TextMeshProUGUI>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = ((intersectedGroups.Count == 1) ? intersectedGroups[0].Item1 : "--new Group--");
				}
				Transform val4 = groupsDialogObj.transform.Find("SelectorDlg/RecipeScroll") ?? groupsDialogObj.transform.Find("Panel/SelectorDlg/RecipeScroll");
				Scrollbar val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<Scrollbar>() : null);
				if ((Object)(object)val5 != (Object)null)
				{
					val5.value = 1f;
				}
				Transform val6 = groupsDialogObj.transform.Find("SelectorDlg") ?? groupsDialogObj.transform.Find("Panel/SelectorDlg");
				if ((Object)(object)val6 != (Object)null)
				{
					((Component)val6).gameObject.SetActive(false);
				}
			}
			groupsDialogObj.SetActive(true);
		}

		private static string SelectedTargetGroupId()
		{
			Transform val = groupsDialogObj.transform.Find("TextArea/Selector") ?? groupsDialogObj.transform.Find("Panel/TextArea/Selector") ?? ((IEnumerable<Transform>)groupsDialogObj.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Selector"));
			if (!((Object)(object)val != (Object)null))
			{
				return "--new Group--";
			}
			return ((TMP_Text)((Component)val).GetComponentInChildren<TextMeshProUGUI>()).text;
		}

		private static void AddStoreAllBtn(InventoryGui __instance)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			storeAllButton = GuiFactory.AddContainerGuiButton("storeAllButton", ">>", new Vector2(45f, 36f), Mod.unloadAllBtnPos.Value);
			GuiFactory.InitJoyKey(storeAllButton, "JoyMenu", "(Menu)");
			((UnityEvent)((Component)storeAllButton).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				if (!((Object)(object)__instance.m_playerGrid == (Object)null) && !((Object)(object)__instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting())
				{
					UnloadItems.UnloadAllItems(((Humanoid)Player.m_localPlayer).GetInventory());
				}
			});
		}

		public static void Init()
		{
			if ((Object)(object)InventoryGui.instance != (Object)null)
			{
				InitButtons(InventoryGui.instance);
			}
		}

		public static void Clean()
		{
			if ((Object)(object)createGroupButton != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)createGroupButton).gameObject);
			}
			if ((Object)(object)storeAllButton != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)storeAllButton).gameObject);
			}
			if ((Object)(object)groupsDialogObj != (Object)null)
			{
				Object.Destroy((Object)(object)groupsDialogObj);
			}
			createGroupButton = null;
			storeAllButton = null;
			groupsDialogObj = null;
			initialized = false;
			Mod.log.LogInfo((object)"Cleaned up UI extensions.");
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	public static class Inventory_Patch
	{
		public static void Postfix(Inventory __instance, ItemData item, ref bool __result)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			if (!Mod.modEnabled.Value || __instance == null || (Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting() || ((object)__instance).Equals((object?)((Humanoid)Player.m_localPlayer).GetInventory()) || !((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(item) || (Mod.onlyStackableItems.Value && item.m_shared.m_maxStackSize == 1) || ContainersTracker.isRearrangingItem)
			{
				return;
			}
			if (Input.GetKey((KeyCode)108))
			{
				Console.instance.Print("SmartContainers tracked item [" + item.m_shared.m_name + "]");
			}
			KeyboardShortcut value = Mod.keyModifier.Value;
			if (!((KeyboardShortcut)(ref value)).IsPressed())
			{
				value = Mod.groupingKeyModifier.Value;
				if (!((KeyboardShortcut)(ref value)).IsPressed() && (!Mod.gamepadKey2.Value.MainPressed() || !ZInput.GetButton(Mod.gamepadKey1.Value)))
				{
					return;
				}
			}
			if ((Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.instance.IsContainerOpen())
			{
				return;
			}
			ContainersTracker.isRearrangingItem = true;
			try
			{
				if (!__result)
				{
					if (TryAddToNearBy(item))
					{
						__result = true;
						Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint());
					}
				}
				else if (__instance.CountItems(item.m_shared.m_name, -1, true) == item.m_stack && TryAddToNearBy(item))
				{
					__instance.RemoveItem(item);
					Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint());
				}
			}
			finally
			{
				ContainersTracker.isRearrangingItem = false;
			}
		}

		public static bool TryAddToNearBy(ItemData item, bool allowCurrent = false, bool forceGrouping = false)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Container openedContainer = InventoryGui.instance.m_currentContainer;
				if (Mod.concurrencyWorkaround.Value.BlockIfAnyOtherOpened() && ContainersTracker.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position, all: true).Any((Container c) => ((object)openedContainer).GetHashCode() != ((object)c).GetHashCode() && c.m_nview.GetZDO().GetInt("InUse", 0) == 1))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Cant distribute items: other Player is using containers nearby.", 0, (Sprite)null, false);
					return false;
				}
				List<Container> list = (from c in ContainersTracker.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position)
					where ((object)openedContainer).GetHashCode() == ((object)c).GetHashCode() || (Mod.concurrencyWorkaround.Value.Ignore() && ((object)openedContainer).GetHashCode() != ((object)c).GetHashCode()) || ((Mod.concurrencyWorkaround.Value.SkipOpenedOthers() || Mod.concurrencyWorkaround.Value.BlockIfAnyOtherOpened()) && c.m_nview.GetZDO().GetInt("InUse", 0) == 0)
					select c).ToList();
				foreach (Container item2 in list)
				{
					if (item2.GetInventory().CanAddItem(item, -1) && (allowCurrent || ((object)openedContainer).GetHashCode() != ((object)item2).GetHashCode()) && item2.GetInventory().HaveItem(item.m_shared.m_name, true))
					{
						Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has same item stack");
						return AddItemToContainer(item, item2, allowCurrent);
					}
				}
				KeyboardShortcut value;
				if (Mod.groupingEnabled.Value)
				{
					if (!forceGrouping)
					{
						value = Mod.groupingKeyModifier.Value;
						if (!((KeyboardShortcut)(ref value)).IsPressed() && !ZInput.IsGamepadActive())
						{
							goto IL_03f3;
						}
					}
					List<Tuple<string, Container>> list2 = new List<Tuple<string, Container>>();
					foreach (Container item3 in list)
					{
						if (item3.GetInventory().CanAddItem(item, -1))
						{
							string text = ItemGroups.FindMatchingUserGroup(item3, item);
							if (text != null)
							{
								list2.Add(Tuple.Create<string, Container>(text, item3));
							}
						}
					}
					if (list2.Any())
					{
						Tuple<string, Container> tuple = list2.OrderByDescending((Tuple<string, Container> t) => t.Item1).First();
						if (list2.Count > 1)
						{
							Mod.log.LogWarning((object)("Ambiguous item-groups [" + string.Join(",", list2) + "] found for " + ((Object)item.m_dropPrefab).name + " item. Using " + tuple.Item1));
						}
						Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item from group " + tuple.Item1 + " : [" + string.Join(",", ItemGroups.Groups[tuple.Item1]) + "]");
						return AddItemToContainer(item, tuple.Item2, allowCurrent);
					}
					foreach (Container item4 in list)
					{
						if (item4.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSame_SystemGroupItems(item4, item))
						{
							return AddItemToContainer(item, item4, allowCurrent);
						}
					}
					foreach (Container item5 in list)
					{
						if (item5.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSame_NamePatternItems(item5, item))
						{
							return AddItemToContainer(item, item5, allowCurrent);
						}
					}
					if (Mod.itemTypeGroupsEnabled.Value)
					{
						foreach (Container item6 in list)
						{
							if (item6.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSameItemType(item6, item))
							{
								return AddItemToContainer(item, item6, allowCurrent);
							}
						}
					}
					goto IL_03f3;
				}
				goto IL_046f;
				IL_03f3:
				if (Mod.fuzzyGroupingEnabled.Value)
				{
					if (!forceGrouping)
					{
						value = Mod.groupingKeyModifier.Value;
						if (!((KeyboardShortcut)(ref value)).IsPressed() && !ZInput.IsGamepadActive())
						{
							goto IL_046f;
						}
					}
					foreach (Container item7 in list)
					{
						if (item7.GetInventory().CanAddItem(item, -1) && ItemGroups.ContainerHasSimilarGroupItems(item7, item))
						{
							return AddItemToContainer(item, item7, allowCurrent);
						}
					}
				}
				goto IL_046f;
				IL_046f:
				return false;
			}
			catch (Exception ex)
			{
				Mod.log.LogError((object)("Failed to rearrange container items: " + ex));
				return false;
			}
		}

		private static bool AddItemToContainer(ItemData item, Container targetContainer, bool allowCurrent = false)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			Container currentContainer = InventoryGui.instance.m_currentContainer;
			if (!allowCurrent && ((object)currentContainer).GetHashCode() == ((object)targetContainer).GetHashCode())
			{
				return false;
			}
			if (!targetContainer.GetInventory().AddItem(item))
			{
				return false;
			}
			targetContainer.Save();
			targetContainer.GetInventory().Changed(false, false);
			if (Mod.hudMessageEnabled.Value && !((object)InventoryGui.instance.m_currentContainer).Equals((object?)targetContainer))
			{
				MessageHud.instance.QueueUnlockMsg(item.GetIcon(), item.m_shared.m_name, Mod.hudMessageText.Value);
			}
			Mod.PlayEffect(Mod.effectFeedbackEnabled.Value, "vfx_Potion_health_medium", ((Component)targetContainer).transform.position);
			return true;
		}
	}
	internal static class ItemDataMethods
	{
		public static string SCName(this string itemName)
		{
			return itemName.ToLower().Replace("$item_", "").Replace("_", "");
		}

		public static string SCName(this ItemData itemDrop)
		{
			return itemDrop.m_shared.m_name.SCName();
		}
	}
	public static class ItemGroups
	{
		private static ICollection<string> prefixItemGroups = new HashSet<string>();

		private static ICollection<string> postfixItemGroups = new HashSet<string>();

		public static readonly IDictionary<string, ISet<string>> Groups = new Dictionary<string, ISet<string>>();

		public static void ParseConfig()
		{
			foreach (KeyValuePair<ConfigDefinition, string> item in Mod.ConfigOrphanedEntries().ToList())
			{
				if (item.Key.Section.Equals("ItemGroup"))
				{
					Mod.config.Bind<string>(item.Key.Section, item.Key.Key, item.Value.ToLower().Replace("_", ""), Mod.groupDescr("user-added items-group based on item-names list"));
				}
			}
			ConfigEntry<string> val = default(ConfigEntry<string>);
			if (Mod.config.TryGetEntry<string>("PrefixedItemGroups", "prefixes", ref val) && val.Value.Length > 0)
			{
				prefixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(val);
				Mod.log.LogInfo((object)string.Format("parsed PrefixedItemGroups : [{0}] ({1})", string.Join(",", prefixItemGroups), prefixItemGroups.Count));
			}
			ConfigEntry<string> val2 = default(ConfigEntry<string>);
			if (Mod.config.TryGetEntry<string>("PostfixedItemGroups", "posfixes", ref val2) && val2.Value.Length > 0)
			{
				postfixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(val2);
				Mod.log.LogInfo((object)string.Format("parsed PostfixedItemGroups: [{0}] ({1})", string.Join(",", postfixItemGroups), postfixItemGroups.Count));
			}
			ConfigEntry<string> val3 = default(ConfigEntry<string>);
			foreach (ConfigDefinition item2 in from _ in Mod.config.Keys
				where _.Section.Equals("ItemGroup")
				orderby _.Key
				select _)
			{
				if (Mod.config.TryGetEntry<string>(item2.Section, item2.Key, ref val3) && val3.Value.Length > 0)
				{
					ISet<string> set = ItemGroupUtils.ParseGroupConfigEntry(val3);
					Groups.Add(item2.Key, set);
					Mod.log.LogInfo((object)string.Format("parsed items group '{0}': [{1}] ({2})", item2.Key, string.Join(",", set), set.Count));
				}
			}
		}

		public static string FindMatchingUserGroup(Container container, ItemData item)
		{
			if (item.m_shared.m_name.Length < 7)
			{
				Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name));
				return null;
			}
			ICollection<string> collection = FindMatchingGroups(container, item.SCName(), item, Groups.Keys.Except(Mod.systemGroupKeys).ToList());
			if (collection.Count > 1)
			{
				Mod.log.LogWarning((object)("Ambiguous item-groups [" + string.Join(",", collection) + "] found for " + ((Object)item.m_dropPrefab).name + " item in single container."));
			}
			if (!collection.Any())
			{
				return null;
			}
			return collection.Max((string _) => _);
		}

		public static bool ContainerHasSame_SystemGroupItems(Container container, ItemData item)
		{
			if (item.m_shared.m_name.Length < 7)
			{
				Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name));
				return false;
			}
			return TestConfiguredGroups(container, item.SCName(), item, Mod.systemGroupKeys);
		}

		public static bool ContainerHasSame_NamePatternItems(Container container, ItemData item)
		{
			if (item.m_shared.m_name.Length < 7)
			{
				Mod.log.LogWarning((object)("Cant process Unexpected Item " + item.m_shared.m_name));
				return false;
			}
			string shortItemName = item.SCName();
			if (!TestItemNamePrefix(container, shortItemName, item))
			{
				return TestItemNamePostfix(container, shortItemName, item);
			}
			return true;
		}

		public static bool ContainerHasSameItemType(Container container, ItemData item)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (item.m_shared.m_name.Length < 7)
			{
				return false;
			}
			ItemType itemType = item.m_shared.m_itemType;
			string shortItemName = item.SCName();
			int num;
			if ((!IsTrophie(itemType) || !HaveMatchingItem(container, (ItemData _) => IsTrophie(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsTool(itemType) || !HaveMatchingItem(container, (ItemData _) => IsTool(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsAmmo(itemType) || !HaveMatchingItem(container, (ItemData _) => IsAmmo(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))) && (!IsArmor(itemType) || !HaveMatchingItem(container, (ItemData _) => IsArmor(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName))))
			{
				if (IsWeapon(itemType))
				{
					num = (HaveMatchingItem(container, (ItemData _) => IsWeapon(_.m_shared.m_itemType) && !_.SCName().Equals(shortItemName)) ? 1 : 0);
					if (num != 0)
					{
						goto IL_00c6;
					}
				}
				else
				{
					num = 0;
				}
				goto IL_00ff;
			}
			num = 1;
			goto IL_00c6;
			IL_00c6:
			Console.instance.Print($"{Localization.instance.Localize(item.m_shared.m_name)} routed because target container has same item type {item.m_shared.m_itemType}");
			goto IL_00ff;
			IL_00ff:
			return (byte)num != 0;
		}

		public static bool ContainerHasSimilarGroupItems(Container container, ItemData item)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			if (item.m_shared.m_name.Length < 7)
			{
				return false;
			}
			string shortItemName = item.m_shared.m_name.SCName();
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType == 0)
			{
				return false;
			}
			bool num = HaveMatchingItem(container, (ItemData _) => _.m_shared.m_itemType == itemType && !_.SCName().Equals(shortItemName));
			if (num)
			{
				Console.instance.Print($"{Localization.instance.Localize(item.m_shared.m_name)} routed because target container has same item type (fuzzy) {item.m_shared.m_itemType}");
			}
			return num;
		}

		private static bool TestItemNamePrefix(Container container, string shortItemName, ItemData item)
		{
			foreach (string prefix in prefixItemGroups)
			{
				if (shortItemName.StartsWith(prefix) && HaveMatchingItem(container, (ItemData _) => _.m_shared.m_name.StartsWith("$item_" + prefix) && !_.SCName().Equals(shortItemName)))
				{
					Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item with Prefix " + prefix);
					return true;
				}
			}
			return false;
		}

		private static bool TestItemNamePostfix(Container container, string shortItemName, ItemData item)
		{
			foreach (string postfix in postfixItemGroups)
			{
				if (shortItemName.EndsWith(postfix) && HaveMatchingItem(container, (ItemData _) => _.m_shared.m_name.EndsWith(postfix) && !_.SCName().Equals(shortItemName)))
				{
					Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item with Postfix " + postfix);
					return true;
				}
			}
			return false;
		}

		private static bool TestConfiguredGroups(Container container, string shortItemName, ItemData item, ICollection<string> grKeys = null)
		{
			foreach (string item2 in grKeys ?? Groups.Keys)
			{
				if (Groups.ContainsKey(item2))
				{
					ISet<string> set = Groups[item2];
					if (TestGroup(shortItemName, container, set))
					{
						Console.instance.Print(Localization.instance.Localize(item.m_shared.m_name) + " routed because target container has item from group " + item2 + " : [" + string.Join(",", set) + "]");
						return true;
					}
				}
			}
			return false;
		}

		private static ICollection<string> FindMatchingGroups(Container container, string shortItemName, ItemData item, ICollection<string> grKeys = null)
		{
			List<string> list = new List<string>();
			foreach (string item2 in grKeys ?? Groups.Keys)
			{
				if (Groups.ContainsKey(item2) && TestGroup(shortItemName, container, Groups[item2]))
				{
					list.Add(item2);
				}
			}
			return list;
		}

		private static bool TestGroup(string shortItemName, Container container, ICollection<string> group)
		{
			if (!group.Contains(shortItemName))
			{
				return false;
			}
			foreach (string iname in group)
			{
				if (!iname.Equals(shortItemName) && HaveMatchingItem(container, (ItemData _) => _.SCName().Equals(iname)))
				{
					return true;
				}
			}
			return false;
		}

		private static bool HaveMatchingItem(Container container, Func<ItemData, bool> predicate)
		{
			foreach (ItemData item in container.GetInventory().m_inventory)
			{
				if (predicate(item))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsArmor(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if (type - 6 <= 1 || (int)type == 11 || type - 17 <= 1)
			{
				return true;
			}
			return false;
		}

		private static bool IsWeapon(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			if (type - 3 <= 2 || (int)type == 14 || (int)type == 22)
			{
				return true;
			}
			return false;
		}

		private static bool IsTrophie(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			return (int)type == 13;
		}

		private static bool IsTool(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			return (int)type == 19;
		}

		private static bool IsAmmo(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)type == 9 || (int)type == 23)
			{
				return true;
			}
			return false;
		}

		public static void Clear()
		{
			prefixItemGroups.Clear();
			postfixItemGroups.Clear();
			Groups.Clear();
		}
	}
	public static class ItemGroupUtils
	{
		private static readonly Predicate<string> IsItemSupported = (string itemName) => itemName.StartsWith("$item_") || itemName.StartsWith("$mod_");

		public static void RegisterNewGroup(Inventory inventory)
		{
			List<string> list = ExtractUniqueItemNames(inventory);
			if (list.Count > 1)
			{
				RegisterNewGroup((ICollection<string>)list);
			}
		}

		public static void RegisterNewGroup(ICollection<string> names)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			if (!names.Any())
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "No new items to create a group from.", 0, (Sprite)null, false);
				return;
			}
			Mod.ignoreUpdate = true;
			ConfigDefinition val = new ConfigDefinition("ItemGroup", "userGroup" + DateTimeOffset.UtcNow.ToUnixTimeSeconds());
			Mod.config.Bind<string>(val, string.Join(",", names), Mod.groupDescr("user-added items-group based on item-names list"));
			ConfigEntry<string> val2 = default(ConfigEntry<string>);
			if (Mod.config.TryGetEntry<string>(val, ref val2) && val2.Value.Length > 0)
			{
				ISet<string> set = ParseGroupConfigEntry(val2);
				ItemGroups.Groups.Add(val.Key, set);
				ManualLogSource log = Mod.log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("parsed items group '{0}': [{1}] ({2})", val.Key, string.Join(",", set), set.Count));
				}
				NotifyPlayer(set.Count, "Registered new group of {0} items.");
			}
		}

		public static void MergeAllToSingleGroup(string targetGroupId, List<string> groupIds, List<string> newItems)
		{
			HashSet<string> hashSet = groupIds.Filter((string _) => !_.Equals(targetGroupId)).FlatMap((string _) => ItemGroups.Groups[_]).Concat(newItems)
				.ToHashSet();
			if (!ItemGroups.Groups.ContainsKey(targetGroupId))
			{
				RegisterNewGroup((ICollection<string>)hashSet);
			}
			else
			{
				hashSet = hashSet.Except(ItemGroups.Groups[targetGroupId]).ToHashSet();
				if (!hashSet.Any())
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null, false);
				}
				else
				{
					AddToItemsGroup(targetGroupId, hashSet);
					NotifyPlayer(hashSet.Count, "Added {0} new items to existing group.");
				}
			}
			foreach (string item in groupIds.Filter((string _) => !_.Equals(targetGroupId)))
			{
				Mod.log.LogInfo((object)("flattened group : " + item));
				ClearItemsGroup(item);
			}
		}

		public static void ExtendGroup(string targetGroupId, List<string> groupIds, List<string> newItems)
		{
			List<string> second = groupIds.FlatMap((string _) => ItemGroups.Groups[_]).Intersect(newItems).ToList();
			HashSet<string> hashSet = newItems.Except(second).ToHashSet();
			if (!ItemGroups.Groups.ContainsKey(targetGroupId))
			{
				RegisterNewGroup((ICollection<string>)hashSet);
				return;
			}
			if (!hashSet.Any())
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null, false);
				return;
			}
			AddToItemsGroup(targetGroupId, hashSet);
			NotifyPlayer(hashSet.Count, "Added {0} new items to existing group.");
		}

		public static void ExtendAndMerge(string targetGroupId, List<string> groupIds, List<string> newItems)
		{
			foreach (string item in groupIds.Filter((string _) => !_.Equals(targetGroupId)))
			{
				List<string> items = newItems.Intersect(ItemGroups.Groups[item]).ToList();
				RemoveFromItemsGroup(item, items);
			}
			if (!ItemGroups.Groups.ContainsKey(targetGroupId))
			{
				RegisterNewGroup((ICollection<string>)newItems);
				return;
			}
			HashSet<string> hashSet = newItems.Except(ItemGroups.Groups[targetGroupId]).ToHashSet();
			if (!hashSet.Any())
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Existing group already contained all items", 0, (Sprite)null, false);
				return;
			}
			AddToItemsGroup(targetGroupId, hashSet);
			NotifyPlayer(hashSet.Count, "Added {0} new items to existing group.");
		}

		public static ConfigEntry<string> AddToItemListConfig(ICollection<string> names, ISet<string> targetSet, ConfigEntry<string> configEntry, string uiMessage)
		{
			foreach (string name in names)
			{
				targetSet.Add(name);
			}
			Mod.ignoreUpdate = true;
			configEntry.Value = string.Join(",", targetSet);
			NotifyPlayer(names.Count, uiMessage);
			return configEntry;
		}

		private static void NotifyPlayer(int count, string uiMessage)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			((Character)Player.m_localPlayer).Message((MessageType)2, string.Format(uiMessage, count), 0, (Sprite)null, false);
			if (Mod.effectFeedbackEnabled.Value)
			{
				Vector3 position = ((Component)InventoryGui.instance.m_currentContainer).gameObject.transform.position;
				Player.m_localPlayer.m_skillLevelupEffects.Create(position, Quaternion.identity, (Transform)null, 1f, -1, ZDOID.None);
			}
		}

		public static List<Tuple<string, List<string>>> FindIntersections(List<string> names)
		{
			List<Tuple<string, List<string>>> list = new List<Tuple<string, List<string>>>();
			foreach (string item in ItemGroups.Groups.Keys.ToList())
			{
				List<string> list2 = ItemGroups.Groups[item].Intersect(names).ToList();
				if (list2.Any())
				{
					list.Add(Tuple.Create(item, list2));
				}
			}
			return list.OrderByDescending((Tuple<string, List<string>> tt) => tt.Item2.Count).ToList();
		}

		public static List<string> ExtractUniqueItemNames(Inventory inventory)
		{
			foreach (string item in inventory.m_inventory.Map((ItemData invi) => invi.m_shared.m_name).Filter((string _) => !IsItemSupported(_)).ToList())
			{
				Mod.log.LogWarning((object)("Unsupported item name " + item));
			}
			return inventory.m_inventory.Map((ItemData invi) => invi.m_shared.m_name).Filter((string _) => IsItemSupported(_)).Distinct()
				.Map((string _) => _.SCName())
				.ToList();
		}

		public static ISet<string> ParseGroupConfigEntry(ConfigEntry<string> configEntry)
		{
			return new HashSet<string>(configEntry.Value.Split(new char[1] { ',' }).Map((string _) => _.SCName().Replace(" ", "")));
		}

		private static void AddToItemsGroup(string groupId, ICollection<string> items)
		{
			foreach (string item in items)
			{
				ItemGroups.Groups[groupId].Add(item);
			}
			SaveItemsGroup(groupId, ItemGroups.Groups[groupId]);
		}

		private static void RemoveFromItemsGroup(string groupId, ICollection<string> items)
		{
			foreach (string item in items)
			{
				ItemGroups.Groups[groupId].Remove(item);
			}
			SaveItemsGroup(groupId, ItemGroups.Groups[groupId]);
		}

		private static void ClearItemsGroup(string flattenedGroupId)
		{
			ItemGroups.Groups[flattenedGroupId].Clear();
			SaveItemsGroup(flattenedGroupId, ItemGroups.Groups[flattenedGroupId]);
		}

		private static void SaveItemsGroup(string groupId, ICollection<string> groupItems)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			ConfigEntry<string> val = default(ConfigEntry<string>);
			if (Mod.config.TryGetEntry<string>(new ConfigDefinition("ItemGroup", groupId), ref val))
			{
				Mod.ignoreUpdate = true;
				val.Value = string.Join(",", groupItems);
			}
		}
	}
	internal static class KeyboardShortcutMethods
	{
		public static bool IsPressedOrNone(this KeyboardShortcut shortcut)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if (!((KeyboardShortcut)(ref shortcut)).IsPressed())
			{
				return (int)((KeyboardShortcut)(ref shortcut)).MainKey == 0;
			}
			return true;
		}

		public static bool MainPressed(this KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey);
		}
	}
	[BepInPlugin("flueno.SmartContainers", "Smart Containers Mod", "1.8.0")]
	public class Mod : BaseUnityPlugin
	{
		internal readonly Harmony harmony;

		internal readonly Assembly assembly;

		public static ManualLogSource log;

		public static ConfigFile config;

		public static ConfigEntry<bool> modEnabled;

		public static ConfigEntry<bool> groupingEnabled;

		public static ConfigEntry<bool> itemTypeGroupsEnabled;

		public static ConfigEntry<bool> fuzzyGroupingEnabled;

		public static ConfigEntry<bool> onlyStackableItems;

		public static ConfigEntry<ConcurrentChestModificationWorkaround> concurrencyWorkaround;

		public static ConfigEntry<bool> hudMessageEnabled;

		public static ConfigEntry<bool> audioFeedbackEnabled;

		public static ConfigEntry<bool> effectFeedbackEnabled;

		public static ConfigEntry<string> hudMessageText;

		public static ConfigEntry<int> range;

		public static ConfigEntry<KeyboardShortcut> keyModifier;

		public static ConfigEntry<string> gamepadKey1;

		public static ConfigEntry<KeyboardShortcut> gamepadKey2;

		public static ConfigEntry<KeyboardShortcut> groupingKeyModifier;

		public static ConfigEntry<bool> createGroupBtnEnabled;

		public static ConfigEntry<bool> mergePromptEnabled;

		public static ConfigEntry<Vector2> createGroupBtnPos;

		public static ConfigEntry<bool> unloadAllEnabled;

		public static ConfigEntry<bool> unloadAllInsteadStackBtn;

		public static ConfigEntry<Vector2> unloadAllBtnPos;

		public static ConfigEntry<KeyboardShortcut> unloadAllItemsGroupKeyModifier;

		public static ConfigEntry<KeyboardShortcut> unloadAllSkipItemsGroupKeyModifier;

		public static ConfigEntry<bool> unloadForceGrouping;

		public static ConfigEntry<string> unloadAllItemsList;

		public static ConfigEntry<string> unloadAllSkipList;

		public static ConfigEntry<string> unloadAllGroupsList;

		public static ConfigEntry<string> unloadAllPrefixItemGroups;

		public static ConfigEntry<string> unloadAllPostfixItemGroups;

		public static ConfigEntry<bool> unloadAllMaterialsFiltering;

		public static ConfigEntry<bool> unloadAllTrophiesFiltering;

		public static ConfigEntry<bool> unloadAllConsumableFiltering;

		public static bool ignoreUpdate;

		public static readonly ICollection<string> systemGroupKeys = new HashSet<string> { "valuables", "ore", "rock", "ingots", "wood", "mushrooms", "berries", "vegetables", "cookedMeat", "food" };

		public Mod()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			harmony = new Harmony("flueno.SmartContainers");
			assembly = Assembly.GetExecutingAssembly();
			config = ((BaseUnityPlugin)this).Config;
			log = ((BaseUnityPlugin)this).Logger;
		}

		private void Start()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_054b: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 332, "Nexus mod ID");
			modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "enabled", true, "Enables this mod");
			MigrateConfig(ConfigOrphanedEntries());
			onlyStackableItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "onlyStackableItems", true, "Rearranges only stackable items");
			hudMessageEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "hudMessageEnabled", true, "Enables hud message indicating that item was routed & placed to some other chest");
			hudMessageText = ((BaseUnityPlugin)this).Config.Bind<string>("General", "hudMessageText", "Routed to another Chest", "HUD message consists of Icon, item-name plus this text.");
			range = ((BaseUnityPlugin)this).Config.Bind<int>("General", "range", 14, new ConfigDescription("Range within which containers will participate in resources arrangement.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 99), Array.Empty<object>()));
			keyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "hkeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "Change only if you wish to have even longer than ctrl+click combination (holding ctrl is mandatory since it's a 'move-stack' ingame key)");
			gamepadKey1 = ((BaseUnityPlugin)this).Config.Bind<string>("General", "gamepadKey1", "JoyLTrigger", "first part of gamepads transfer-item key-combo");
			gamepadKey2 = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "gamepadKey2", new KeyboardShortcut((KeyCode)330, Array.Empty<KeyCode>()), "second part of gamepads transfer-item key-combo");
			audioFeedbackEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "audioFeedbackEnabled", true, "Enables playing of sound on successful items transfer");
			effectFeedbackEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "effectFeedbackEnabled", true, "Enables highlighting of end-target chests where items have been transferred.");
			concurrencyWorkaround = ((BaseUnityPlugin)this).Config.Bind<ConcurrentChestModificationWorkaround>("General", "concurrentChestModificationWorkaround", ConcurrentChestModificationWorkaround.ExcludeContainersOpenedByOthers, "There are rare possibility of items loss if two players simultaneously (within a ~second) modify same containers inventory. Options are: ignore possible issue; ignore 'opened' chests; block mod if any other nearby player opened a chest");
			groupingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "enabled", true, "Enables distributing items to containers with 'same-kinded' items (used if no nearby containers contain 'same item')");
			itemTypeGroupsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "itemTypeGroupsEnabled", true, "Enable grouping by item-types (Trophie, Tool, Ammo, Armor, Weapon).");
			fuzzyGroupingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "fuzzyGroupingEnabled", false, "Enable grouping by more broad criteria.");
			groupingKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Grouping", "groupingKeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), " Change to 'LeftControl + LeftShift' if you want to trigger grouping with a separate hotkey (ctrl+shift+click)(holding ctrl is mandatory since it's a 'move-stack' ingame key)");
			createGroupBtnEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "createGroupBtnEnabled", true, "Adds to the chest UI button which creates items-group based on the current items set in the chest.");
			mergePromptEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Grouping", "mergePromptEnabled", true, "In case when createGroupBtn clicked and chest already contains some members of one ore more groups - dialog showed with option to merge items & groups into a single group.");
			createGroupBtnPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Grouping", "createGroupBtnPos", new Vector2(1.5f, 10.7f), "Adjusts btn position on inventory ui.");
			((BaseUnityPlugin)this).Config.Bind<string>("PrefixedItemGroups", "prefixes", "trophy,mead,arrow,armor,cape,helmet,atgeir,bow,battleaxe,knife,mace,shield,sledge,spear,sword,tankard,club,mushroom,arrow", groupDescr("If both item names start with same 'prefix' - they are considered to have same group. I.e. arrowFire & arrowFlint"));
			((BaseUnityPlugin)this).Config.Bind<string>("PostfixedItemGroups", "posfixes", "cone,seeds,pelt,hide,berries", groupDescr("If both item names end with same 'postfix' - they are considered to have same group. I.e. carrotSeeds & turnipSeeds"));
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "valuables", "ruby,coins,amber,amberpearl", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "ore", "copperore,flametalore,ironore,silverore,tinore,ironscrap,blackmetalscrap", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "rock", "stone,flint,obsidian", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "ingots", "copper,bronze,flametal,iron,silver,tin,blackmetal", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "wood", "wood,finewood,corewood,elderbark,roundlog", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "mushrooms", "Mushroom,MushroomBlue,MushroomYellow,mushroomcommon", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "berries", "Blueberries,raspberries,cloudberries,honey", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "vegetables", "Carrot,Turnip", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "cookedMeat", "CookedLoxMeat,NeckTailGrilled,MeatCooked,FishCooked,SerpentMeatCooked", groupDescr());
			((BaseUnityPlugin)this).Config.Bind<string>("ItemGroup", "food", "CarrotSoup,Sausages,QueensJam,SerpentStew,TurnipStew,BloodPudding", groupDescr());
			unloadAllEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "enabled", false, "Enables Unload-all option & UI button. Allows to batch-unload all eligible items from players inventory to their corresponding stacks & groups in nearby chests.");
			unloadAllInsteadStackBtn = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "nativeButton", false, "Use existing 'place-stacks' UI button for unloading. If disabled - new UI button will be created.");
			unloadAllBtnPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("Unload", "btnPos", new Vector2(1.5f, 8.15f), (ConfigDescription)null);
			unloadAllItemsGroupKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Unload", "addToItemsFilterKeyModifier", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "If pressed - overrides createGroupBtn behaviour by passing item-names to unload 'itemsList' instead of creating new items group");
			unloadForceGrouping = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "alwaysGrouping", true, "If enabled - check for groupingKeyModifier pressed is ignored for 'unload' button");
			unloadAllSkipItemsGroupKeyModifier = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Unload", "addToSkipItemsFilterKeyModifier", new KeyboardShortcut((KeyCode)306, Array.Empty<KeyCode>()), "If pressed - overrides createGroupBtn behaviour by passing item-names to unload 'itemsSkipList' instead of creating new items group");
			unloadAllItemsList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "itemsList", "", groupDescr("List of item-names allowed to be 'unloaded'"));
			unloadAllSkipList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "itemsSkipList", "", groupDescr("List of item-names to exclude from being 'unloaded'"));
			unloadAllGroupsList = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "groupsList", "valuables,ore,wood,mushrooms", "List of items group-ids from [ItemGroup] config section allowed to be 'unloaded'");
			unloadAllPrefixItemGroups = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "prefixItemGroups", "trophy", (ConfigDescription)null);
			unloadAllPostfixItemGroups = ((BaseUnityPlugin)this).Config.Bind<string>("Unload", "postfixItemGroups", "seeds", (ConfigDescription)null);
			unloadAllMaterialsFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "materialsFiltering", true, "allow all Materials to be 'unloaded'");
			unloadAllTrophiesFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "trophiesFiltering", true, "allow all Trophies to be 'unloaded'");
			unloadAllConsumableFiltering = ((BaseUnityPlugin)this).Config.Bind<bool>("Unload", "consumableFiltering", false, "allow all Consumables to be 'unloaded'");
			if (modEnabled.Value)
			{
				ItemGroups.ParseConfig();
				UnloadItems.ParseConfig();
				ContainersTracker.Init();
				Gui_Patch.Init();
				((BaseUnityPlugin)this).Config.SettingChanged += HandleConfigUpdate;
				harmony.PatchAll(assembly);
				log.LogInfo((object)"SmartContainers 1.8.0 loaded (Valheim 1.0 / Unity 6 port).");
			}
		}

		public static ConfigDescription groupDescr(string descr = "Items-group based on item-names list")
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			return new ConfigDescription(descr, (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = TextAreaDrawer
				}
			});
		}

		private static void TextAreaDrawer(ConfigEntryBase entry)
		{
			GUILayout.ExpandHeight(true);
			GUILayout.ExpandWidth(true);
			entry.BoxedValue = GUILayout.TextArea((string)entry.BoxedValue, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.ExpandHeight(true)
			});
		}

		private void HandleConfigUpdate(object sender, SettingChangedEventArgs e)
		{
			if (ignoreUpdate)
			{
				ignoreUpdate = false;
				log.LogInfo((object)$"SettingChangedEventArgs (ignored) {e.ChangedSetting.Definition}");
				return;
			}
			Gui_Patch.Clean();
			Gui_Patch.Init();
			ItemGroups.Clear();
			ItemGroups.ParseConfig();
			UnloadItems.Clear();
			UnloadItems.ParseConfig();
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
			((BaseUnityPlugin)this).Config.Reload();
			Gui_Patch.Clean();
			ItemGroups.Clear();
			UnloadItems.Clear();
			ContainersTracker.containerList.Clear();
		}

		public static bool isSystemGroup(string groupId)
		{
			return systemGroupKeys.Contains(groupId);
		}

		public static void PlayEffect(bool allowed, string prefabName, Vector3 pos)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (allowed)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity);
				}
				else
				{
					log.LogWarning((object)("Failed to locate FeedbackEffect " + prefabName + " prefab"));
				}
			}
		}

		public static Dictionary<ConfigDefinition, string> ConfigOrphanedEntries()
		{
			return Traverse.Create((object)config).Property("OrphanedEntries", (object[])null).GetValue<Dictionary<ConfigDefinition, string>>();
		}

		private static void MigrateConfig(Dictionary<ConfigDefinition, string> orphans)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0051: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0075: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_0099: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00bd: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_00e1: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (orphans.ContainsKey(new ConfigDefinition("ItemGroup", "coockedMeat")))
			{
				orphans.Remove(new ConfigDefinition("ItemGroup", "coockedMeat"));
			}
			ChangeKey<bool>(orphans, new ConfigDefinition("General", "groupingEnabled"), new ConfigDefinition("Grouping", "enabled"));
			ChangeKey<bool>(orphans, new ConfigDefinition("General", "itemTypeGroupsEnabled"), new ConfigDefinition("Grouping", "itemTypeGroupsEnabled"));
			ChangeKey<bool>(orphans, new ConfigDefinition("General", "fuzzyGroupingEnabled"), new ConfigDefinition("Grouping", "fuzzyGroupingEnabled"));
			ChangeKey<bool>(orphans, new ConfigDefinition("General", "createGroupBtnEnabled"), new ConfigDefinition("Grouping", "createGroupBtnEnabled"));
			ChangeKey<Vector2>(orphans, new ConfigDefinition("General", "createGroupBtnPos"), new ConfigDefinition("Grouping", "createGroupBtnPos"));
		}

		private static void ChangeKey<T>(Dictionary<ConfigDefinition, string> orphans, ConfigDefinition dkey, ConfigDefinition dkeyNew)
		{
			if (orphans.ContainsKey(dkey))
			{
				orphans.Add(dkeyNew, orphans[dkey]);
				orphans.Remove(dkey);
			}
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class Container_Awake_Patch
	{
		private static void Postfix(Container __instance)
		{
			if (Mod.modEnabled.Value && !((Object)__instance).name.StartsWith("Treasure") && __instance.GetInventory() != null && __instance.m_nview.IsValid() && (__instance.m_nview.GetZDO().GetLong(StringExtensionMethods.GetStableHashCode("creator"), 0L) != 0L || __instance.m_nview.GetZDO().GetOwner() != 0L))
			{
				ContainersTracker.containerList.Add(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Container), "OnDestroyed")]
	internal static class Container_OnDestroyed_Patch
	{
		private static void Prefix(Container __instance)
		{
			if (Mod.modEnabled.Value)
			{
				ContainersTracker.containerList.Remove(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "StackAll")]
	internal static class Container_OnStackAll_Patch
	{
		private static void Postfix(Inventory __instance, Inventory fromInventory, bool message)
		{
			if (Mod.unloadAllEnabled.Value && Mod.unloadAllInsteadStackBtn.Value)
			{
				InventoryGui instance = InventoryGui.instance;
				if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_playerGrid == (Object)null) && !((Object)(object)instance.m_containerGrid == (Object)null) && !((Character)Player.m_localPlayer).IsTeleporting())
				{
					UnloadItems.UnloadAllItems(((Humanoid)Player.m_localPlayer).GetInventory());
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateTeleport")]
	public static class PlayerUpdateTeleport_Patch_Cleanup_Containers
	{
		public static void Prefix(float dt)
		{
			if (Mod.modEnabled.Value)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && localPlayer.m_teleporting && !ContainersTracker.teleportingInProgress)
				{
					ContainersTracker.teleportingInProgress = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateTeleport")]
	public static class PlayerUpdateTeleport_Postfix
	{
		public static void Postfix(float dt)
		{
			if (Mod.modEnabled.Value)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && ContainersTracker.teleportingInProgress && !localPlayer.m_teleporting)
				{
					ContainersTracker.CleanupContainersList();
					ContainersTracker.teleportingInProgress = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	public static class Game_Start_Patch
	{
		private static void Postfix(Game __instance)
		{
			Gui_Patch.Clean();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	public static class Gui_Hide_Patch
	{
		private static void Postfix(InventoryGui __instance)
		{
			if (Gui_Patch.initialized && (Object)(object)Gui_Patch.groupsDialogObj != (Object)null)
			{
				Gui_Patch.groupsDialogObj.SetActive(false);
			}
		}
	}
	public static class UnloadItems
	{
		private static ISet<string> unloadAllItemsList = new HashSet<string>();

		private static ISet<string> unloadAllItemsSkipList = new HashSet<string>();

		public static ICollection<string> unloadAllGroupsList = new HashSet<string>();

		private static ICollection<string> unloadAllPrefixItemGroups = new HashSet<string>();

		private static ICollection<string> unloadAllPostfixItemGroups = new HashSet<string>();

		public static void ParseConfig()
		{
			if (Mod.unloadAllPrefixItemGroups.Value.Length > 0)
			{
				unloadAllPrefixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllPrefixItemGroups);
			}
			if (Mod.unloadAllPostfixItemGroups.Value.Length > 0)
			{
				unloadAllPostfixItemGroups = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllPostfixItemGroups);
			}
			if (Mod.unloadAllItemsList.Value.Length > 0)
			{
				unloadAllItemsList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllItemsList);
			}
			if (Mod.unloadAllSkipList.Value.Length > 0)
			{
				unloadAllItemsSkipList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllSkipList);
			}
			if (Mod.unloadAllGroupsList.Value.Length > 0)
			{
				unloadAllGroupsList = ItemGroupUtils.ParseGroupConfigEntry(Mod.unloadAllGroupsList);
			}
		}

		public static void UnloadAllItems(Inventory playerInv)
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			List<ItemData> list = playerInv.m_inventory.Filter((ItemData i) => !i.m_equipped).Map((ItemData i) => (i: i, i.m_shared.m_name.SCName())).Filter(((ItemData i, string) tuple) => !Mod.onlyStackableItems.Value || tuple.i.m_shared.m_maxStackSize > 1)
				.Filter(((ItemData i, string) tuple) => !unloadAllItemsSkipList.Contains(tuple.Item2))
				.Filter(((ItemData i, string) tuple) => (Mod.unloadAllMaterialsFiltering.Value && (int)tuple.i.m_shared.m_itemType == 1) || (Mod.unloadAllTrophiesFiltering.Value && (int)tuple.i.m_shared.m_itemType == 13) || (Mod.unloadAllConsumableFiltering.Value && (int)tuple.i.m_shared.m_itemType == 2) || (unloadAllItemsList.Any() && unloadAllItemsList.Contains(tuple.Item2)) || (unloadAllPrefixItemGroups.Any() && TestList((string _) => tuple.Item2.StartsWith(_), unloadAllPrefixItemGroups)) || (unloadAllPostfixItemGroups.Any() && TestList((string _) => tuple.Item2.EndsWith(_), unloadAllPostfixItemGroups)) || (unloadAllGroupsList.Any() && unloadAllGroupsList.Any((string groupId) => ItemGroups.Groups.ContainsKey(groupId) && TestList((string _) => tuple.Item2.Equals(_), ItemGroups.Groups[groupId]))))
				.Map(((ItemData i, string) tuple) => tuple.i)
				.ToList();
			bool flag = false;
			foreach (ItemData item in list)
			{
				if (Inventory_Patch.TryAddToNearBy(item, allowCurrent: true, Mod.unloadForceGrouping.Value))
				{
					playerInv.RemoveItem(item);
					if (!flag)
					{
						Mod.PlayEffect(Mod.audioFeedbackEnabled.Value, "sfx_lootspawn", ((Character)Player.m_localPlayer).GetCenterPoint());
						flag = true;
					}
				}
			}
		}

		public static void AddToUnloadAllItemsFilter(Inventory inventory)
		{
			Mod.unloadAllItemsList = AddToItemListConfig(inventory, unloadAllItemsList, Mod.unloadAllItemsList, "Added {0} items to unload-items filter");
		}

		public static void AddToUnloadAllItemsSkipList(Inventory inventory)
		{
			Mod.unloadAllSkipList = AddToItemListConfig(inventory, unloadAllItemsSkipList, Mod.unloadAllSkipList, "Added {0} items to unload-skip-items list");
		}

		private static ConfigEntry<string> AddToItemListConfig(Inventory inventory, ISet<string> targetSet, ConfigEntry<string> configEntry, string uiMessage)
		{
			List<string> list = ItemGroupUtils.ExtractUniqueItemNames(inventory);
			if (list.Count >= 1)
			{
				return ItemGroupUtils.AddToItemListConfig(list, targetSet, configEntry, uiMessage);
			}
			return configEntry;
		}

		private static bool TestList(Func<string, bool> predicate, ICollection<string> group)
		{
			foreach (string item in group)
			{
				if (predicate(item))
				{
					return true;
				}
			}
			return false;
		}

		public static void Clear()
		{
			unloadAllItemsList.Clear();
			unloadAllItemsSkipList.Clear();
			unloadAllGroupsList.Clear();
			unloadAllPrefixItemGroups.Clear();
			unloadAllPostfixItemGroups.Clear();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}