Decompiled source of BagOHeim v1.4.0

plugins/BagOHeim.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BagOHeim")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c235aeab0e13e672a1f60ca17ae0eb4da89c9489")]
[assembly: AssemblyProduct("BagOHeim")]
[assembly: AssemblyTitle("BagOHeim")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BagOHeim
{
	internal static class AmmoSupply
	{
		public static bool Armed;

		private static bool _busy;

		public static void FindInPacks(Inventory inventory, string ammoName, string matchPrefab, ref ItemData result)
		{
			if (result != null || !Armed || _busy || !BagOHeimPlugin.AmmoFromPacks.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || inventory != ((Humanoid)localPlayer).GetInventory())
			{
				return;
			}
			_busy = true;
			try
			{
				if (TakeOut(localPlayer, ammoName, matchPrefab))
				{
					result = inventory.GetAmmoItem(ammoName, matchPrefab);
				}
			}
			finally
			{
				_busy = false;
			}
		}

		private static bool IsMatch(ItemData item, string ammoName, string matchPrefab)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			if ((Object)(object)item.m_dropPrefab != (Object)null && ((int)item.m_shared.m_itemType == 9 || (int)item.m_shared.m_itemType == 23) && item.m_shared.m_ammoType == ammoName)
			{
				if (matchPrefab != null)
				{
					return ((Object)item.m_dropPrefab).name == matchPrefab;
				}
				return true;
			}
			return false;
		}

		private static bool TakeOut(Player player, string ammoName, string matchPrefab)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (ItemData item in inventory.m_inventory.ToList())
			{
				Pack pack = Pack.From(item);
				if (pack == null || pack.Locked)
				{
					continue;
				}
				Inventory val = PackView.LiveInventoryOf(item);
				Inventory val2 = val ?? pack.LoadInventory();
				if (pack.Unreadable)
				{
					continue;
				}
				ItemData val3 = ((IEnumerable<ItemData>)val2.m_inventory).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => IsMatch(i, ammoName, matchPrefab)));
				if (val3 == null)
				{
					continue;
				}
				int num = Mathf.Min(val3.m_stack, val3.m_shared.m_maxStackSize);
				ItemData val4 = val3.Clone();
				val4.m_stack = num;
				val4.m_equipped = false;
				if (inventory.CanAddItem(val4, num))
				{
					val2.RemoveItem(val3, num);
					if (val != null)
					{
						val.Changed(false, false);
					}
					else
					{
						pack.Save(val2);
					}
					inventory.AddItem(val4);
					inventory.Changed(false, false);
					((Character)player).Message((MessageType)1, $"Took {num} {Refill.Name(val4.m_shared)} from {pack.Name}", 0, (Sprite)null, false);
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Attack), "StartDraw")]
	internal static class DrawPatch
	{
		private static void Prefix(Humanoid character)
		{
			AmmoSupply.Armed = (Object)(object)character == (Object)(object)Player.m_localPlayer;
		}

		private static void Finalizer()
		{
			AmmoSupply.Armed = false;
		}
	}
	[HarmonyPatch(typeof(Attack), "Start")]
	internal static class ShootPatch
	{
		private static void Prefix(Humanoid character)
		{
			AmmoSupply.Armed = (Object)(object)character == (Object)(object)Player.m_localPlayer;
		}

		private static void Finalizer()
		{
			AmmoSupply.Armed = false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetAmmoItem")]
	internal static class FindAmmoPatch
	{
		private static void Postfix(Inventory __instance, string ammoName, string matchPrefabName, ref ItemData __result)
		{
			AmmoSupply.FindInPacks(__instance, ammoName, matchPrefabName, ref __result);
		}
	}
	public enum PackIconStyle
	{
		Backpack,
		IconOnly
	}
	[BepInPlugin("mbaya.BagOHeim", "Bag O' Heim", "1.4.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class BagOHeimPlugin : BaseUnityPlugin
	{
		public const string Guid = "mbaya.BagOHeim";

		public const string Name = "Bag O' Heim";

		public const string Version = "1.4.0";

		private const string BasePrefab = "LeatherScraps";

		private const float AutoRefillCheckSeconds = 2f;

		internal static ManualLogSource Log;

		internal static ConfigEntry<RangeMode> Mode;

		internal static ConfigEntry<float> Range;

		internal static ConfigEntry<int> PackWidth;

		internal static ConfigEntry<int> PackHeight;

		internal static ConfigEntry<float> WeightFactor;

		internal static ConfigEntry<NamingStyle> Naming;

		internal static ConfigEntry<KeyboardShortcut> RefillKey;

		internal static ConfigEntry<bool> AutoRefill;

		internal static ConfigEntry<bool> TakeFromInventory;

		internal static ConfigEntry<bool> AmmoFromPacks;

		internal static ConfigEntry<bool> PackMaterials;

		internal static ConfigEntry<PackIconStyle> IconStyle;

		internal static ConfigEntry<float> PanelScale;

		internal static ConfigEntry<bool> ShowContentsIcon;

		internal static ConfigEntry<bool> AutoPickupEnabled;

		internal static ConfigEntry<float> PanelOffsetX;

		internal static ConfigEntry<float> PanelOffsetY;

		internal static ConfigEntry<bool> EquipFromPacks;

		internal static ConfigEntry<int> PortalBagWood;

		private Harmony _harmony;

		private float _nextAutoCheck;

		private bool _wasInBase;

		private void Awake()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Expected O, but got Unknown
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Expected O, but got Unknown
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Mode = ((BaseUnityPlugin)this).Config.Bind<RangeMode>("General", "RangeMode", RangeMode.Workbench, "Which chests packs refill from. Workbench = chests in your base: within build range of the workbench you're near (workbenches with overlapping ranges count as one base). Distance = within 'Range' meters of you.");
			Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 50f, "Used when RangeMode is Distance: how far (in meters) chests can be.");
			PackWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Packs", "Columns", 4, new ConfigDescription("Slots across in each pack.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>()));
			PackHeight = ((BaseUnityPlugin)this).Config.Bind<int>("Packs", "Rows", 2, new ConfigDescription("Rows of slots in each pack.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
			WeightFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Packs", "ContentsWeight", 0.5f, new ConfigDescription("How much a pack's contents count toward carry weight: 1 = full weight, 0.5 = half, 0 = weightless.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			AmmoFromPacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Packs", "UseAmmoFromPacks", true, "Bows and crossbows use arrows and bolts from packs you're carrying (such as a Bag O' Arrows). When you start to draw or shoot with none in your inventory, a stack is taken out of a pack into your inventory. Refilling puts spare ammo back.");
			PackMaterials = ((BaseUnityPlugin)this).Config.Bind<bool>("Packs", "UsePackContentsForBuilding", true, "Materials inside packs you're carrying count when you build or craft, so you don't have to take them out first (a Bag O' Portals can supply the portal's materials). Whatever your inventory can't cover is taken out of the packs.");
			EquipFromPacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Packs", "EquipFromPacks", true, "Right-click a weapon, armour, arrows or other equipment in an open pack to equip it. It is moved into your inventory first, because the game only equips what's in your inventory.");
			IconStyle = ((BaseUnityPlugin)this).Config.Bind<PackIconStyle>("Packs", "IconStyle", PackIconStyle.Backpack, "How a pack looks in your inventory. Backpack = a backpack with a big, white-outlined icon of its contents on the front. IconOnly = just that icon, outlined in white, filling the slot. Takes effect on next game start.");
			ShowContentsIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("Packs", "ShowContentsIcon", false, "Also show a small icon of a pack's main contents in the corner of its inventory slot. Off by default, since the pack's own icon already shows what it's for.");
			AutoPickupEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Packs", "AutoPickup", true, "Allow packs to pick up the items they're set to hold. Each pack has its own Auto-pickup switch (off by default); this turns the feature off for all of them.");
			PanelOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Packs", "PanelOffsetX", 0f, new ConfigDescription("Where you dragged the settings panel to, sideways from its usual spot beside the pack. Saved automatically; double-click the panel to reset.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3000f, 3000f), Array.Empty<object>()));
			PanelOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Packs", "PanelOffsetY", 0f, new ConfigDescription("Where you dragged the settings panel to, up or down from its usual spot. Saved automatically.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3000f, 3000f), Array.Empty<object>()));
			PanelScale = ((BaseUnityPlugin)this).Config.Bind<float>("Packs", "PanelScale", 0f, new ConfigDescription("Size of the settings panel beside an open pack. 0 = match the game's own windows automatically. Set a number (1 = normal, 1.5 = half as big again) if it still looks too small or too large on your screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>()));
			PortalBagWood = ((BaseUnityPlugin)this).Config.Bind<int>("Packs", "PortalBagWood", 20, new ConfigDescription("How much Wood a Bag O' Portals holds, so you can build the workbench a portal needs to be built near (0 = none). Applies to Portal bags you haven't set amounts for yourself.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200), Array.Empty<object>()));
			Naming = ((BaseUnityPlugin)this).Config.Bind<NamingStyle>("Packs", "NamingStyle", NamingStyle.BagO, "Default pack names. BagO = Bag O' Potions, Bag O' Lunch, Bag O' Arrows, Bag O' Portals, Bag O' Stuff. Plain = Potion Pack, Lunchbox, Quiver, Portal Bag, Backpack. Packs you've renamed keep their name. Crafting menu names update on next game start.");
			RefillKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Refill", "RefillKey", new KeyboardShortcut((KeyCode)107, Array.Empty<KeyCode>()), "Refill every pack you're carrying from chests in your base.");
			TakeFromInventory = ((BaseUnityPlugin)this).Config.Bind<bool>("Refill", "TakeFromInventory", true, "Refilling a pack also uses matching items from your own inventory (never what you're wearing or holding, and never other packs), so it works away from your base. Chests in your base are used for whatever is still missing.");
			AutoRefill = ((BaseUnityPlugin)this).Config.Bind<bool>("Refill", "AutoRefillOnEnteringBase", false, "Refill your packs automatically whenever you walk into your base.");
			PrefabManager.OnVanillaPrefabsAvailable += AddPacks;
			_harmony = new Harmony("mbaya.BagOHeim");
			_harmony.PatchAll(typeof(BagOHeimPlugin).Assembly);
			Log.LogInfo((object)"Bag O' Heim 1.4.0 loaded");
		}

		private void AddPacks()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			PrefabManager.OnVanillaPrefabsAvailable -= AddPacks;
			PackKinds.Info[] all = PackKinds.All;
			foreach (PackKinds.Info info in all)
			{
				CustomItem val = new CustomItem(info.Prefab, "LeatherScraps", new ItemConfig
				{
					Name = info.Label,
					Description = info.Description,
					CraftingStation = "piece_workbench",
					Requirements = ((IEnumerable<(string, int)>)info.Recipe).Select((Func<(string, int), RequirementConfig>)(((string item, int amount) r) => new RequirementConfig(r.item, r.amount, 0, true))).ToArray(),
					Icons = PackIcon(info.IconPrefab)
				});
				ItemDrop itemDrop = val.ItemDrop;
				if ((Object)(object)itemDrop == (Object)null)
				{
					Log.LogError((object)("Could not create " + info.Label + "."));
					continue;
				}
				SharedData shared = itemDrop.m_itemData.m_shared;
				shared.m_itemType = (ItemType)16;
				shared.m_maxStackSize = 1;
				shared.m_maxQuality = 1;
				shared.m_weight = 1f;
				shared.m_teleportable = true;
				shared.m_value = 0;
				ItemManager.Instance.AddItem(val);
			}
			PackIcons.ReleaseCopies();
		}

		private static Sprite[] PackIcon(string prefabName)
		{
			Sprite val = GameIcon(prefabName);
			Sprite val2 = PackIcons.Compose(val) ?? val;
			if (!((Object)(object)val2 != (Object)null))
			{
				return null;
			}
			return (Sprite[])(object)new Sprite[1] { val2 };
		}

		private static Sprite GameIcon(string prefabName)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				Log.LogWarning((object)("Icon prefab " + prefabName + " not found; using the default icon."));
				return null;
			}
			ItemDrop component = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				return component.m_itemData.m_shared.m_icons.FirstOrDefault();
			}
			Piece component2 = prefab.GetComponent<Piece>();
			if (!((Object)(object)component2 != (Object)null))
			{
				return null;
			}
			return component2.m_icon;
		}

		private void Update()
		{
			//IL_0026: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			PackView.Update();
			PackPanel.Update();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (!IsTyping())
			{
				KeyboardShortcut value = RefillKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Refill.AllCarried(localPlayer);
				}
			}
			if (AutoRefill.Value && Time.time >= _nextAutoCheck)
			{
				_nextAutoCheck = Time.time + 2f;
				bool isValid = BaseArea.For(((Component)localPlayer).transform.position).IsValid;
				if (isValid && !_wasInBase)
				{
					Refill.AllCarried(localPlayer, quiet: true);
				}
				_wasInBase = isValid;
			}
		}

		private static bool IsTyping()
		{
			if (!PackPanel.IsTyping && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible())
			{
				return Menu.IsVisible();
			}
			return true;
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class BagPickup
	{
		private class Slot
		{
			public ItemData PackItem;

			public Pack Pack;

			public Inventory Live;

			public int Room;
		}

		private static int _active;

		private static float _lastMessage;

		public static bool Active => _active > 0;

		private static bool Enabled => BagOHeimPlugin.AutoPickupEnabled.Value;

		public static void Enter()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				_active++;
			}
		}

		public static void Leave()
		{
			if (_active > 0)
			{
				_active--;
			}
		}

		private static List<Slot> Wanting(Player player, ItemData incoming)
		{
			List<Slot> list = new List<Slot>();
			if (!Enabled || incoming == null || (Object)(object)incoming.m_dropPrefab == (Object)null || PackKinds.IsPack(incoming))
			{
				return list;
			}
			string prefab = ((Object)incoming.m_dropPrefab).name;
			foreach (ItemData item in ((Humanoid)player).GetInventory().m_inventory)
			{
				Pack pack = Pack.From(item);
				if (pack == null || pack.Locked || !pack.AutoPickup || !PackKinds.Accepts(pack.Kind, incoming))
				{
					continue;
				}
				PackTarget packTarget = pack.Targets.FirstOrDefault((PackTarget t) => t.Prefab == prefab);
				if (packTarget == null)
				{
					continue;
				}
				Inventory val = PackView.LiveInventoryOf(item);
				Inventory inventory = val ?? pack.LoadInventory();
				if (!pack.Unreadable)
				{
					int num = packTarget.Amount - Pack.Count(inventory, prefab);
					if (num > 0)
					{
						list.Add(new Slot
						{
							PackItem = item,
							Pack = pack,
							Live = val,
							Room = num
						});
					}
				}
			}
			return list;
		}

		public static bool CanTakeAll(Player player, ItemData incoming, int stack)
		{
			if (stack <= 0)
			{
				stack = incoming?.m_stack ?? 0;
			}
			if (stack > 0)
			{
				return Wanting(player, incoming).Sum((Slot s) => s.Room) >= stack;
			}
			return false;
		}

		public static int Absorb(Player player, ItemData incoming)
		{
			int num = 0;
			foreach (Slot item in Wanting(player, incoming))
			{
				if (incoming.m_stack <= 0)
				{
					break;
				}
				Inventory val = item.Live ?? item.Pack.LoadInventory();
				int num2 = Mathf.Min(item.Room, incoming.m_stack);
				ItemData val2 = incoming.Clone();
				val2.m_stack = num2;
				val2.m_equipped = false;
				if (!val.CanAddItem(val2, num2))
				{
					num2 = FitInto(val, incoming, num2);
					if (num2 <= 0)
					{
						continue;
					}
					val2.m_stack = num2;
				}
				val.AddItem(val2);
				if (item.Live != null)
				{
					item.Live.Changed(false, false);
				}
				else
				{
					item.Pack.Save(val);
				}
				incoming.m_stack -= num2;
				num += num2;
				Say(player, num2, incoming, item.Pack);
			}
			if (num > 0)
			{
				((Humanoid)player).GetInventory().Changed(false, false);
			}
			return num;
		}

		private static int FitInto(Inventory contents, ItemData incoming, int want)
		{
			for (int num = want; num > 0; num--)
			{
				ItemData val = incoming.Clone();
				val.m_stack = num;
				if (contents.CanAddItem(val, num))
				{
					return num;
				}
			}
			return 0;
		}

		private static void Say(Player player, int amount, ItemData item, Pack pack)
		{
			if (!(Time.time - _lastMessage < 0.5f))
			{
				_lastMessage = Time.time;
				((Character)player).Message((MessageType)1, $"{amount} {Refill.Name(item.m_shared)} into {pack.Name}", 0, (Sprite)null, false);
			}
		}
	}
	[HarmonyPatch]
	internal static class PickupStartPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Humanoid), "Pickup", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				yield return methodInfo;
			}
			MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(Player), "Pickup", (Type[])null, (Type[])null);
			if (methodInfo2 != null)
			{
				yield return methodInfo2;
			}
			MethodInfo methodInfo3 = AccessTools.Method(typeof(Player), "AutoPickup", (Type[])null, (Type[])null);
			if (methodInfo3 != null)
			{
				yield return methodInfo3;
			}
		}

		private static void Prefix(object __instance)
		{
			if (__instance == Player.m_localPlayer)
			{
				BagPickup.Enter();
			}
		}

		private static void Finalizer(object __instance)
		{
			if (__instance == Player.m_localPlayer)
			{
				BagPickup.Leave();
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	internal static class AbsorbPatch
	{
		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (!BagPickup.Active || !PackMaterials.IsPlayersInventory(__instance))
			{
				return true;
			}
			BagPickup.Absorb(Player.m_localPlayer, item);
			if (item.m_stack > 0)
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	internal static class CanAbsorbPatch
	{
		private static void Postfix(Inventory __instance, ItemData item, int stack, ref bool __result)
		{
			if (!__result && BagPickup.Active && PackMaterials.IsPlayersInventory(__instance))
			{
				__result = BagPickup.CanTakeAll(Player.m_localPlayer, item, stack);
			}
		}
	}
	public enum RangeMode
	{
		Workbench,
		Distance
	}
	internal class BaseArea
	{
		private const string WorkbenchName = "$piece_workbench";

		private readonly Vector3 _origin;

		private readonly float _distance;

		private readonly List<CraftingStation> _workbenches;

		public bool IsValid
		{
			get
			{
				if (_workbenches != null)
				{
					return _workbenches.Count > 0;
				}
				return true;
			}
		}

		private BaseArea(Vector3 origin, float distance, List<CraftingStation> workbenches)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			_origin = origin;
			_distance = distance;
			_workbenches = workbenches;
		}

		public static BaseArea For(Vector3 position)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (BagOHeimPlugin.Mode.Value == RangeMode.Distance)
			{
				return new BaseArea(position, BagOHeimPlugin.Range.Value, null);
			}
			return new BaseArea(position, 0f, ConnectedWorkbenches(position));
		}

		public bool Contains(Vector3 point)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (_workbenches == null)
			{
				return Vector3.Distance(_origin, point) <= _distance;
			}
			return _workbenches.Any((CraftingStation w) => (Object)(object)w != (Object)null && Vector3.Distance(((Component)w).transform.position, point) <= w.GetStationBuildRange());
		}

		public float DistanceFrom(Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.Distance(_origin, point);
		}

		public string Describe()
		{
			if (_workbenches != null)
			{
				return "in this base";
			}
			return $"within {BagOHeimPlugin.Range.Value:0} m";
		}

		private static List<CraftingStation> ConnectedWorkbenches(Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			List<CraftingStation> list = CraftingStation.m_allStations.Where((CraftingStation s) => (Object)(object)s != (Object)null && s.m_name == "$piece_workbench").ToList();
			List<CraftingStation> list2 = list.Where((CraftingStation s) => Vector3.Distance(((Component)s).transform.position, position) <= s.GetStationBuildRange()).ToList();
			Queue<CraftingStation> queue = new Queue<CraftingStation>(list2);
			while (queue.Count > 0)
			{
				CraftingStation val = queue.Dequeue();
				foreach (CraftingStation item in list)
				{
					if (!list2.Contains(item))
					{
						float num = val.GetStationBuildRange() + item.GetStationBuildRange();
						if (Vector3.Distance(((Component)val).transform.position, ((Component)item).transform.position) <= num)
						{
							list2.Add(item);
							queue.Enqueue(item);
						}
					}
				}
			}
			return list2;
		}
	}
	internal static class ChestSupply
	{
		public static int Take(Player player, BaseArea area, string prefab, int amount, out ItemData template)
		{
			template = null;
			if (amount <= 0)
			{
				return 0;
			}
			int num = 0;
			foreach (Container item in Sources(player, area))
			{
				Inventory inventory = item.GetInventory();
				if (!inventory.m_inventory.Any((ItemData i) => Matches(i, prefab)))
				{
					continue;
				}
				if (!item.m_nview.IsOwner())
				{
					item.m_nview.ClaimOwnership();
					item.Load();
				}
				foreach (ItemData item2 in inventory.m_inventory.ToList())
				{
					if (Matches(item2, prefab))
					{
						int num2 = Mathf.Min(amount - num, item2.m_stack);
						if (template == null)
						{
							template = item2.Clone();
						}
						inventory.RemoveItem(item2, num2);
						num += num2;
						if (num >= amount)
						{
							return num;
						}
					}
				}
			}
			return num;
		}

		private static bool Matches(ItemData item, string prefab)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return ((Object)item.m_dropPrefab).name == prefab;
			}
			return false;
		}

		private static IEnumerable<Container> Sources(Player player, BaseArea area)
		{
			long playerId = player.GetPlayerID();
			return from c in Object.FindObjectsByType<Container>((FindObjectsSortMode)0)
				where IsUsable(c, playerId) && area.Contains(((Component)c).transform.position)
				orderby area.DistanceFrom(((Component)c).transform.position)
				select c;
		}

		private static bool IsUsable(Container c, long playerId)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null || (Object)(object)c.m_nview == (Object)null || !c.m_nview.IsValid())
			{
				return false;
			}
			if (c.GetInventory() == null || PackView.IsPackContainer(c))
			{
				return false;
			}
			if ((Object)(object)((Component)c).GetComponent<TombStone>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)c.m_rootObjectOverride != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)c).GetComponentInParent<Ship>() != (Object)null || (Object)(object)((Component)c).GetComponentInParent<Vagon>() != (Object)null)
			{
				return false;
			}
			if (c.IsInUse() || c.m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1)
			{
				return false;
			}
			if (!c.CheckAccess(playerId))
			{
				return false;
			}
			if (c.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	internal static class DropOnBagPatch
	{
		private static bool Prefix(InventoryGui __instance, ItemData item)
		{
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			ItemData dragItem = __instance.m_dragItem;
			Inventory dragInventory = __instance.m_dragInventory;
			if ((Object)(object)__instance.m_dragGo == (Object)null || dragItem == null || dragInventory == null || item == null || item == dragItem)
			{
				return true;
			}
			if (!PackKinds.IsPack(item) || PackKinds.IsPack(dragItem))
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting())
			{
				return true;
			}
			Pack pack = new Pack(item);
			if (!PackKinds.Accepts(pack.Kind, dragItem))
			{
				return true;
			}
			Inventory val = PackView.LiveInventoryOf(item);
			if (val != null && val == dragInventory)
			{
				return true;
			}
			Inventory val2 = val ?? pack.LoadInventory();
			if (pack.Unreadable)
			{
				return true;
			}
			int num = Mathf.Clamp(__instance.m_dragAmount, 1, dragItem.m_stack);
			ItemData val3 = dragItem.Clone();
			val3.m_stack = num;
			val3.m_equipped = false;
			if (!val2.CanAddItem(val3, num))
			{
				((Character)localPlayer).Message((MessageType)2, pack.Name + " has no room for that", 0, (Sprite)null, false);
				return false;
			}
			((Humanoid)localPlayer).RemoveEquipAction(dragItem);
			((Humanoid)localPlayer).UnequipItem(dragItem, false);
			dragInventory.RemoveItem(dragItem, num);
			val2.AddItem(val3);
			if (val != null)
			{
				val.Changed(false, false);
			}
			else
			{
				pack.Save(val2);
			}
			((Humanoid)localPlayer).GetInventory().Changed(false, false);
			__instance.SetupDragItem((ItemData)null, (Inventory)null, 1);
			__instance.m_moveItemEffects.Create(((Component)__instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	internal static class EquipFromPackPatch
	{
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item)
		{
			if (!BagOHeimPlugin.EquipFromPacks.Value || item == null)
			{
				return true;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (inventory != null && inventory != ((Humanoid)val).GetInventory())
			{
				BagOHeimPlugin.Log.LogInfo((object)$"Right-click in another inventory: item={item.m_shared.m_name} openPack={PackView.OpenInventory != null} isThePack={inventory == PackView.OpenInventory} equipable={item.IsEquipable()}");
			}
			if (inventory == null || inventory == ((Humanoid)val).GetInventory() || inventory != PackView.OpenInventory)
			{
				return true;
			}
			if (!item.IsEquipable())
			{
				return true;
			}
			Equip(val, inventory, item);
			return false;
		}

		private static void Equip(Player player, Inventory pack, ItemData item)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			int num = Mathf.Min(item.m_stack, item.m_shared.m_maxStackSize);
			ItemData moved = item.Clone();
			moved.m_stack = num;
			moved.m_equipped = false;
			if (!inventory.CanAddItem(moved, num))
			{
				((Character)player).Message((MessageType)2, "No room in your inventory to equip that", 0, (Sprite)null, false);
				return;
			}
			pack.RemoveItem(item, num);
			inventory.AddItem(moved);
			inventory.Changed(false, false);
			ItemData val = (ItemData)(inventory.ContainsItem(moved) ? ((object)moved) : ((object)((IEnumerable<ItemData>)inventory.m_inventory).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => (Object)(object)i.m_dropPrefab == (Object)(object)moved.m_dropPrefab && i.m_worldLevel == moved.m_worldLevel))));
			bool flag = false;
			if (val != null)
			{
				((Humanoid)player).UseItem(inventory, val, true);
				flag = ((Humanoid)player).IsItemEquiped(val) || player.IsEquipActionQueued(val);
			}
			BagOHeimPlugin.Log.LogInfo((object)$"Equip from pack: {item.m_shared.m_name} equipped or queued={flag}");
			if (!flag)
			{
				if (val != null)
				{
					inventory.RemoveItem(val, num);
					pack.AddItem(item.Clone());
					inventory.Changed(false, false);
				}
				((Character)player).Message((MessageType)2, "Can't equip that right now", 0, (Sprite)null, false);
			}
		}
	}
	internal static class InventorySupply
	{
		public static int Take(Player player, string prefab, int amount, out ItemData template)
		{
			template = null;
			if (amount <= 0 || !BagOHeimPlugin.TakeFromInventory.Value)
			{
				return 0;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			int num = 0;
			foreach (ItemData item in inventory.m_inventory.ToList())
			{
				if (!((Object)(object)item.m_dropPrefab == (Object)null) && !(((Object)item.m_dropPrefab).name != prefab) && !item.m_equipped && !PackKinds.IsPack(item))
				{
					int num2 = Mathf.Min(amount - num, item.m_stack);
					if (template == null)
					{
						template = item.Clone();
					}
					inventory.RemoveItem(item, num2);
					num += num2;
					if (num >= amount)
					{
						break;
					}
				}
			}
			return num;
		}
	}
	internal class PackTarget
	{
		public string Prefab;

		public int Amount;
	}
	internal class Pack
	{
		internal const string ItemsKey = "BOH.Items";

		private const string TargetsKey = "BOH.Targets";

		private const string NameKey = "BOH.Name";

		private const string WeightKey = "BOH.Weight";

		private const string MainKey = "BOH.Main";

		private const string HaveKey = "BOH.Have";

		private const string WantKey = "BOH.Want";

		private const string NoTeleportKey = "BOH.NoTeleport";

		private const string LockKey = "BOH.Locked";

		private const string IconKey = "BOH.Icon";

		private const string AutoKey = "BOH.Auto";

		public readonly ItemData Item;

		public readonly PackKinds.Info Info;

		public bool Unreadable { get; private set; }

		public PackKind Kind => Info.Kind;

		public string IconPrefab
		{
			get
			{
				if (!Item.m_customData.TryGetValue("BOH.Icon", out var value) || value.Length <= 0)
				{
					return null;
				}
				return value;
			}
			set
			{
				if (string.IsNullOrEmpty(value))
				{
					Item.m_customData.Remove("BOH.Icon");
				}
				else
				{
					Item.m_customData["BOH.Icon"] = value;
				}
			}
		}

		public string ShownIconPrefab => IconPrefab ?? Info.IconPrefab;

		public bool AutoPickup
		{
			get
			{
				return Item.m_customData.ContainsKey("BOH.Auto");
			}
			set
			{
				if (value)
				{
					Item.m_customData["BOH.Auto"] = "1";
				}
				else
				{
					Item.m_customData.Remove("BOH.Auto");
				}
			}
		}

		public bool Locked
		{
			get
			{
				return Item.m_customData.ContainsKey("BOH.Locked");
			}
			set
			{
				if (value)
				{
					Item.m_customData["BOH.Locked"] = "1";
				}
				else
				{
					Item.m_customData.Remove("BOH.Locked");
				}
			}
		}

		public string Name
		{
			get
			{
				if (!Item.m_customData.TryGetValue("BOH.Name", out var value) || value.Length <= 0)
				{
					return Info.Label;
				}
				return value;
			}
			set
			{
				value = (value ?? "").Trim();
				if (value.Length == 0 || value == Info.Label)
				{
					Item.m_customData.Remove("BOH.Name");
				}
				else
				{
					Item.m_customData["BOH.Name"] = ((value.Length > 32) ? value.Substring(0, 32) : value);
				}
			}
		}

		public float ContentsWeight
		{
			get
			{
				if (!Item.m_customData.TryGetValue("BOH.Weight", out var value) || !float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					return 0f;
				}
				return result;
			}
		}

		public string MainPrefab
		{
			get
			{
				if (!Item.m_customData.TryGetValue("BOH.Main", out var value))
				{
					return null;
				}
				return value;
			}
		}

		public int Have
		{
			get
			{
				if (!Item.m_customData.TryGetValue("BOH.Have", out var value) || !int.TryParse(value, out var result))
				{
					return 0;
				}
				return result;
			}
		}

		public int Want
		{
			get
			{
				if (!Item.m_customData.TryGetValue("BOH.Want", out var value) || !int.TryParse(value, out var result))
				{
					return 0;
				}
				return result;
			}
		}

		public bool HoldsNonTeleportable => Item.m_customData.ContainsKey("BOH.NoTeleport");

		public List<PackTarget> Targets
		{
			get
			{
				if (Item.m_customData.TryGetValue("BOH.Targets", out var value))
				{
					return Parse(value);
				}
				if (Kind == PackKind.Portals)
				{
					List<PackTarget> list = (from c in PackKinds.PortalCost()
						select new PackTarget
						{
							Prefab = c.prefab,
							Amount = c.amount * 2
						}).ToList();
					int value2 = BagOHeimPlugin.PortalBagWood.Value;
					if (value2 > 0)
					{
						list.Add(new PackTarget
						{
							Prefab = "Wood",
							Amount = value2
						});
					}
					return list;
				}
				return new List<PackTarget>();
			}
			set
			{
				IEnumerable<PackTarget> source = from t in value
					where !string.IsNullOrEmpty(t.Prefab) && t.Amount > 0
					group t by t.Prefab into g
					select new PackTarget
					{
						Prefab = g.Key,
						Amount = g.Sum((PackTarget t) => t.Amount)
					};
				Item.m_customData["BOH.Targets"] = string.Join(";", source.Select((PackTarget t) => $"{t.Prefab}={t.Amount}"));
			}
		}

		public Pack(ItemData item)
		{
			Item = item;
			Info = PackKinds.Of(item);
		}

		public static Pack From(ItemData item)
		{
			if (!PackKinds.IsPack(item))
			{
				return null;
			}
			return new Pack(item);
		}

		public Inventory LoadInventory()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			Inventory val = new Inventory(Name, (Sprite)null, BagOHeimPlugin.PackWidth.Value, BagOHeimPlugin.PackHeight.Value);
			if (Item.m_customData.TryGetValue("BOH.Items", out var value) && value.Length > 0)
			{
				try
				{
					val.Load(new ZPackage(Convert.FromBase64String(value)));
					ReHome(val);
				}
				catch (Exception ex)
				{
					Unreadable = true;
					BagOHeimPlugin.Log.LogError((object)("Could not read the contents of '" + Name + "'; leaving it untouched. " + ex.Message));
				}
			}
			return val;
		}

		private static void ReHome(Inventory inventory)
		{
			//IL_0063: 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)
			foreach (ItemData item in inventory.m_inventory.Where((ItemData i) => i.m_gridPos.x < 0 || i.m_gridPos.y < 0 || i.m_gridPos.x >= inventory.GetWidth() || i.m_gridPos.y >= inventory.GetHeight()).ToList())
			{
				Vector2i slot;
				while (!TryFreeSlot(inventory, out slot))
				{
					Inventory obj = inventory;
					obj.m_height++;
				}
				item.m_gridPos = slot;
			}
		}

		private static bool TryFreeSlot(Inventory inventory, out Vector2i slot)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			HashSet<Vector2i> hashSet = new HashSet<Vector2i>(inventory.m_inventory.Select((ItemData i) => i.m_gridPos));
			for (int num = 0; num < inventory.GetHeight(); num++)
			{
				for (int num2 = 0; num2 < inventory.GetWidth(); num2++)
				{
					slot = new Vector2i(num2, num);
					if (!hashSet.Contains(slot))
					{
						return true;
					}
				}
			}
			slot = default(Vector2i);
			return false;
		}

		public void Save(Inventory inventory)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if (Unreadable)
			{
				return;
			}
			ZPackage val = new ZPackage();
			inventory.Save(val);
			Item.m_customData["BOH.Items"] = Convert.ToBase64String(val.GetArray());
			List<ItemData> inventory2 = inventory.m_inventory;
			float num = inventory2.Sum((ItemData i) => i.GetWeight(-1));
			Item.m_customData["BOH.Weight"] = num.ToString(CultureInfo.InvariantCulture);
			IGrouping<string, ItemData> grouping = (from i in inventory2
				group i by (!((Object)(object)i.m_dropPrefab != (Object)null)) ? "" : ((Object)i.m_dropPrefab).name into g
				where g.Key.Length > 0
				orderby g.Sum((ItemData i) => i.m_stack) descending
				select g).FirstOrDefault();
			if (grouping != null)
			{
				Item.m_customData["BOH.Main"] = grouping.Key;
			}
			else
			{
				Item.m_customData.Remove("BOH.Main");
			}
			List<PackTarget> targets = Targets;
			int num2 = targets.Sum((PackTarget t) => t.Amount);
			int num3 = targets.Sum((PackTarget t) => Count(inventory, t.Prefab, t.Amount));
			Item.m_customData["BOH.Have"] = num3.ToString(CultureInfo.InvariantCulture);
			Item.m_customData["BOH.Want"] = num2.ToString(CultureInfo.InvariantCulture);
			if (inventory2.Any((ItemData i) => !i.m_shared.m_teleportable))
			{
				Item.m_customData["BOH.NoTeleport"] = "1";
			}
			else
			{
				Item.m_customData.Remove("BOH.NoTeleport");
			}
		}

		public static int Count(Inventory inventory, string prefab, int cap = int.MaxValue)
		{
			return Math.Min(cap, inventory.m_inventory.Where((ItemData i) => (Object)(object)i.m_dropPrefab != (Object)null && ((Object)i.m_dropPrefab).name == prefab).Sum((ItemData i) => i.m_stack));
		}

		public void RememberContents(Inventory inventory)
		{
			Targets = (from i in inventory.m_inventory
				where (Object)(object)i.m_dropPrefab != (Object)null
				group i by ((Object)i.m_dropPrefab).name into g
				select new PackTarget
				{
					Prefab = g.Key,
					Amount = g.Sum((ItemData i) => i.m_stack)
				}).ToList();
		}

		private static List<PackTarget> Parse(string s)
		{
			List<PackTarget> list = new List<PackTarget>();
			string[] array = s.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split('=');
				if (array2.Length == 2 && int.TryParse(array2[1], out var result) && result > 0)
				{
					list.Add(new PackTarget
					{
						Prefab = array2[0],
						Amount = result
					});
				}
			}
			return list;
		}
	}
	internal static class PackIcons
	{
		private const string BagResource = "BagOHeim.bag.png";

		private const int Size = 128;

		private const int PatchCenterX = 64;

		private const int PatchCenterY = 52;

		private const int PatchBox = 92;

		private const int PatchBorder = 4;

		private const int IconOnlyBox = 118;

		private const int IconOnlyBorder = 4;

		private static Color[] _bag;

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

		private static readonly Dictionary<Texture, Texture2D> Readable = new Dictionary<Texture, Texture2D>();

		public static Sprite ForPrefab(string prefab)
		{
			if (string.IsNullOrEmpty(prefab))
			{
				return null;
			}
			if (ByPrefab.TryGetValue(prefab, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Sprite val = GameSprite(prefab);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Sprite val2 = Compose(val) ?? val;
			ReleaseCopies();
			ByPrefab[prefab] = val2;
			return val2;
		}

		public static Sprite GameSprite(string prefab)
		{
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 != (Object)null && val2.m_itemData.m_shared.m_icons != null && val2.m_itemData.m_shared.m_icons.Length != 0)
			{
				return val2.m_itemData.m_shared.m_icons[0];
			}
			GameObject val3 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			Piece val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<Piece>() : null);
			if (!((Object)(object)val4 != (Object)null))
			{
				return null;
			}
			return val4.m_icon;
		}

		public static Sprite Compose(Sprite patch)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)patch == (Object)null || (Object)(object)patch.texture == (Object)null)
			{
				return null;
			}
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				return null;
			}
			try
			{
				Color[] array = BagPixels();
				if (array == null)
				{
					return null;
				}
				Texture2D obj = ReadableCopy((Texture)(object)patch.texture);
				Rect textureRect = patch.textureRect;
				int num = Mathf.RoundToInt(((Rect)(ref textureRect)).x);
				int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).y);
				int num3 = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
				int num4 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
				Color[] pixels = obj.GetPixels(num, num2, num3, num4);
				bool num5 = BagOHeimPlugin.IconStyle.Value == PackIconStyle.IconOnly;
				Color[] array2 = (Color[])(num5 ? ((Array)new Color[16384]) : ((Array)(Color[])array.Clone()));
				int num6 = (num5 ? 118 : 92);
				int num7 = (num5 ? 4 : 4);
				int num8 = (num5 ? 64 : 64);
				int num9 = (num5 ? 64 : 52);
				float num10 = Mathf.Min((float)num6 / (float)num3, (float)num6 / (float)num4);
				int num11 = Mathf.Max(1, Mathf.RoundToInt((float)num3 * num10));
				int num12 = Mathf.Max(1, Mathf.RoundToInt((float)num4 * num10));
				int num13 = num8 - num11 / 2;
				int num14 = num9 - num12 / 2;
				Color[] array3 = (Color[])(object)new Color[num11 * num12];
				for (int i = 0; i < num12; i++)
				{
					for (int j = 0; j < num11; j++)
					{
						array3[i * num11 + j] = Sample(pixels, num3, num4, ((float)j + 0.5f) / (float)num11 * (float)num3 - 0.5f, ((float)i + 0.5f) / (float)num12 * (float)num4 - 0.5f);
					}
				}
				for (int k = -num7; k < num12 + num7; k++)
				{
					for (int l = -num7; l < num11 + num7; l++)
					{
						int num15 = num13 + l;
						int num16 = num14 + k;
						if (num15 >= 0 && num15 < 128 && num16 >= 0 && num16 < 128 && NearIcon(array3, num11, num12, l, k, num7))
						{
							array2[num16 * 128 + num15] = Over(Color.white, array2[num16 * 128 + num15]);
						}
					}
				}
				for (int m = 0; m < num12; m++)
				{
					for (int n = 0; n < num11; n++)
					{
						int num17 = num13 + n;
						int num18 = num14 + m;
						if (num17 >= 0 && num17 < 128 && num18 >= 0 && num18 < 128)
						{
							array2[num18 * 128 + num17] = Over(array3[m * num11 + n], array2[num18 * 128 + num17]);
						}
					}
				}
				Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
				val.SetPixels(array2);
				((Texture)val).filterMode = (FilterMode)1;
				val.Apply();
				return Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
			}
			catch (Exception ex)
			{
				BagOHeimPlugin.Log.LogWarning((object)("Couldn't put an icon on the backpack; using the plain game icon. " + ex.Message));
				return null;
			}
		}

		private static bool NearIcon(Color[] icon, int w, int h, int x, int y, int radius)
		{
			for (int i = -radius; i <= radius; i++)
			{
				for (int j = -radius; j <= radius; j++)
				{
					if (j * j + i * i <= radius * radius)
					{
						int num = x + j;
						int num2 = y + i;
						if (num >= 0 && num < w && num2 >= 0 && num2 < h && icon[num2 * w + num].a > 0.35f)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static Color[] BagPixels()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (_bag != null)
			{
				return _bag;
			}
			using Stream stream = typeof(PackIcons).Assembly.GetManifestResourceStream("BagOHeim.bag.png");
			if (stream == null)
			{
				BagOHeimPlugin.Log.LogWarning((object)"Missing embedded BagOHeim.bag.png");
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, array);
			if (((Texture)val).width != 128 || ((Texture)val).height != 128)
			{
				return null;
			}
			return _bag = val.GetPixels();
		}

		private static Texture2D ReadableCopy(Texture texture)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (Readable.TryGetValue(texture, out var value))
			{
				return value;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(texture.width, texture.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit(texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(texture.width, texture.height, (TextureFormat)4, false);
				val.ReadPixels(new Rect(0f, 0f, (float)texture.width, (float)texture.height), 0, 0);
				val.Apply();
				Readable[texture] = val;
				return val;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		public static void ReleaseCopies()
		{
			foreach (Texture2D value in Readable.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			Readable.Clear();
		}

		private static Color Sample(Color[] pixels, int w, int h, float u, float v)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			u = Mathf.Clamp(u, 0f, (float)(w - 1));
			v = Mathf.Clamp(v, 0f, (float)(h - 1));
			int num = Mathf.FloorToInt(u);
			int num2 = Mathf.FloorToInt(v);
			int num3 = Mathf.Min(num + 1, w - 1);
			int num4 = Mathf.Min(num2 + 1, h - 1);
			float num5 = u - (float)num;
			float num6 = v - (float)num2;
			Color val = Color.Lerp(pixels[num2 * w + num], pixels[num2 * w + num3], num5);
			Color val2 = Color.Lerp(pixels[num4 * w + num], pixels[num4 * w + num3], num5);
			return Color.Lerp(val, val2, num6);
		}

		private static Color Over(Color s, Color d)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			float num = s.a + d.a * (1f - s.a);
			if (num <= 0f)
			{
				return Color.clear;
			}
			return new Color((s.r * s.a + d.r * d.a * (1f - s.a)) / num, (s.g * s.a + d.g * d.a * (1f - s.a)) / num, (s.b * s.a + d.b * d.a * (1f - s.a)) / num, num);
		}
	}
	public enum NamingStyle
	{
		BagO,
		Plain
	}
	public enum PackKind
	{
		Potions,
		Lunchbox,
		Quiver,
		Portals,
		Backpack
	}
	internal static class PackKinds
	{
		public class Info
		{
			public PackKind Kind;

			public string Prefab;

			public string BagOLabel;

			public string PlainLabel;

			public string Description;

			public string IconPrefab;

			public (string item, int amount)[] Recipe;

			public string Label
			{
				get
				{
					if (BagOHeimPlugin.Naming.Value != NamingStyle.Plain)
					{
						return BagOLabel;
					}
					return PlainLabel;
				}
			}
		}

		public static readonly Info[] All = new Info[5]
		{
			new Info
			{
				Kind = PackKind.Potions,
				Prefab = "BOH_PotionPack",
				BagOLabel = "Bag O' Potions",
				PlainLabel = "Potion Pack",
				IconPrefab = "MeadHealthMinor",
				Description = "Holds potions and meads, and refills them to the amounts you set from your base's chests.",
				Recipe = new(string, int)[3]
				{
					("LeatherScraps", 6),
					("DeerHide", 2),
					("Resin", 2)
				}
			},
			new Info
			{
				Kind = PackKind.Lunchbox,
				Prefab = "BOH_Lunchbox",
				BagOLabel = "Bag O' Lunch",
				PlainLabel = "Lunchbox",
				IconPrefab = "CookedMeat",
				Description = "Holds food, and refills it to the amounts you set from your base's chests.",
				Recipe = new(string, int)[2]
				{
					("Wood", 6),
					("LeatherScraps", 2)
				}
			},
			new Info
			{
				Kind = PackKind.Quiver,
				Prefab = "BOH_Quiver",
				BagOLabel = "Bag O' Arrows",
				PlainLabel = "Quiver",
				IconPrefab = "ArrowWood",
				Description = "Holds arrows and bolts, and refills them to the amounts you set from your base's chests.",
				Recipe = new(string, int)[3]
				{
					("DeerHide", 4),
					("LeatherScraps", 4),
					("Wood", 2)
				}
			},
			new Info
			{
				Kind = PackKind.Portals,
				Prefab = "BOH_PortalBag",
				BagOLabel = "Bag O' Portals",
				PlainLabel = "Portal Bag",
				IconPrefab = "portal_wood",
				Description = "Holds what it takes to build two portals, plus wood for a workbench, and refills it from your inventory and your base's chests.",
				Recipe = new(string, int)[3]
				{
					("DeerHide", 4),
					("LeatherScraps", 4),
					("GreydwarfEye", 2)
				}
			},
			new Info
			{
				Kind = PackKind.Backpack,
				Prefab = "BOH_Backpack",
				BagOLabel = "Bag O' Stuff",
				PlainLabel = "Backpack",
				IconPrefab = "piece_chest",
				Description = "Holds anything. Name it, set its amounts, and it refills from your base's chests.",
				Recipe = new(string, int)[2]
				{
					("DeerHide", 6),
					("LeatherScraps", 8)
				}
			}
		};

		private static readonly Dictionary<string, Info> ByPrefab = All.ToDictionary((Info i) => i.Prefab);

		private const string PortalPrefab = "portal_wood";

		public const string WorkbenchWood = "Wood";

		private static List<(string prefab, int amount)> _portalCost;

		public static Info Of(ItemData item)
		{
			if (!((Object)(object)item?.m_dropPrefab != (Object)null) || !ByPrefab.TryGetValue(((Object)item.m_dropPrefab).name, out var value))
			{
				return null;
			}
			return value;
		}

		public static bool IsPack(ItemData item)
		{
			return Of(item) != null;
		}

		public static bool Accepts(PackKind kind, ItemData item)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Invalid comparison between Unknown and I4
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			if (item == null || IsPack(item))
			{
				return false;
			}
			SharedData shared = item.m_shared;
			bool flag = shared.m_food > 0f || shared.m_foodStamina > 0f || shared.m_foodEitr > 0f;
			switch (kind)
			{
			case PackKind.Quiver:
				if ((int)shared.m_itemType != 9)
				{
					return (int)shared.m_itemType == 23;
				}
				return true;
			case PackKind.Lunchbox:
				return (int)shared.m_itemType == 2 && flag;
			case PackKind.Potions:
				if ((int)shared.m_itemType == 2)
				{
					return !flag;
				}
				return false;
			case PackKind.Portals:
				if ((Object)(object)item.m_dropPrefab != (Object)null)
				{
					if (!(((Object)item.m_dropPrefab).name == "Wood"))
					{
						return PortalCost().Any(((string prefab, int amount) c) => c.prefab == ((Object)item.m_dropPrefab).name);
					}
					return true;
				}
				return false;
			default:
				return true;
			}
		}

		public static string RefusalMessage(PackKind kind)
		{
			return kind switch
			{
				PackKind.Quiver => "This pack only holds arrows and bolts.", 
				PackKind.Lunchbox => "This pack only holds food.", 
				PackKind.Potions => "This pack only holds potions and meads.", 
				PackKind.Portals => "This pack only holds portal materials and wood.", 
				_ => "Packs can't go inside other packs.", 
			};
		}

		public static List<(string prefab, int amount)> PortalCost()
		{
			if (_portalCost != null)
			{
				return _portalCost;
			}
			List<(string, int)> list = new List<(string, int)>();
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("portal_wood") : null);
			Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return list;
			}
			Requirement[] resources = val2.m_resources;
			foreach (Requirement val3 in resources)
			{
				if ((Object)(object)val3?.m_resItem != (Object)null && val3.m_amount > 0)
				{
					list.Add((((Object)val3.m_resItem).name, val3.m_amount));
				}
			}
			return _portalCost = list;
		}
	}
	internal static class PackMaterials
	{
		private struct Entry
		{
			public string Name;

			public int Quality;

			public int WorldLevel;

			public int Stack;
		}

		private class Cached
		{
			public string Data;

			public List<Entry> Entries;
		}

		private static readonly Dictionary<ItemData, Cached> Cache = new Dictionary<ItemData, Cached>();

		private static int _frame = -1;

		private static List<Entry> _all = new List<Entry>();

		public static bool Busy;

		public static bool Enabled => BagOHeimPlugin.PackMaterials.Value;

		private static List<Entry> EntriesOf(ItemData packItem, Pack pack)
		{
			Inventory val = PackView.LiveInventoryOf(packItem);
			if (val != null)
			{
				return Read(val);
			}
			packItem.m_customData.TryGetValue("BOH.Items", out var value);
			value = value ?? "";
			if (Cache.TryGetValue(packItem, out var value2) && value2.Data == value)
			{
				return value2.Entries;
			}
			Inventory inventory = pack.LoadInventory();
			List<Entry> list = (pack.Unreadable ? new List<Entry>() : Read(inventory));
			Cache[packItem] = new Cached
			{
				Data = value,
				Entries = list
			};
			return list;
		}

		private static List<Entry> Read(Inventory inventory)
		{
			return (from i in inventory.m_inventory
				where i.m_shared != null
				select new Entry
				{
					Name = i.m_shared.m_name,
					Quality = i.m_quality,
					WorldLevel = i.m_worldLevel,
					Stack = i.m_stack
				}).ToList();
		}

		private static void Refresh(Player player)
		{
			if (_frame == Time.frameCount)
			{
				return;
			}
			_frame = Time.frameCount;
			_all = new List<Entry>();
			foreach (ItemData item in ((Humanoid)player).GetInventory().m_inventory)
			{
				Pack pack = Pack.From(item);
				if (pack != null && !pack.Locked)
				{
					_all.AddRange(EntriesOf(item, pack));
				}
			}
		}

		private static bool Matches(Entry e, string name, int quality, bool matchWorld)
		{
			if ((name == null || e.Name == name) && (quality < 0 || quality == e.Quality))
			{
				if (matchWorld)
				{
					return e.WorldLevel >= Game.m_worldLevel;
				}
				return true;
			}
			return false;
		}

		public static int Count(Player player, string name, int quality, bool matchWorld)
		{
			if (!Enabled || (Object)(object)player == (Object)null)
			{
				return 0;
			}
			Refresh(player);
			return _all.Where((Entry e) => Matches(e, name, quality, matchWorld)).Sum((Entry e) => e.Stack);
		}

		public static int Take(Player player, string name, int amount, int quality, bool matchWorld)
		{
			if (!Enabled || (Object)(object)player == (Object)null || amount <= 0)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData item in ((Humanoid)player).GetInventory().m_inventory.ToList())
			{
				if (num >= amount)
				{
					break;
				}
				Pack pack = Pack.From(item);
				if (pack == null || pack.Locked)
				{
					continue;
				}
				Inventory val = PackView.LiveInventoryOf(item);
				Inventory val2 = val ?? pack.LoadInventory();
				if (pack.Unreadable)
				{
					continue;
				}
				bool flag = false;
				foreach (ItemData item2 in val2.m_inventory.ToList())
				{
					if (num >= amount)
					{
						break;
					}
					if (item2.m_shared != null && !(item2.m_shared.m_name != name) && (quality < 0 || item2.m_quality == quality) && (!matchWorld || item2.m_worldLevel >= Game.m_worldLevel))
					{
						int num2 = Mathf.Min(item2.m_stack, amount - num);
						val2.RemoveItem(item2, num2);
						num += num2;
						flag = true;
					}
				}
				if (flag)
				{
					if (val != null)
					{
						val.Changed(false, false);
					}
					else
					{
						pack.Save(val2);
					}
				}
			}
			if (num > 0)
			{
				_frame = -1;
				((Humanoid)player).GetInventory().Changed(false, false);
			}
			return num;
		}

		public static bool IsPlayersInventory(Inventory inventory)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				return inventory == ((Humanoid)Player.m_localPlayer).GetInventory();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "CountItems")]
	internal static class CountItemsPatch
	{
		private static void Postfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result)
		{
			if (PackMaterials.Enabled && !PackMaterials.Busy && name != null && PackMaterials.IsPlayersInventory(__instance))
			{
				__result += PackMaterials.Count(Player.m_localPlayer, name, quality, matchWorldLevel);
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "HaveItem", new Type[]
	{
		typeof(string),
		typeof(bool)
	})]
	internal static class HaveItemPatch
	{
		private static void Postfix(Inventory __instance, string name, bool matchWorldLevel, ref bool __result)
		{
			if (!__result && PackMaterials.Enabled && !PackMaterials.Busy && name != null && PackMaterials.IsPlayersInventory(__instance))
			{
				__result = PackMaterials.Count(Player.m_localPlayer, name, -1, matchWorldLevel) > 0;
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(int),
		typeof(bool)
	})]
	internal static class RemoveMaterialsPatch
	{
		private static void Prefix(Inventory __instance, string name, ref int amount, int itemQuality, bool worldLevelBased)
		{
			if (!PackMaterials.Enabled || PackMaterials.Busy || name == null || amount <= 0 || !PackMaterials.IsPlayersInventory(__instance))
			{
				return;
			}
			int num = 0;
			foreach (ItemData item in __instance.m_inventory)
			{
				if (item.m_shared.m_name == name && (itemQuality < 0 || item.m_quality == itemQuality) && (!worldLevelBased || item.m_worldLevel >= Game.m_worldLevel))
				{
					num += item.m_stack;
				}
			}
			if (num < amount)
			{
				int num2 = PackMaterials.Take(Player.m_localPlayer, name, amount - num, itemQuality, worldLevelBased);
				amount -= num2;
			}
		}
	}
	internal static class PackPanel
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__CloseBag;

			public static Action <1>__SaveOffset;

			public static Action <2>__CloseBag;
		}

		private const float Width = 420f;

		private const float ReadableZoom = 1.3f;

		private const float GapToContents = 6f;

		private const float RowHeight = 34f;

		private const int MaxTargetRows = 8;

		private const int MaxResults = 5;

		private const int MaxIconRows = 9;

		private static readonly string[] ExtraIcons = new string[6] { "portal_wood", "piece_chest", "piece_workbench", "forge", "piece_chest_wood", "piece_chest_private" };

		private static readonly string[] CommonIcons = new string[18]
		{
			"portal_wood", "piece_chest", "ArrowWood", "MeadHealthMinor", "MeadStaminaMinor", "CookedMeat", "Wood", "FineWood", "Stone", "Coal",
			"Copper", "Tin", "Iron", "BlackMetalScrap", "SurtlingCore", "GreydwarfEye", "LeatherScraps", "DeerHide"
		};

		private static GameObject _panel;

		private static GameObject _containerClose;

		private static InputField _nameField;

		private static InputField _searchField;

		private static string _search = "";

		private static string _typedName;

		private static bool _blocking;

		private static bool _pickingIcon;

		private static string _iconSearch = "";

		private static float _height;

		private static Vector2 _offset;

		private static RectTransform Contents
		{
			get
			{
				if (!((Object)(object)InventoryGui.instance != (Object)null))
				{
					return null;
				}
				return InventoryGui.instance.m_container;
			}
		}

		private static float Zoom
		{
			get
			{
				if (!(BagOHeimPlugin.PanelScale.Value > 0f))
				{
					return 1.3f;
				}
				return BagOHeimPlugin.PanelScale.Value;
			}
		}

		public static bool IsTyping => _blocking;

		public static void Show()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			_search = "";
			_typedName = null;
			_pickingIcon = false;
			_iconSearch = "";
			_offset = new Vector2(BagOHeimPlugin.PanelOffsetX.Value, BagOHeimPlugin.PanelOffsetY.Value);
			Rebuild();
		}

		private static void Attach()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			if ((Object)(object)_panel == (Object)null)
			{
				return;
			}
			RectTransform component = _panel.GetComponent<RectTransform>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			RectTransform contents = Contents;
			((Transform)component).localScale = Vector3.one * Zoom;
			Vector2 val = default(Vector2);
			if ((Object)(object)contents != (Object)null)
			{
				if ((Object)(object)((Transform)component).parent != (Object)(object)contents)
				{
					((Transform)component).SetParent((Transform)(object)contents, false);
				}
				((Vector2)(ref val))..ctor(1f, 1f);
				component.anchorMax = val;
				component.anchorMin = val;
				component.pivot = new Vector2(0f, 1f);
				ApplyPosition();
			}
			else
			{
				((Vector2)(ref val))..ctor(1f, 0.5f);
				component.anchorMax = val;
				component.anchorMin = val;
				component.pivot = new Vector2(1f, 0.5f);
				component.anchoredPosition = new Vector2(-30f, 0f);
			}
		}

		private static void ApplyPosition()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_panel == (Object)null))
			{
				RectTransform component = _panel.GetComponent<RectTransform>();
				if ((Object)(object)component != (Object)null && (Object)(object)((Transform)component).parent == (Object)(object)Contents)
				{
					component.anchoredPosition = new Vector2(6f, 0f) + _offset;
				}
			}
		}

		private static void SaveOffset()
		{
			BagOHeimPlugin.PanelOffsetX.Value = _offset.x;
			BagOHeimPlugin.PanelOffsetY.Value = _offset.y;
		}

		private static void EnsureAttached()
		{
			if (!((Object)(object)_panel == (Object)null))
			{
				RectTransform contents = Contents;
				RectTransform component = _panel.GetComponent<RectTransform>();
				if ((Object)(object)contents != (Object)null && (Object)(object)component != (Object)null && (Object)(object)((Transform)component).parent != (Object)(object)contents)
				{
					Attach();
				}
			}
		}

		private static void CloseBag()
		{
			if ((Object)(object)InventoryGui.instance != (Object)null && (Object)(object)InventoryGui.instance.m_currentContainer != (Object)null)
			{
				InventoryGui.instance.CloseContainer();
			}
		}

		private static void EnsureContainerClose()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			if ((Object)(object)_containerClose != (Object)null || !PackView.IsOpen || GUIManager.Instance == null)
			{
				return;
			}
			RectTransform contents = Contents;
			if (!((Object)(object)contents == (Object)null))
			{
				_containerClose = GUIManager.Instance.CreateButton("X", (Transform)(object)contents, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-34f, -26f), 48f, 34f);
				ButtonClickedEvent onClick = _containerClose.GetComponent<Button>().onClick;
				object obj = <>O.<0>__CloseBag;
				if (obj == null)
				{
					UnityAction val = CloseBag;
					<>O.<0>__CloseBag = val;
					obj = (object)val;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
			}
		}

		public static void Hide()
		{
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			if ((Object)(object)_containerClose != (Object)null)
			{
				Object.Destroy((Object)(object)_containerClose);
			}
			_panel = null;
			_containerClose = null;
			_nameField = null;
			_searchField = null;
			SetBlockInput(block: false);
		}

		public static void Refresh()
		{
			if ((Object)(object)_panel != (Object)null)
			{
				Rebuild();
			}
		}

		public static void Update()
		{
			EnsureAttached();
			EnsureContainerClose();
			SetBlockInput(((Object)(object)_nameField != (Object)null && _nameField.isFocused) || ((Object)(object)_searchField != (Object)null && _searchField.isFocused));
		}

		private static void SetBlockInput(bool block)
		{
			if (block != _blocking)
			{
				_blocking = block;
				GUIManager.BlockInput(block);
			}
		}

		private static void Rebuild()
		{
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			//IL_0493: Unknown result type (might be due to invalid IL or missing references)
			//IL_0688: Unknown result type (might be due to invalid IL or missing references)
			//IL_0697: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_064e: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			Pack pack = PackView.OpenPack;
			Inventory inventory = PackView.OpenInventory;
			if (pack == null || inventory == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				Hide();
				return;
			}
			if ((Object)(object)_nameField != (Object)null)
			{
				_typedName = _nameField.text;
			}
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			List<PackTarget> targets = pack.Targets;
			List<(string, string, int)> list = SearchResults(pack.Kind, targets);
			List<(string, string)> list2 = (_pickingIcon ? IconResults(_iconSearch) : null);
			int num = Mathf.Max(1, Mathf.Min(targets.Count, 8));
			float num2 = (_height = (_pickingIcon ? (250f + (float)(list2.Count + 1) * 34f) : (342f + (float)num * 34f + (float)(list.Count + 1) * 34f)));
			GUIManager instance = GUIManager.Instance;
			_panel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-240f, 0f), 420f, num2, false);
			Canvas obj = _panel.AddComponent<Canvas>();
			obj.overrideSorting = true;
			obj.sortingOrder = 200;
			_panel.AddComponent<GraphicRaycaster>();
			PanelDrag panelDrag = _panel.AddComponent<PanelDrag>();
			panelDrag.Target = _panel.GetComponent<RectTransform>();
			panelDrag.Moved = delegate(Vector2 delta)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				_offset += delta;
				ApplyPosition();
			};
			panelDrag.Dropped = SaveOffset;
			panelDrag.Reset = delegate
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				_offset = Vector2.zero;
				ApplyPosition();
				SaveOffset();
			};
			Attach();
			Button("X", 176f, -24f, 44f, CloseBag);
			if (_pickingIcon)
			{
				BuildIconPicker(pack, list2);
				return;
			}
			float num3 = -28f;
			Text(pack.Name, 0f, num3, 24, instance.ValheimOrange, 320f, (TextAnchor)4);
			num3 -= 38f;
			_nameField = instance.CreateInputField(_panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(-55f, num3), (ContentType)0, "Name this pack", 16, 270f, 30f).GetComponent<InputField>();
			_nameField.characterLimit = 32;
			_nameField.text = _typedName ?? pack.Name;
			Button("Rename", 140f, num3, 100f, delegate
			{
				pack.Name = _nameField.text;
				_typedName = null;
				PackView.OpenInventory.m_name = pack.Name;
				InventoryGui.instance.m_currentContainer.m_name = pack.Name;
				pack.Save(PackView.OpenInventory);
				Rebuild();
			});
			num3 -= 42f;
			Button("Remember these amounts", -95f, num3, 210f, delegate
			{
				pack.RememberContents(inventory);
				pack.Save(inventory);
				Rebuild();
			});
			Button("Refill", 120f, num3, 150f, delegate
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				BaseArea baseArea = BaseArea.For(((Component)localPlayer).transform.position);
				if (!Refill.One(localPlayer, baseArea, pack))
				{
					Refill.Message(localPlayer, baseArea.IsValid ? "Nothing to add." : "Nothing to add. Chests are only used inside your base (near a workbench).");
				}
				Rebuild();
			});
			num3 -= 46f;
			Button(pack.Locked ? "Unlock this pack" : "Lock this pack", -95f, num3, 210f, delegate
			{
				pack.Locked = !pack.Locked;
				pack.Save(inventory);
				Rebuild();
			});
			Button(pack.AutoPickup ? "Auto-pickup: ON" : "Auto-pickup: off", 120f, num3, 190f, delegate
			{
				pack.AutoPickup = !pack.AutoPickup;
				pack.Save(inventory);
				Rebuild();
			});
			num3 -= 46f;
			Button("Choose icon...", -95f, num3, 210f, delegate
			{
				_pickingIcon = true;
				_iconSearch = "";
				Rebuild();
			});
			Text(IconLabel(pack), 20f, num3, 15, Color.gray, 190f, (TextAnchor)3);
			num3 -= 46f;
			Text("Refills to:", -190f, num3, 18, instance.ValheimBeige, 200f, (TextAnchor)3);
			num3 -= 34f;
			if (targets.Count == 0)
			{
				Text("Nothing yet: fill the pack and click Remember, or add items below.", 0f, num3, 14, Color.gray, 380f, (TextAnchor)4);
				num3 -= 34f;
			}
			foreach (PackTarget item4 in targets.Take(8))
			{
				SharedData shared = Refill.SharedOf(item4.Prefab);
				string text = ((shared != null) ? Refill.Name(shared) : item4.Prefab);
				int num4 = Pack.Count(inventory, item4.Prefab);
				string text2 = ((num4 >= item4.Amount) ? "#9ccc65" : "#ffb74d");
				Text($"{text}  <color={text2}>{num4}/{item4.Amount}</color>", -190f, num3, 16, Color.white, 230f, (TextAnchor)3);
				PackTarget t = item4;
				Button("-", 105f, num3, 34f, delegate
				{
					Adjust(pack, t.Prefab, -Step(shared));
				});
				Button("+", 143f, num3, 34f, delegate
				{
					Adjust(pack, t.Prefab, Step(shared));
				});
				Button("x", 181f, num3, 34f, delegate
				{
					Adjust(pack, t.Prefab, -1073741823);
				});
				num3 -= 34f;
			}
			if (targets.Count > 8)
			{
				Text($"+{targets.Count - 8} more", 0f, num3, 14, Color.gray, 380f, (TextAnchor)4);
				num3 -= 34f;
			}
			num3 -= 10f;
			_searchField = instance.CreateInputField(_panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, num3), (ContentType)0, "Add an item: type part of a name, press Enter", 16, 370f, 30f).GetComponent<InputField>();
			_searchField.text = _search;
			((UnityEvent<string>)(object)_searchField.onEndEdit).AddListener((UnityAction<string>)delegate(string search)
			{
				_search = search;
				Rebuild();
			});
			num3 -= 38f;
			foreach (var item5 in list)
			{
				string item = item5.Item1;
				string item2 = item5.Item2;
				int item3 = item5.Item3;
				string p = item;
				int s = item3;
				Button("+ " + item2, 0f, num3, 370f, delegate
				{
					Adjust(pack, p, s);
					_search = "";
					Rebuild();
				});
				num3 -= 34f;
			}
		}

		private static string IconLabel(Pack pack)
		{
			string text = DisplayName(pack.ShownIconPrefab);
			if (pack.IconPrefab == null)
			{
				return "Icon: " + text + " (default)";
			}
			return "Icon: " + text;
		}

		private static string DisplayName(string prefab)
		{
			SharedData val = Refill.SharedOf(prefab);
			if (val != null)
			{
				return Refill.Name(val);
			}
			GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			Piece val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Piece>() : null);
			if (!((Object)(object)val3 != (Object)null))
			{
				return prefab;
			}
			return Localization.instance.Localize(val3.m_name);
		}

		private static List<(string prefab, string label)> IconResults(string query)
		{
			List<(string, string)> list = new List<(string, string)>();
			query = (query ?? "").Trim();
			string[] commonIcons;
			if (query.Length < 2)
			{
				commonIcons = CommonIcons;
				foreach (string text in commonIcons)
				{
					if (!((Object)(object)PackIcons.GameSprite(text) == (Object)null))
					{
						list.Add((text, DisplayName(text)));
						if (list.Count >= 9)
						{
							break;
						}
					}
				}
				return list;
			}
			commonIcons = ExtraIcons;
			foreach (string text2 in commonIcons)
			{
				string text3 = DisplayName(text2);
				if (text3.IndexOf(query, StringComparison.CurrentCultureIgnoreCase) >= 0 && !((Object)(object)PackIcons.GameSprite(text2) == (Object)null))
				{
					list.Add((text2, text3));
				}
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				foreach (GameObject go in ObjectDB.instance.m_items)
				{
					if (list.Count >= 9)
					{
						break;
					}
					ItemDrop val = (((Object)(object)go != (Object)null) ? go.GetComponent<ItemDrop>() : null);
					if (!((Object)(object)val == (Object)null) && val.m_itemData.m_shared.m_icons != null && val.m_itemData.m_shared.m_icons.Length != 0 && !((Object)go).name.StartsWith("BOH_") && !list.Any(((string, string) r) => r.Item1 == ((Object)go).name))
					{
						string text4 = Refill.Name(val.m_itemData.m_shared);
						if (text4.IndexOf(query, StringComparison.CurrentCultureIgnoreCase) >= 0)
						{
							list.Add((((Object)go).name, text4));
						}
					}
				}
			}
			return list;
		}

		private static void BuildIconPicker(Pack pack, List<(string prefab, string label)> icons)
		{
			//IL_0037: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.Instance;
			float num = -28f;
			Text("Choose an icon for " + pack.Name, 0f, num, 20, instance.ValheimOrange, 320f, (TextAnchor)4);
			num -= 42f;
			_searchField = instance.CreateInputField(_panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, num), (ContentType)0, "Search by name, press Enter", 16, 370f, 30f).GetComponent<InputField>();
			_searchField.text = _iconSearch;
			((UnityEvent<string>)(object)_searchField.onEndEdit).AddListener((UnityAction<string>)delegate(string text)
			{
				_iconSearch = text;
				Rebuild();
			});
			num -= 40f;
			if (icons.Count == 0)
			{
				Text("Nothing matches that.", 0f, num, 16, Color.gray, 380f, (TextAnchor)4);
				num -= 34f;
			}
			foreach (var icon in icons)
			{
				string item = icon.prefab;
				string item2 = icon.label;
				string chosen = item;
				Sprite val = PackIcons.GameSprite(item);
				if ((Object)(object)val != (Object)null)
				{
					IconImage(val, -172f, num, 28f);
				}
				Button(item2, 28f, num, 308f, delegate
				{
					pack.IconPrefab = chosen;
					pack.Save(PackView.OpenInventory);
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						((Humanoid)localPlayer).GetInventory().Changed(false, false);
					}
					_pickingIcon = false;
					Rebuild();
				});
				num -= 34f;
			}
			num -= 8f;
			Button("Use the default icon", -95f, num, 210f, delegate
			{
				pack.IconPrefab = null;
				pack.Save(PackView.OpenInventory);
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Humanoid)localPlayer).GetInventory().Changed(false, false);
				}
				_pickingIcon = false;
				Rebuild();
			});
			Button("Back", 120f, num, 150f, delegate
			{
				_pickingIcon = false;
				Rebuild();
			});
		}

		private static void IconImage(Sprite sprite, float x, float y, float size)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("BagOHeim_IconRow", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(_panel.transform, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.sizeDelta = new Vector2(size, size);
			val2.anchoredPosition = new Vector2(x, y);
			Image component = val.GetComponent<Image>();
			component.sprite = sprite;
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = false;
		}

		private static int Step(SharedData shared)
		{
			int num = ((shared == null || shared.m_maxStackSize < 50) ? 1 : 10);
			if (!Input.GetKey((KeyCode)304) && !Input.GetKey((KeyCode)303))
			{
				return num;
			}
			return num * 10;
		}

		private static void Adjust(Pack pack, string prefab, int delta)
		{
			List<PackTarget> targets = pack.Targets;
			PackTarget packTarget = targets.FirstOrDefault((PackTarget t) => t.Prefab == prefab);
			if (packTarget == null)
			{
				PackTarget obj = new PackTarget
				{
					Prefab = prefab,
					Amount = 0
				};
				packTarget = obj;
				targets.Add(obj);
			}
			packTarget.Amount = Mathf.Max(0, packTarget.Amount + delta);
			pack.Targets = targets;
			pack.Save(PackView.OpenInventory);
			Rebuild();
		}

		private static List<(string prefab, string label, int step)> SearchResults(PackKind kind, List<PackTarget> targets)
		{
			List<(string, string, int)> list = new List<(string, string, int)>();
			string text = (_search ?? "").Trim();
			if (text.Length < 2 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return list;
			}
			HashSet<string> hashSet = new HashSet<string>(targets.Select((PackTarget t) => t.Prefab));
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				ItemDrop val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null || hashSet.Contains(((Object)item).name))
				{
					continue;
				}
				ItemData itemData = val.m_itemData;
				if (itemData.m_shared.m_icons == null || itemData.m_shared.m_icons.Length == 0)
				{
					continue;
				}
				itemData.m_dropPrefab = item;
				if (!PackKinds.Accepts(kind, itemData))
				{
					continue;
				}
				string text2 = Refill.Name(itemData.m_shared);
				if (text2.IndexOf(text, StringComparison.CurrentCultureIgnoreCase) >= 0)
				{
					list.Add((((Object)item).name, text2, Mathf.Min(itemData.m_shared.m_maxStackSize, 10)));
					if (list.Count >= 5)
					{
						break;
					}
				}
			}
			return list;
		}

		private static void Text(string text, float x, float y, int size, Color color, float width, TextAnchor anchor)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			Text component = GUIManager.Instance.CreateText(text, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(x + (((int)anchor == 3) ? (width / 2f) : 0f), y), GUIManager.Instance.AveriaSerifBold, size, color, true, Color.black, width, 32f, false).GetComponent<Text>();
			component.alignment = anchor;
			component.supportRichText = true;
		}

		private static void Button(string label, float x, float y, float width, Action onClick)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			((UnityEvent)GUIManager.Instance.CreateButton(label, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(x, y), width, 30f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				onClick();
			});
		}
	}
	internal static class PackView
	{
		private static GameObject _host;

		private static Container _container;

		private static Pack _pack;

		private static Inventory _inventory;

		public static Pack OpenPack
		{
			get
			{
				if (!IsOpen)
				{
					return null;
				}
				return _pack;
			}
		}

		public static Pack RegisteredPack => _pack;

		public static Inventory OpenInventory
		{
			get
			{
				if (!IsOpen)
				{
					return null;
				}
				return _inventory;
			}
		}

		public static bool IsOpen
		{
			get
			{
				if (_pack != null && (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible())
				{
					return (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)_container;
				}
				return false;
			}
		}

		public static bool IsPackContainer(Container c)
		{
			if ((Object)(object)c != (Object)null)
			{
				return (Object)(object)c == (Object)(object)_container;
			}
			return false;
		}

		public static bool IsPackInventory(Inventory inventory)
		{
			if (inventory != null)
			{
				return inventory == _inventory;
			}
			return false;
		}

		public static Inventory LiveInventoryOf(ItemData packItem)
		{
			if (!IsOpen || _pack.Item != packItem)
			{
				return null;
			}
			return _inventory;
		}

		public static void Open(Player player, Pack pack)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null)
			{
				return;
			}
			if ((Object)(object)instance.m_currentContainer != (Object)null)
			{
				instance.CloseContainer();
			}
			Finish();
			Inventory inventory = pack.LoadInventory();
			if (pack.Unreadable)
			{
				((Character)player).Message((MessageType)2, "'" + pack.Name + "' couldn't be read, so it was left untouched.", 0, (Sprite)null, false);
				return;
			}
			if ((Object)(object)_host == (Object)null || (Object)(object)_host.transform.parent != (Object)(object)((Component)player).transform)
			{
				if ((Object)(object)_host != (Object)null)
				{
					Object.Destroy((Object)(object)_host);
				}
				_host = new GameObject("BagOHeim_PackView");
				_host.SetActive(false);
				_host.transform.SetParent(((Component)player).transform, false);
				_container = _host.AddComponent<Container>();
			}
			_pack = pack;
			_inventory = inventory;
			Inventory inventory2 = _inventory;
			inventory2.m_onChanged = (Action)Delegate.Combine(inventory2.m_onChanged, new Action(OnChanged));
			_container.m_name = pack.Name;
			_container.m_width = _inventory.GetWidth();
			_container.m_height = _inventory.GetHeight();
			_container.m_inventory = _inventory;
			_container.m_nview = ((Character)player).m_nview;
			instance.Show(_container, 1);
			instance.m_waitForContainerStack = false;
			PackPanel.Show();
		}

		public static void Update()
		{
			if (_pack != null)
			{
				Player localPlayer = Player.m_localPlayer;
				bool flag = (Object)(object)localPlayer != (Object)null && ((Humanoid)localPlayer).GetInventory().m_inventory.Contains(_pack.Item);
				if (IsOpen && !flag)
				{
					InventoryGui.instance.CloseContainer();
				}
				if (!IsOpen)
				{
					Finish();
				}
			}
		}

		private static void OnChanged()
		{
			if (_pack != null)
			{
				_pack.Save(_inventory);
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Humanoid)localPlayer).GetInventory().Changed(false, false);
				}
				PackPanel.Refresh();
			}
		}

		private static void Finish()
		{
			if (_pack != null)
			{
				_pack.Save(_inventory);
				Inventory inventory = _inventory;
				inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnChanged));
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Humanoid)localPlayer).GetInventory().Changed(false, false);
				}
				_pack = null;
				_inventory = null;
				PackPanel.Hide();
			}
		}
	}
	internal class PanelDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler, IPointerClickHandler
	{
		public RectTransform Target;

		public Action<Vector2> Moved;

		public Action Dropped;

		public Action Reset;

		public void OnBeginDrag(PointerEventData eventData)
		{
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Target == (Object)null) && !((Object)(object)((Transform)Target).parent == (Object)null))
			{
				float num = Mathf.Max(0.0001f, ((Transform)Target).parent.lossyScale.x);
				Moved?.Invoke(eventData.delta / num);
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			Dropped?.Invoke();
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			if (eventData.clickCount >= 2)
			{
				Reset?.Invoke();
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	internal static class UseItemPatch
	{
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item)
		{
			if (!PackKinds.IsPack(item))
			{
				return true;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (inventory != null && inventory != ((Humanoid)val).GetInventory())
			{
				return true;
			}
			if (PackView.LiveInventoryOf(item) != null)
			{
				InventoryGui.instance.CloseContainer();
			}
			else
			{
				PackView.Open(val, new Pack(item));
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class PackAcceptsPatch
	{
		private static float _lastMessage;

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Inventory), "AddItem", new Type[1] { typeof(ItemData) }, (Type[])null);
			yield return AccessTools.Method(typeof(Inventory), "AddItem", new Type[5]
			{
				typeof(ItemData),
				typeof(int),
				typeof(int),
				typeof(int),
				typeof(bool)
			}, (Type[])null);
			yield return AccessTools.Method(typeof(Inventory), "AddItem", new Type[2]
			{
				typeof(ItemData),
				typeof(Vector2i)
			}, (Type[])null);
		}

		private static bool Prefix(Inventory __instance, ItemData item, ref bool __result)
		{
			if (!PackView.IsPackInventory(__instance))
			{
				return true;
			}
			Pack registeredPack = PackView.RegisteredPack;
			if (registeredPack == null || PackKinds.Accepts(registeredPack.Kind, item))
			{
				return true;
			}
			NotifyRefused(registeredPack.Kind);
			__result = false;
			return false;
		}

		internal static void NotifyRefused(PackKind kind)
		{
			if (!(Time.time - _lastMessage < 1f) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				_lastMessage = Time.time;
				((Character)Player.m_localPlayer).Message((MessageType)2, PackKinds.RefusalMessage(kind), 0, (Sprite)null, false);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
	internal static class PackDropGuardPatch
	{
		private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, Vector2i pos, ref bool __result)
		{
			//IL_0049: 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)
			Pack registeredPack = PackView.RegisteredPack;
			if (registeredPack == null)
			{
				return true;
			}
			Inventory inventory = __instance.m_inventory;
			bool flag = PackView.IsPackInventory(inventory);
			bool flag2 = PackView.IsPackInventory(fromInventory);
			if (!flag && !flag2)
			{
				return true;
			}
			bool flag3 = flag && !PackKinds.Accepts(registeredPack.Kind, item);
			if (!flag3 && flag2)
			{
				ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
				flag3 = itemAt != null && itemAt != item && !PackKinds.Accepts(registeredPack.Kind, itemAt);
			}
			if (!flag3)
			{
				return true;
			}
			PackAcceptsPatch.NotifyRefused(registeredPack.Kind);
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Container), "StackAll")]
	internal static class PackStackAllPatch
	{
		private static bool Prefix(Container __instance)
		{
			return !PackView.IsPackContainer(__instance);
		}
	}
	[HarmonyPatch(typeof(Container), "SetInUse")]
	internal static class PackSetInUsePatch
	{
		private static bool Prefix(Container __instance)
		{
			return !PackView.IsPackContainer(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetWeight")]
	internal static class PackWeightPatch
	{
		private static void