Decompiled source of OpenKeep v5.2.0

plugins\OpenKeep.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using AreaLoading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BlueprintShelf;
using BundlePrefabs;
using Charter;
using ConfigReload;
using EliteCraftingLink;
using GUIFramework;
using HarmonyLib;
using Hotkeys;
using ItemCopies;
using MapClicks;
using Microsoft.CodeAnalysis;
using OpenKeep.Batch;
using OpenKeep.Blueprints;
using OpenKeep.Blueprints.Bench;
using OpenKeep.Blueprints.Copy;
using OpenKeep.Blueprints.Planner;
using OpenKeep.Blueprints.Sites;
using OpenKeep.Blueprints.Tab;
using OpenKeep.BuildCamera;
using OpenKeep.Capacity;
using OpenKeep.Carts;
using OpenKeep.Core;
using OpenKeep.Homestead;
using OpenKeep.Mimir;
using OpenKeep.Reach;
using OpenKeep.Recipes;
using OpenKeep.Salvage;
using OpenKeep.Shared;
using OpenKeep.Signs;
using OpenKeep.Stacks;
using OpenKeep.Store;
using OpenKeep.Tracker;
using PatchGuard;
using PlateColumn;
using Splatform;
using SyncedConfig;
using TMPro;
using Translations;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;
using WindowInput;
using YamlConfig;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("OpenKeep")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("OpenKeep: storage and inventory for Valheim")]
[assembly: AssemblyFileVersion("5.2.0.0")]
[assembly: AssemblyInformationalVersion("5.2.0+41299e456a94991837b85ab4893af7d9fdb6c6b4")]
[assembly: AssemblyProduct("OpenKeep")]
[assembly: AssemblyTitle("OpenKeep")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("5.2.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 OpenKeep
{
	[HarmonyPatch(typeof(Player), "Update")]
	public static class PlayerUpdatePatch
	{
		[HarmonyPostfix]
		public static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				CameraToggle.Tick(__instance);
				TorchKeyPatch.Tick(__instance);
				ReachKeys.Tick(__instance);
				DumpKeyPatch.Tick(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	public static class InventoryUpdatePatch
	{
		[HarmonyPostfix]
		public static void Postfix(InventoryGui __instance)
		{
			RecipeInput.Poll(__instance);
			SalvageHotkey.Tick(__instance);
			StoreHotkeys.Tick(__instance);
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
	public static class UpdateRecipePatch
	{
		[HarmonyPostfix]
		public static void Postfix(InventoryGui __instance, Player player)
		{
			BatchStepper.Refresh(__instance, player);
			RecipeActions.Refresh(__instance);
		}
	}
	[HarmonyPatch(typeof(Container), "CheckForChanges")]
	public static class ContainerTickPatch
	{
		[HarmonyPrefix]
		public static void Prefix(Container __instance, out uint __state)
		{
			__state = __instance.m_lastRevision;
		}

		[HarmonyPostfix]
		public static void Postfix(Container __instance, uint __state)
		{
			SignRefresh.Tick(__instance, force: false);
			TidySchedule.Tick(__instance, __state);
		}
	}
	[BepInPlugin("milkyteam.openkeep", "OpenKeep", "5.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "milkyteam.openkeep";

		public const string PluginName = "OpenKeep";

		public const string PluginVersion = "5.2.0";

		public static ManualLogSource Log { get; private set; }

		public static SyncedConfiguration Synced { get; private set; }

		public static ConfigEntry<bool> LockConfiguration { get; private set; }

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Synced = new SyncedConfiguration((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, "OpenKeep", "5.2.0");
			LockConfiguration = Synced.BindLocking("General", "Lock Configuration", defaultValue: true, "[Server Only] Clients cannot change synced settings while connected to a server that has this on.");
			Harmony harmony = new Harmony("milkyteam.openkeep");
			Lang.Install(harmony, Assembly.GetExecutingAssembly(), "OpenKeep", ((BaseUnityPlugin)this).Logger);
			InitializeModules();
			int num = PatchEverything(harmony);
			StacksModule.HookSpawns(harmony);
			AreaLoader.Install(harmony, delegate(string text)
			{
				Log.LogInfo((object)("OpenKeep: " + text));
			});
			IconClick.Install(harmony);
			Synced.Finish(harmony);
			Log.LogInfo((object)("Loading [OpenKeep 5.2.0]" + ((num > 0) ? $" with {num} failed patches, see above" : "")));
			Guard.Install(harmony, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly());
		}

		private static void InitializeModules()
		{
			CoreModule.Initialize(Synced);
			ReachModule.Initialize(Synced);
			StoreModule.Initialize(Synced);
			SalvageModule.Initialize(Synced);
			StacksModule.Initialize(Synced);
			CapacityModule.Initialize(Synced);
			CartsModule.Initialize(Synced);
			SignsModule.Initialize(Synced);
			HomesteadModule.Initialize(Synced);
			SharedModule.Initialize(Synced);
			BatchModule.Initialize(Synced);
			CameraModule.Initialize(Synced);
			RecipeListModule.Initialize(Synced);
			TrackerModule.Initialize(Synced);
			BlueprintsModule.Initialize(Synced);
			MimirModule.Initialize(Synced);
		}

		private void Start()
		{
			EpicLootLink.Register();
		}

		private static int PatchEverything(Harmony harmony)
		{
			int num = 0;
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
			foreach (Type type in typesFromAssembly)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0)
				{
					try
					{
						harmony.CreateClassProcessor(type).Patch();
					}
					catch (Exception ex)
					{
						num++;
						Log.LogError((object)("Patch " + type.FullName + " failed to apply: " + ex.Message));
					}
				}
			}
			return num;
		}
	}
}
namespace OpenKeep.Tracker
{
	public sealed class CraftWatch
	{
		private Recipe recipe;

		private int quality;

		private int crafts;

		private int before;

		public static CraftWatch Start(InventoryGui gui, Player player)
		{
			Recipe craftRecipe = gui.m_craftRecipe;
			if ((Object)(object)craftRecipe == (Object)null || (Object)(object)player == (Object)null || (Object)(object)craftRecipe.m_item == (Object)null || !TrackerSettings.Enabled.Value)
			{
				return null;
			}
			int num = ((gui.m_craftUpgradeItem == null) ? 1 : (gui.m_craftUpgradeItem.m_quality + 1));
			if (!TrackerList.IsTracked(craftRecipe, num))
			{
				return null;
			}
			int num2 = ((gui.m_craftUpgradeItem != null || !gui.m_multiCrafting) ? 1 : gui.m_multiCraftAmount);
			return new CraftWatch
			{
				recipe = craftRecipe,
				quality = num,
				crafts = num2,
				before = Held(player, craftRecipe, num)
			};
		}

		public void Finish(Player player)
		{
			if ((Object)(object)player != (Object)null && Held(player, recipe, quality) > before)
			{
				TrackerList.Crafted(recipe, quality, crafts);
			}
		}

		private static int Held(Player player, Recipe recipe, int quality)
		{
			return ((Humanoid)player).GetInventory().CountItems(recipe.m_item.m_itemData.m_shared.m_name, quality, false);
		}
	}
	public sealed class TrackedRecipe
	{
		public const int MaxAmount = 9999;

		private const string UpgraderMark = "u";

		public string Key { get; }

		public int Quality { get; }

		public bool Upgrader { get; }

		public int Amount { get; set; }

		public Recipe Recipe => RecipeKeys.Find(Key);

		public TrackedRecipe(string key, int quality, int amount, bool upgrader)
		{
			Key = key;
			Quality = ((quality < 1) ? 1 : quality);
			Amount = ((amount < 1) ? 1 : ((amount > 9999) ? 9999 : amount));
			Upgrader = upgrader;
		}

		public bool Is(string key, int quality, bool upgrader)
		{
			if (quality == Quality && upgrader == Upgrader)
			{
				return key == Key;
			}
			return false;
		}

		public override string ToString()
		{
			return Key + "|" + Quality + "|" + Amount + (Upgrader ? "|u" : "");
		}

		public static TrackedRecipe Parse(string text)
		{
			string[] array = (text ?? "").Split(new char[1] { '|' });
			if (array.Length < 3 || array.Length > 4 || array[0].Length == 0)
			{
				return null;
			}
			if (!int.TryParse(array[1], out var result) || !int.TryParse(array[2], out var result2))
			{
				return null;
			}
			return new TrackedRecipe(array[0], result, result2, array.Length == 4 && array[3] == "u");
		}
	}
	public static class TrackerCounts
	{
		public static int Need(Requirement requirement, int quality, int amount)
		{
			return requirement.GetAmount(quality) * amount;
		}

		public static int Have(Player player, Requirement requirement, int quality)
		{
			string name = requirement.m_resItem.m_itemData.m_shared.m_name;
			int num = ((Humanoid)player).GetInventory().CountItems(name, -1, true);
			if (!TrackerSettings.CountNearbyChests.Value || !ReachRules.Active(ReachRules.FromQuality(quality)))
			{
				return num;
			}
			return num + ReachCount.InContainers(name, -1, worldLevel: true);
		}

		public static bool Shows(Requirement requirement, TrackedRecipe tracked)
		{
			return RecipeNeeds.Counts(requirement, tracked.Quality, tracked.Upgrader);
		}
	}
	public class TrackerDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		public RectTransform Target;

		private Vector2 last;

		public void OnBeginDrag(PointerEventData data)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Target == (Object)null || !Local(data, out last))
			{
				last = Vector2.zero;
			}
		}

		public void OnDrag(PointerEventData data)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			if (!((Object)(object)Target == (Object)null) && Local(data, out var point))
			{
				RectTransform target = Target;
				target.anchoredPosition += point - last;
				last = point;
				Clamp(Target);
			}
		}

		public void OnEndDrag(PointerEventData data)
		{
			//IL_0020: 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_0035: 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)
			if (!((Object)(object)Target == (Object)null))
			{
				Clamp(Target);
				Vector2 anchoredPosition = Target.anchoredPosition;
				TrackerSettings.Position.Value = string.Format(CultureInfo.InvariantCulture, "{0:0},{1:0}", anchoredPosition.x, 0f - anchoredPosition.y);
			}
		}

		private bool Local(PointerEventData data, out Vector2 point)
		{
			//IL_000b: 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_0022: Expected O, but got Unknown
			return RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)((Transform)Target).parent, data.position, data.pressEventCamera, ref point);
		}

		public static void Clamp(RectTransform target)
		{
			//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)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0030: 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_004d: 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_0076: 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)
			Rect rect = ((RectTransform)((Transform)target).parent).rect;
			Rect rect2 = target.rect;
			Vector2 val = Vector2.Scale(((Rect)(ref rect2)).size, Vector2.op_Implicit(((Transform)target).localScale));
			float num = Mathf.Clamp(target.anchoredPosition.x, 0f, Mathf.Max(0f, ((Rect)(ref rect)).width - val.x));
			float num2 = Mathf.Clamp(target.anchoredPosition.y, 0f - Mathf.Max(0f, ((Rect)(ref rect)).height - val.y), 0f);
			target.anchoredPosition = new Vector2(num, num2);
		}

		public static bool Saved(out Vector2 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			position = Vector2.zero;
			string[] array = (TrackerSettings.Position.Value ?? "").Split(new char[1] { ',' });
			if (array.Length != 2)
			{
				return false;
			}
			NumberStyles style = NumberStyles.Float;
			if (!float.TryParse(array[0].Trim(), style, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1].Trim(), style, CultureInfo.InvariantCulture, out var result2))
			{
				return false;
			}
			position = new Vector2(result, result2);
			return true;
		}
	}
	public sealed class TrackerEntry
	{
		private const float Gap = 3f;

		private readonly TrackedRecipe tracked;

		private readonly Recipe recipe;

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

		private readonly List<TMP_Text> labels = new List<TMP_Text>();

		private readonly List<TMP_Text> counts = new List<TMP_Text>();

		private readonly List<TMP_Text> notes = new List<TMP_Text>();

		private readonly List<GameObject> controls = new List<GameObject>();

		private TMP_Text name;

		private TMP_Text amount;

		private static bool Shift
		{
			get
			{
				if (!Input.GetKey((KeyCode)304))
				{
					return Input.GetKey((KeyCode)303);
				}
				return true;
			}
		}

		private TrackerEntry(TrackedRecipe tracked, Recipe recipe)
		{
			this.tracked = tracked;
			this.recipe = recipe;
		}

		public static TrackerEntry Build(Transform parent, TrackedRecipe tracked, Recipe recipe, int index)
		{
			TrackerEntry trackerEntry = new TrackerEntry(tracked, recipe);
			RectTransform val = TrackerUi.Node("OpenKeep_TrackerEntry", parent);
			TrackerUi.Column(((Component)val).gameObject, 1f);
			trackerEntry.Header((Transform)(object)val, index);
			trackerEntry.Notes((Transform)(object)val);
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement requirement in resources)
			{
				if (TrackerCounts.Shows(requirement, tracked))
				{
					trackerEntry.Material((Transform)(object)val, requirement);
				}
			}
			return trackerEntry;
		}

		private void Header(Transform root, int index)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			float size = TrackerStyle.Size;
			HorizontalLayoutGroup val = TrackerUi.Row(root, "header", 3f);
			((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Color.clear;
			((Component)val).gameObject.AddComponent<TrackerWheel>().Index = index;
			Control(TrackerUi.TextButton(((Component)val).transform, "remove", "X", size * 0.85f, delegate
			{
				TrackerList.Remove(index);
			}));
			TrackerUi.Icon(((Component)val).transform, recipe.m_item.m_itemData.GetIcon(), size * 1.6f);
			name = TrackerUi.Text(((Component)val).transform, "name", size, (TextAlignmentOptions)4097);
			name.text = TrackerList.DisplayName(recipe, tracked.Quality);
			TrackerUi.Flexible(name, size * 11f);
			Amount(((Component)val).transform, index);
		}

		private void Amount(Transform row, int index)
		{
			float size = TrackerStyle.Size;
			Control(TrackerUi.TextButton(row, "less", "-", size, delegate
			{
				TrackerList.Step(index, -1, Shift);
			}));
			amount = TrackerUi.Text(row, "amount", size, (TextAlignmentOptions)514);
			amount.text = "x" + tracked.Amount;
			TrackerUi.Short(amount, size * 1.6f);
			Control(TrackerUi.TextButton(row, "more", "+", size, delegate
			{
				TrackerList.Step(index, 1, Shift);
			}));
		}

		private void Control(Button button)
		{
			controls.Add(((Component)button).gameObject);
		}

		private void Notes(Transform root)
		{
			CraftingStation requiredStation = recipe.GetRequiredStation(tracked.Quality);
			if ((Object)(object)requiredStation != (Object)null)
			{
				Note(root, Lang.Format("$ok_tracker_station", Localization.instance.Localize(requiredStation.m_name), recipe.GetRequiredStationLevel(tracked.Quality)));
			}
			if (recipe.m_requireOnlyOneIngredient)
			{
				Note(root, Lang.Get("$ok_tracker_anyone"));
			}
		}

		private void Note(Transform root, string text)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text val = TrackerUi.Text(root, "note", TrackerStyle.Size * 0.8f, (TextAlignmentOptions)4097);
			val.text = text;
			((Graphic)val).color = TrackerStyle.Dim;
			notes.Add(val);
		}

		private void Material(Transform root, Requirement requirement)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			float size = TrackerStyle.Size;
			HorizontalLayoutGroup obj = TrackerUi.Row(root, "material", 6f);
			((LayoutGroup)obj).padding = new RectOffset(Mathf.RoundToInt(size * 0.4f), 0, 0, 0);
			TrackerUi.Icon(((Component)obj).transform, requirement.m_resItem.m_itemData.GetIcon(), size * 1.25f);
			TMP_Text val = TrackerUi.Text(((Component)obj).transform, "name", size * 0.9f, (TextAlignmentOptions)4097);
			val.text = Localization.instance.Localize(requirement.m_resItem.m_itemData.m_shared.m_name);
			TrackerUi.Flexible(val, size * 9f);
			TMP_Text val2 = TrackerUi.Text(((Component)obj).transform, "count", size * 0.9f, (TextAlignmentOptions)4100);
			TrackerUi.Short(val2, size * 3f);
			materials.Add(requirement);
			labels.Add(val);
			counts.Add(val2);
		}

		public void ShowControls(bool open)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject control in controls)
			{
				control.SetActive(open);
			}
			((Component)amount).gameObject.SetActive(open || tracked.Amount > 1);
			float size = TrackerStyle.Size;
			float num = size * 1.6f + 3f + (open ? (size * 0.85f + 3f) : 0f);
			foreach (TMP_Text note in notes)
			{
				note.margin = new Vector4(num, 0f, 0f, 0f);
			}
		}

		public void Count(Player player)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			bool flag = true;
			bool flag2 = false;
			for (int i = 0; i < materials.Count; i++)
			{
				int num = TrackerCounts.Have(player, materials[i], tracked.Quality);
				int num2 = TrackerCounts.Need(materials[i], tracked.Quality, tracked.Amount);
				bool flag3 = num >= num2;
				Paint(i, num + "/" + num2, flag3 ? TrackerStyle.Have : TrackerStyle.Missing);
				flag = flag && flag3;
				flag2 = flag2 || flag3;
			}
			bool flag4 = (recipe.m_requireOnlyOneIngredient ? flag2 : flag);
			((Graphic)name).color = (flag4 ? TrackerStyle.Ready : TrackerStyle.Have);
		}

		private void Paint(int row, string text, Color colour)
		{
			//IL_0037: 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 (counts[row].text != text)
			{
				counts[row].text = text;
			}
			((Graphic)counts[row]).color = colour;
			((Graphic)labels[row]).color = colour;
		}
	}
	public enum TrackerFont
	{
		Sans,
		Serif,
		Norse
	}
	public class TrackerHud : MonoBehaviour
	{
		private const float CountSeconds = 0.5f;

		private TrackerPanel panel;

		private int builtVersion = -1;

		private string builtStyle = "";

		private string placedAt;

		private float nextCount;

		private void Update()
		{
			bool flag = TrackerVisibility.Show();
			if (panel == null && flag && (Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_rootObject != (Object)null)
			{
				panel = TrackerPanel.Create(Hud.instance.m_rootObject.transform);
			}
			if (panel == null)
			{
				return;
			}
			panel.SetVisible(flag);
			if (!flag)
			{
				return;
			}
			panel.Interactive(TrackerVisibility.CursorFree);
			if (builtVersion != TrackerList.Version)
			{
				Rebuild();
				nextCount = 0f;
			}
			Follow();
			if (!(Time.unscaledTime < nextCount))
			{
				nextCount = Time.unscaledTime + 0.5f;
				if (builtStyle != TrackerStyle.Signature)
				{
					Rebuild();
				}
				panel.Count(Player.m_localPlayer);
			}
		}

		private void Follow()
		{
			string value = TrackerSettings.Position.Value;
			if (!(value == placedAt))
			{
				placedAt = value;
				panel.Place();
			}
		}

		private void Rebuild()
		{
			builtVersion = TrackerList.Version;
			builtStyle = TrackerStyle.Signature;
			panel.Rebuild();
			panel.KeepOnScreen();
		}
	}
	public static class TrackerList
	{
		private const string DataKey = "trackedRecipes";

		private static List<TrackedRecipe> entries;

		private static Player loadedFor;

		public static int Version { get; private set; }

		public static List<TrackedRecipe> Entries
		{
			get
			{
				Player localPlayer = Player.m_localPlayer;
				if (entries == null || (Object)(object)loadedFor != (Object)(object)localPlayer)
				{
					Load(localPlayer);
				}
				return entries;
			}
		}

		public static bool IsTracked(Recipe recipe, int quality)
		{
			return IndexOf(recipe, quality) >= 0;
		}

		public static int IndexOf(Recipe recipe, int quality)
		{
			if ((Object)(object)recipe == (Object)null)
			{
				return -1;
			}
			string key = RecipeKeys.Of(recipe);
			bool atUpgrader = RecipeNeeds.AtUpgrader;
			List<TrackedRecipe> list = Entries;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].Is(key, quality, atUpgrader))
				{
					return i;
				}
			}
			return -1;
		}

		public static void Toggle(Recipe recipe, int quality)
		{
			if (TrackerSettings.Enabled.Value && !((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				int num = IndexOf(recipe, quality);
				if (num >= 0)
				{
					Remove(num);
					return;
				}
				if (Entries.Count >= TrackerSettings.MaxTracked.Value)
				{
					Messages.Center(Lang.Format("$ok_tracker_full", TrackerSettings.MaxTracked.Value));
					return;
				}
				Entries.Add(new TrackedRecipe(RecipeKeys.Of(recipe), quality, StartAmount(recipe, quality), RecipeNeeds.AtUpgrader));
				Save();
				Messages.Center(Lang.Format("$ok_tracker_tracking", DisplayName(recipe, quality)));
			}
		}

		public static void Remove(int index)
		{
			if (index >= 0 && index < Entries.Count)
			{
				TrackedRecipe trackedRecipe = Entries[index];
				Entries.RemoveAt(index);
				Save();
				Recipe recipe = trackedRecipe.Recipe;
				if ((Object)(object)recipe != (Object)null)
				{
					Messages.Center(Lang.Format("$ok_tracker_untracked", DisplayName(recipe, trackedRecipe.Quality)));
				}
			}
		}

		public static void Step(int index, int direction, bool tens)
		{
			if (index >= 0 && index < Entries.Count)
			{
				int amount = Entries[index].Amount;
				int num = ((!tens) ? (amount + direction) : ((direction > 0) ? ((amount / 10 + 1) * 10) : ((amount - 1) / 10 * 10)));
				Entries[index].Amount = Mathf.Clamp(num, 1, 9999);
				Save();
			}
		}

		public static void Crafted(Recipe recipe, int quality, int crafts)
		{
			int num = IndexOf(recipe, quality);
			if (num >= 0 && TrackerSettings.UntrackWhenCrafted.Value)
			{
				TrackedRecipe trackedRecipe = Entries[num];
				trackedRecipe.Amount -= Mathf.Max(1, crafts);
				if (trackedRecipe.Amount > 0)
				{
					Save();
					return;
				}
				Entries.RemoveAt(num);
				Save();
				Messages.TopLeft(Lang.Format("$ok_tracker_made", DisplayName(recipe, quality)));
			}
		}

		public static string DisplayName(Recipe recipe, int quality)
		{
			string text = Localization.instance.Localize(recipe.m_item.m_itemData.m_shared.m_name);
			if (quality <= 1)
			{
				return text;
			}
			return Lang.Format("$ok_tracker_upgrade", text, quality);
		}

		private static int StartAmount(Recipe recipe, int quality)
		{
			if (quality != 1 || !((Object)(object)BatchAmount.Current == (Object)(object)recipe))
			{
				return 1;
			}
			return Mathf.Max(1, BatchAmount.Value);
		}

		private static void Load(Player player)
		{
			loadedFor = player;
			entries = (from entry in CharacterData.GetList("trackedRecipes").Select(TrackedRecipe.Parse)
				where entry != null
				select entry).ToList();
			Version++;
		}

		private static void Save()
		{
			CharacterData.SetSet("trackedRecipes", Entries.Select((TrackedRecipe entry) => entry.ToString()));
			Version++;
		}
	}
	public static class TrackerModule
	{
		public static void Initialize(SyncedConfiguration synced)
		{
			TrackerSettings.Bind(synced);
		}
	}
	public sealed class TrackerPanel
	{
		private const int InventoryOrder = 600;

		private const int AboveInventory = 50;

		private static readonly Vector2 DefaultPosition = new Vector2(20f, 330f);

		private readonly RectTransform root;

		private readonly CanvasGroup group;

		private readonly Image background;

		private readonly TMP_Text title;

		private readonly RectTransform list;

		private readonly List<TrackerEntry> entries = new List<TrackerEntry>();

		private bool? open;

		private TrackerPanel(RectTransform root)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			this.root = root;
			group = ((Component)root).gameObject.AddComponent<CanvasGroup>();
			background = ((Component)root).gameObject.AddComponent<Image>();
			((Graphic)background).raycastTarget = false;
			((LayoutGroup)TrackerUi.Column(((Component)root).gameObject, 2f)).padding = new RectOffset(6, 6, 4, 6);
			ContentSizeFitter obj = ((Component)root).gameObject.AddComponent<ContentSizeFitter>();
			obj.horizontalFit = (FitMode)2;
			obj.verticalFit = (FitMode)2;
			title = Title(root);
			list = TrackerUi.Node("OpenKeep_TrackerList", (Transform)(object)root);
			TrackerUi.Column(((Component)list).gameObject, 4f);
		}

		public static TrackerPanel Create(Transform hudRoot)
		{
			//IL_0016: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = TrackerUi.Node("OpenKeep_Tracker", hudRoot);
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(0f, 1f);
			obj.pivot = new Vector2(0f, 1f);
			OwnCanvas(((Component)obj).gameObject, hudRoot);
			return new TrackerPanel(obj);
		}

		private static void OwnCanvas(GameObject go, Transform hudRoot)
		{
			Canvas componentInParent = ((Component)hudRoot).GetComponentInParent<Canvas>();
			Canvas val = (((Object)(object)InventoryGui.instance != (Object)null) ? ((Component)InventoryGui.instance).GetComponent<Canvas>() : null);
			Canvas val2 = go.AddComponent<Canvas>();
			val2.overrideSorting = true;
			if ((Object)(object)componentInParent != (Object)null)
			{
				val2.sortingLayerID = componentInParent.sortingLayerID;
			}
			val2.sortingOrder = (((Object)(object)val != (Object)null) ? val.sortingOrder : 600) + 50;
			go.AddComponent<GraphicRaycaster>();
		}

		public void SetVisible(bool visible)
		{
			if (((Component)root).gameObject.activeSelf != visible)
			{
				((Component)root).gameObject.SetActive(visible);
			}
		}

		public void Interactive(bool free)
		{
			if (open == free)
			{
				return;
			}
			open = free;
			group.blocksRaycasts = free;
			foreach (TrackerEntry entry in entries)
			{
				entry.ShowControls(free);
			}
			KeepOnScreen();
		}

		public void Rebuild()
		{
			for (int num = ((Transform)this.list).childCount - 1; num >= 0; num--)
			{
				GameObject gameObject = ((Component)((Transform)this.list).GetChild(num)).gameObject;
				gameObject.SetActive(false);
				Object.Destroy((Object)(object)gameObject);
			}
			entries.Clear();
			Style();
			List<TrackedRecipe> list = TrackerList.Entries;
			for (int i = 0; i < list.Count; i++)
			{
				Recipe recipe = list[i].Recipe;
				if (!((Object)(object)recipe == (Object)null))
				{
					TrackerEntry trackerEntry = TrackerEntry.Build((Transform)(object)this.list, list[i], recipe, i);
					trackerEntry.ShowControls(open == true);
					entries.Add(trackerEntry);
				}
			}
		}

		public void Count(Player player)
		{
			foreach (TrackerEntry entry in entries)
			{
				entry.Count(player);
			}
		}

		private void Style()
		{
			//IL_0018: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			float value = TrackerSettings.Scale.Value;
			((Transform)root).localScale = new Vector3(value, value, 1f);
			Image val = GameBackground();
			if ((Object)(object)val != (Object)null)
			{
				background.sprite = val.sprite;
				background.type = val.type;
			}
			((Graphic)background).color = new Color(0f, 0f, 0f, TrackerSettings.BackgroundOpacity.Value);
			title.font = TrackerStyle.Font;
			title.fontSize = TrackerStyle.Size * 0.8f;
			title.text = Lang.Get("$ok_tracker_title");
		}

		private static TMP_Text Title(RectTransform root)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text obj = TrackerUi.Text((Transform)(object)root, "OpenKeep_TrackerTitle", TrackerStyle.Size * 0.8f, (TextAlignmentOptions)4097);
			((Graphic)obj).color = TrackerStyle.Dim;
			((Graphic)obj).raycastTarget = true;
			((Component)obj).gameObject.AddComponent<TrackerDrag>().Target = root;
			return obj;
		}

		public void Place()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Vector2 position;
			Vector2 val = (TrackerDrag.Saved(out position) ? position : DefaultPosition);
			root.anchoredPosition = new Vector2(val.x, 0f - val.y);
			KeepOnScreen();
		}

		public void KeepOnScreen()
		{
			LayoutRebuilder.ForceRebuildLayoutImmediate(root);
			TrackerDrag.Clamp(root);
		}

		private static Image GameBackground()
		{
			InventoryGui instance = InventoryGui.instance;
			Transform val = (((Object)(object)instance != (Object)null && (Object)(object)instance.m_recipeDecription != (Object)null) ? instance.m_recipeDecription.transform.parent : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<Image>();
		}
	}
	[HarmonyPatch]
	public static class TrackerPatches
	{
		[HarmonyPatch(typeof(Hud), "Awake")]
		[HarmonyPostfix]
		public static void AfterHudAwake(Hud __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<TrackerHud>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<TrackerHud>();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyPrefix]
		[HarmonyPriority(200)]
		public static void BeforeCrafting(InventoryGui __instance, Player player, out CraftWatch __state)
		{
			__state = CraftWatch.Start(__instance, player);
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		[HarmonyPostfix]
		public static void AfterCrafting(Player player, CraftWatch __state)
		{
			__state?.Finish(player);
		}
	}
	public static class TrackerSettings
	{
		public const string Section = "13. Recipe Tracker";

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<int> MaxTracked { get; private set; }

		public static ConfigEntry<bool> CountNearbyChests { get; private set; }

		public static ConfigEntry<bool> UntrackWhenCrafted { get; private set; }

		public static ConfigEntry<bool> HideInCombat { get; private set; }

		public static ConfigEntry<bool> HideWithMap { get; private set; }

		public static ConfigEntry<float> Scale { get; private set; }

		public static ConfigEntry<TrackerFont> Font { get; private set; }

		public static ConfigEntry<int> FontSize { get; private set; }

		public static ConfigEntry<string> HaveColour { get; private set; }

		public static ConfigEntry<string> MissingColour { get; private set; }

		public static ConfigEntry<string> ReadyColour { get; private set; }

		public static ConfigEntry<float> BackgroundOpacity { get; private set; }

		public static ConfigEntry<string> Position { get; private set; }

		public static void Bind(SyncedConfiguration synced)
		{
			Enabled = synced.Bind("13. Recipe Tracker", "Enabled", true, "Track a recipe (right click it in the crafting list, its Track button, or right stick down on a gamepad) to keep it on screen with every material it needs: what you have against what the tracked amount needs. With the inventory open, drag the tracker by its title, change an amount with - and + (Shift: tens) or the mouse wheel, and remove a recipe with the X at its left.", false, null);
			MaxTracked = synced.Bind("13. Recipe Tracker", "Max Tracked", 6, "The most recipes tracked at once.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 12));
			CountNearbyChests = synced.Bind("13. Recipe Tracker", "Count Nearby Chests", true, "Materials in the containers Reach would craft from where you stand count too (only while Reach and its Crafting switch are on). Off: only what you carry.", false, null);
			UntrackWhenCrafted = synced.Bind("13. Recipe Tracker", "Untrack When Crafted", true, "Crafting a tracked recipe counts its amount down; once that many are made it leaves the tracker. Off: it stays until you remove it.", false, null);
			HideInCombat = synced.Bind("13. Recipe Tracker", "Hide In Combat", true, "Hidden while a creature is after you, and for 5 seconds after.", false, null);
			HideWithMap = synced.Bind("13. Recipe Tracker", "Hide With Map", true, "Hidden while the large map is open.", false, null);
			BindLook(synced);
		}

		private static void BindLook(SyncedConfiguration synced)
		{
			Scale = synced.Bind("13. Recipe Tracker", "Scale", 1f, "The tracker's size.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.5f, 2f));
			Font = synced.Bind("13. Recipe Tracker", "Font", TrackerFont.Sans, "The game's typeface to use: Sans (its body text), Serif (its item names) or Norse (its titles).", false, null);
			FontSize = synced.Bind("13. Recipe Tracker", "Font Size", 16, "The text size; the tracker widens with it.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(10, 28));
			HaveColour = synced.Bind("13. Recipe Tracker", "Have Colour", "#FFFFFF", "A material you have enough of (HTML colour).", false, null);
			MissingColour = synced.Bind("13. Recipe Tracker", "Missing Colour", "#FF6A5A", "A material you are short of (HTML colour).", false, null);
			ReadyColour = synced.Bind("13. Recipe Tracker", "Ready Colour", "#FFB65C", "A recipe's name once every material is there (HTML colour).", false, null);
			BackgroundOpacity = synced.Bind("13. Recipe Tracker", "Background Opacity", 0.56f, "The dark background behind the tracker, 0 (none) to 1.", false, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0f, 1f));
			Position = synced.Bind("13. Recipe Tracker", "Position", "", "Where the tracker's top left corner sits: x right and y down from the screen's top left, in interface units (20,330 is the default place at the left edge); written when you drag it. A place off the screen is pulled back onto it. Empty: the default place.", false, null);
		}

		public static Color Colour(ConfigEntry<string> entry, Color fallback)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (entry == null || !ColorUtility.TryParseHtmlString(entry.Value, ref result))
			{
				return fallback;
			}
			return result;
		}
	}
	public static class TrackerStyle
	{
		private static readonly string[] FontNames = new string[3] { "Valheim-AveriaSansLibre", "Valheim-AveriaSerifLibre", "Valheim-Norsebold" };

		private static readonly TMP_FontAsset[] fonts = (TMP_FontAsset[])(object)new TMP_FontAsset[FontNames.Length];

		public static readonly Color Dim = new Color(0.72f, 0.72f, 0.72f, 1f);

		public static float Size => TrackerSettings.FontSize.Value;

		public static Color Have => TrackerSettings.Colour(TrackerSettings.HaveColour, Color.white);

		public static Color Missing => TrackerSettings.Colour(TrackerSettings.MissingColour, new Color(1f, 0.42f, 0.35f));

		public static Color Ready => TrackerSettings.Colour(TrackerSettings.ReadyColour, new Color(1f, 0.713f, 0.361f));

		public static string Signature => $"{TrackerSettings.Font.Value}|{TrackerSettings.FontSize.Value}|{TrackerSettings.Scale.Value}|{TrackerSettings.BackgroundOpacity.Value}|{(((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.m_recipes.Count : 0)}";

		public static TMP_FontAsset Font
		{
			get
			{
				int num = Mathf.Clamp((int)TrackerSettings.Font.Value, 0, FontNames.Length - 1);
				if ((Object)(object)fonts[num] == (Object)null)
				{
					fonts[num] = Find(FontNames[num]);
				}
				if (!((Object)(object)fonts[num] != (Object)null))
				{
					return Fallback();
				}
				return fonts[num];
			}
		}

		private static TMP_FontAsset Find(string name)
		{
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			foreach (TMP_FontAsset val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == name)
				{
					return val;
				}
			}
			return null;
		}

		private static TMP_FontAsset Fallback()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_recipeDecription != (Object)null && (Object)(object)instance.m_recipeDecription.font != (Object)null)
			{
				return instance.m_recipeDecription.font;
			}
			return TMP_Settings.defaultFontAsset;
		}
	}
	public static class TrackerUi
	{
		private static readonly Color Hover = new Color(1f, 0.713f, 0.361f, 1f);

		public static RectTransform Node(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		public static TMP_Text Text(Transform parent, string name, float size, TextAlignmentOptions align)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.layer = ((Component)parent).gameObject.layer;
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = TrackerStyle.Font;
			val.SetActive(true);
			((TMP_Text)val2).fontSize = size;
			((TMP_Text)val2).alignment = align;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val2).overflowMode = (TextOverflowModes)1;
			((Graphic)val2).raycastTarget = false;
			((Graphic)val2).color = Color.white;
			return (TMP_Text)(object)val2;
		}

		public static Image Icon(Transform parent, Sprite sprite, float size)
		{
			RectTransform val = Node("icon", parent);
			Image obj = ((Component)val).gameObject.AddComponent<Image>();
			obj.sprite = sprite;
			obj.preserveAspect = true;
			((Graphic)obj).raycastTarget = false;
			Fixed(((Component)val).gameObject, size, size);
			return obj;
		}

		public static Button TextButton(Transform parent, string name, string label, float size, Action click)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			RectTransform val = Node(name, parent);
			((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = Color.clear;
			Button val2 = ((Component)val).gameObject.AddComponent<Button>();
			TMP_Text val3 = Text((Transform)(object)val, "label", size, (TextAlignmentOptions)514);
			Stretch((RectTransform)val3.transform);
			val3.overflowMode = (TextOverflowModes)0;
			val3.text = label;
			((Selectable)val2).targetGraphic = (Graphic)(object)val3;
			ColorBlock colors = ((Selectable)val2).colors;
			((ColorBlock)(ref colors)).highlightedColor = Hover;
			((ColorBlock)(ref colors)).pressedColor = Hover;
			((Selectable)val2).colors = colors;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)val2).navigation = navigation;
			((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
			{
				Guard.Run("tracker " + name, click);
			});
			Fixed(((Component)val).gameObject, size, size);
			return val2;
		}

		public static HorizontalLayoutGroup Row(Transform parent, string name, float spacing)
		{
			HorizontalLayoutGroup obj = ((Component)Node(name, parent)).gameObject.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing;
			((LayoutGroup)obj).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			return obj;
		}

		public static VerticalLayoutGroup Column(GameObject go, float spacing)
		{
			VerticalLayoutGroup obj = go.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing;
			((LayoutGroup)obj).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			return obj;
		}

		public static void Fixed(GameObject go, float width, float height)
		{
			LayoutElement obj = go.AddComponent<LayoutElement>();
			obj.minWidth = width;
			obj.preferredWidth = width;
			obj.minHeight = height;
			obj.preferredHeight = height;
		}

		public static void Flexible(TMP_Text text, float most)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			LayoutElement obj = ((Component)text).gameObject.AddComponent<LayoutElement>();
			obj.flexibleWidth = 1f;
			obj.preferredWidth = Mathf.Min(text.GetPreferredValues(text.text).x + 1f, most);
			obj.minWidth = obj.preferredWidth;
		}

		public static void Short(TMP_Text text, float minWidth)
		{
			text.overflowMode = (TextOverflowModes)0;
			((Component)text).gameObject.AddComponent<LayoutElement>().minWidth = minWidth;
		}

		public static void Stretch(RectTransform rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = Vector2.zero;
			rect.offsetMax = Vector2.zero;
		}
	}
	public static class TrackerVisibility
	{
		private const float CombatLinger = 5f;

		private static float lastThreat = -100f;

		public static bool CursorFree
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Invalid comparison between Unknown and I4
				if ((int)ZCursor.LockState != 1)
				{
					return ZCursor.IsVisible;
				}
				return false;
			}
		}

		public static bool Show()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!TrackerSettings.Enabled.Value || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				return false;
			}
			if (localPlayer.IsTargeted())
			{
				lastThreat = Time.time;
			}
			if (TrackerList.Entries.Count == 0)
			{
				return false;
			}
			if (TrackerSettings.HideWithMap.Value && Minimap.IsOpen())
			{
				return false;
			}
			if (TrackerSettings.HideInCombat.Value)
			{
				return Time.time - lastThreat >= 5f;
			}
			return true;
		}
	}
	public class TrackerWheel : MonoBehaviour, IScrollHandler, IEventSystemHandler
	{
		public int Index;

		public void OnScroll(PointerEventData data)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			float delta = data.scrollDelta.y;
			if (!Mathf.Approximately(delta, 0f))
			{
				bool tens = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				Guard.Run("tracker wheel", delegate
				{
					TrackerList.Step(Index, (delta > 0f) ? 1 : (-1), tens);
				});
			}
		}
	}
	public static class TrackerWords
	{
		public const string Track = "$ok_tracker_track";

		public const string Untrack = "$ok_tracker_untrack";

		public const string Title = "$ok_tracker_title";

		public const string Tracking = "$ok_tracker_tracking";

		public const string Untracked = "$ok_tracker_untracked";

		public const string Full = "$ok_tracker_full";

		public const string Made = "$ok_tracker_made";

		public const string Upgrade = "$ok_tracker_upgrade";

		public const string Station = "$ok_tracker_station";

		public const string AnyOne = "$ok_tracker_anyone";
	}
}
namespace OpenKeep.Store
{
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	public static class AutoSortPatch
	{
		[HarmonyPrefix]
		public static void Prefix(InventoryGui __instance, out bool __state)
		{
			__state = InventoryGui.IsVisible();
		}

		[HarmonyPostfix]
		public static void Postfix(Container container, bool __state)
		{
			if (StoreSettings.Enabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if ((Object)(object)container != (Object)null && StoreSettings.AutoSortContainers.Value)
				{
					Sorting.SortContainer(container, quiet: true);
				}
				if (!__state && StoreSettings.AutoSortInventory.Value)
				{
					Sorting.SortPlayer(Player.m_localPlayer, quiet: true);
				}
			}
		}
	}
	internal sealed class ChestBatch
	{
		private readonly Container container;

		private readonly string word;

		private int pending;

		private bool finished;

		public bool Shared { get; }

		public int Moved { get; private set; }

		public bool Waiting => pending > 0;

		public ChestBatch(Container container, string word)
		{
			this.container = container;
			this.word = word;
			Shared = StoreTargets.IsShared(container);
		}

		public void Put(ItemData item, int amount, int credit, Action after = null)
		{
			pending++;
			StackMover.Reserve(item);
			ChestWriter.Put(container, item, amount, null, delegate(bool ok)
			{
				StackMover.Release(item);
				Reply(ok, credit);
				after?.Invoke();
			});
		}

		public void Take(ItemData item, int amount, int credit)
		{
			pending++;
			ChestWriter.Take(container, item, amount, delegate(bool ok)
			{
				Reply(ok, credit);
			});
		}

		public void Finish()
		{
			finished = true;
		}

		private void Reply(bool ok, int credit)
		{
			pending--;
			if (ok)
			{
				Moved += credit;
			}
			if (finished && pending == 0)
			{
				Report();
			}
		}

		private void Report()
		{
			if (Moved > 0)
			{
				MoveMessages.Center(Lang.Format(word, Moved, StoreTargets.Name(container)));
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	public static class ClickRouting
	{
		[HarmonyPrefix]
		public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			if (!StoreSettings.Enabled.Value || item == null || (Object)(object)__instance.m_dragGo != (Object)null || (Object)(object)grid != (Object)(object)__instance.m_playerGrid)
			{
				return true;
			}
			if ((int)mod == 3 || !Keys.Held(StoreSettings.RouteModifier))
			{
				return true;
			}
			Routing.Route(item);
			return false;
		}
	}
	public static class Cycling
	{
		private const float WheelCooldown = 0.25f;

		private static float lastWheel;

		public static void Poll(InventoryGui gui)
		{
			if (!((Object)(object)gui.m_currentContainer == (Object)null))
			{
				if (Keys.Pressed(StoreSettings.CyclePreviousKey))
				{
					Cycle(-1);
				}
				else if (Keys.Pressed(StoreSettings.CycleNextKey))
				{
					Cycle(1);
				}
				else if (StoreSettings.CycleWithWheel.Value)
				{
					PollWheel(gui);
				}
			}
		}

		private static void PollWheel(InventoryGui gui)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			float mouseScrollWheel = ZInput.GetMouseScrollWheel();
			if (mouseScrollWheel == 0f || Time.time - lastWheel < 0.25f || Keys.TextInputActive || (Object)(object)gui.m_containerGrid == (Object)null || TooltipScrolls() || GridScrolls(gui.m_containerGrid))
			{
				return;
			}
			Transform transform = ((Component)gui.m_containerGrid).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (!((Object)(object)val == (Object)null))
			{
				Rect rect = val.rect;
				if (((Rect)(ref rect)).Contains(Vector2.op_Implicit(((Transform)val).InverseTransformPoint(ZInput.pointerPosition))))
				{
					lastWheel = Time.time;
					Cycle((!(mouseScrollWheel > 0f)) ? 1 : (-1));
				}
			}
		}

		private static bool GridScrolls(InventoryGrid grid)
		{
			Scrollbar scrollbar = grid.m_scrollbar;
			if ((Object)(object)scrollbar != (Object)null && ((Component)scrollbar).gameObject.activeInHierarchy)
			{
				return scrollbar.size < 0.999f;
			}
			return false;
		}

		private static bool TooltipScrolls()
		{
			GameObject tooltip = UITooltip.m_tooltip;
			Transform val = (((Object)(object)tooltip != (Object)null && tooltip.activeInHierarchy) ? Utils.FindChild(tooltip.transform, "ecf_tooltip_bar", (IterativeSearchType)0) : null);
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject.activeInHierarchy;
			}
			return false;
		}

		public static void Cycle(int direction)
		{
			if (!StoreActions.Ready(out var player))
			{
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			Container val = (((Object)(object)instance != (Object)null) ? instance.m_currentContainer : null);
			if (!((Object)(object)val == (Object)null))
			{
				List<Container> list = Ring(player, instance, val);
				if (list.Count < 2)
				{
					Messages.Center("$ok_store_nocycle");
					return;
				}
				int num = list.IndexOf(val);
				Container obj = list[(num + direction + list.Count) % list.Count];
				instance.CloseContainer();
				obj.Interact((Humanoid)(object)player, false, false);
			}
		}

		private static List<Container> Ring(Player player, InventoryGui gui, Container current)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(StoreSettings.NearbyRange.Value, gui.m_autoCloseDistance);
			Vector3 origin = ((Component)player).transform.position;
			List<Container> list = ContainerScan.Nearby(origin, num, ContainerUse.Store);
			foreach (Container item in ContainerScan.All())
			{
				if (!list.Contains(item) && StoreTargets.Distance(origin, item) <= num && Viewable(item))
				{
					list.Add(item);
				}
			}
			if (!list.Contains(current))
			{
				list.Add(current);
			}
			list.Sort((Container a, Container b) => Angle(origin, a).CompareTo(Angle(origin, b)));
			return list;
		}

		private static bool Viewable(Container container)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || CoreSettings.SharedChests.Value == SharedMode.Off || container.GetInventory() == null)
			{
				return false;
			}
			if (!ContainerScan.InUseByAnother(container) || !ContainerRules.IsEnabled(ContainerScan.PrefabName(container)) || !SwitchAllows(container))
			{
				return false;
			}
			if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
			{
				return false;
			}
			if ((int)container.m_privacy == 0 && (Object)(object)container.m_piece == (Object)null)
			{
				return false;
			}
			return container.CheckAccess(localPlayer.GetPlayerID());
		}

		private static bool SwitchAllows(Container container)
		{
			if (ContainerScan.IsShip(container))
			{
				return CoreSettings.Ships.Value;
			}
			if (ContainerScan.IsCart(container))
			{
				return CoreSettings.Carts.Value;
			}
			if (ContainerScan.IsPrivateChest(container))
			{
				return CoreSettings.PlayerChests.Value;
			}
			return true;
		}

		private static float Angle(Vector3 origin, Container container)
		{
			//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)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)container).transform.position - origin;
			return Mathf.Atan2(val.z, val.x);
		}
	}
	public static class DumpKeyPatch
	{
		public static void Tick(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && StoreSettings.Enabled.Value && !Keys.InventoryOpen && !Menu.IsVisible() && !Console.IsVisible() && !UnifiedPopup.IsVisible() && Keys.Pressed(StoreSettings.DumpKey))
			{
				StoreActions.Dump();
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
	public static class FavouriteOverlay
	{
		[HarmonyPostfix]
		public static void Postfix(InventoryGrid __instance, Player player)
		{
			Refresh(__instance, (Object)(object)player != (Object)null);
		}

		public static void Refresh(InventoryGrid grid, bool playerGrid)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			bool flag = StoreSettings.Enabled.Value && StoreSettings.ShowFavourites.Value;
			if (GridMarks.Of(grid).Current(grid.m_inventory, grid.m_elements, flag, playerGrid))
			{
				return;
			}
			Inventory inventory = grid.m_inventory;
			foreach (InventoryElement element in grid.m_elements)
			{
				SlotMarks slotMarks = ((Component)element).GetComponent<SlotMarks>();
				if (!((Object)(object)slotMarks == (Object)null) || (flag && inventory != null))
				{
					if ((Object)(object)slotMarks == (Object)null)
					{
						slotMarks = SlotMarks.Attach(element);
					}
					ItemData val = ((flag && inventory != null) ? inventory.GetItemAt(element.Position.x, element.Position.y) : null);
					bool favouriteItem = val != null && Favourites.IsFavouriteItem(val);
					bool favouriteSlot = flag && playerGrid && Favourites.IsFavouriteSlot(element.Position);
					bool junk = val != null && Favourites.IsJunk(val);
					slotMarks.Set(favouriteItem, favouriteSlot, junk);
				}
			}
		}
	}
	public static class Favourites
	{
		private const string ItemsKey = "favouriteItems";

		private const string SlotsKey = "favouriteSlots";

		private const string JunkKey = "junk";

		private static Player cachedFor;

		private static HashSet<string> items;

		private static HashSet<string> slots;

		private static HashSet<string> junk;

		private static HashSet<int> slotKeys;

		private static int revision;

		public static int Revision
		{
			get
			{
				CheckPlayer();
				return revision;
			}
		}

		public static bool IsFavouriteItem(ItemData item)
		{
			if (item != null)
			{
				return Set(ref items, "favouriteItems").Contains(Id(item));
			}
			return false;
		}

		public static bool IsJunk(ItemData item)
		{
			if (item != null)
			{
				return Set(ref junk, "junk").Contains(Id(item));
			}
			return false;
		}

		public static bool IsFavouriteSlot(Vector2i pos)
		{
			//IL_0005: 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)
			return SlotKeys().Contains(Pack(pos.x, pos.y));
		}

		public static bool ToggleItem(ItemData item)
		{
			return Toggle(ref items, "favouriteItems", Id(item));
		}

		public static bool ToggleSlot(Vector2i pos)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			slotKeys = null;
			return Toggle(ref slots, "favouriteSlots", SlotId(pos));
		}

		public static bool ToggleJunk(ItemData item)
		{
			return Toggle(ref junk, "junk", Id(item));
		}

		public static void ToggleItemWithMessage(ItemData item)
		{
			Messages.Center(Lang.Format(ToggleItem(item) ? "$ok_store_favourite_on" : "$ok_store_favourite_off", ItemNames.DisplayName(item)));
		}

		public static void ToggleSlotWithMessage(Vector2i pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Messages.Center(Lang.Format(ToggleSlot(pos) ? "$ok_store_slot_on" : "$ok_store_slot_off", pos.x + 1 + "," + (pos.y + 1)));
		}

		public static void ToggleJunkWithMessage(ItemData item)
		{
			Messages.Center(Lang.Format(ToggleJunk(item) ? "$ok_store_junk_on" : "$ok_store_junk_off", ItemNames.DisplayName(item)));
		}

		private static string Id(ItemData item)
		{
			return ItemNames.PrefabName(item);
		}

		private static string SlotId(Vector2i pos)
		{
			return pos.x + ":" + pos.y;
		}

		private static int Pack(int x, int y)
		{
			return (x << 16) | (y & 0xFFFF);
		}

		private static HashSet<int> SlotKeys()
		{
			HashSet<string> hashSet = Set(ref slots, "favouriteSlots");
			if (slotKeys != null)
			{
				return slotKeys;
			}
			slotKeys = new HashSet<int>();
			foreach (string item in hashSet)
			{
				string[] array = item.Split(new char[1] { ':' });
				if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2))
				{
					slotKeys.Add(Pack(result, result2));
				}
			}
			return slotKeys;
		}

		private static bool Toggle(ref HashSet<string> set, string key, string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			HashSet<string> hashSet = Set(ref set, key);
			bool num = !hashSet.Remove(id);
			if (num)
			{
				hashSet.Add(id);
			}
			CharacterData.SetSet(key, hashSet);
			revision++;
			return num;
		}

		private static HashSet<string> Set(ref HashSet<string> set, string key)
		{
			CheckPlayer();
			return set ?? (set = CharacterData.GetSet(key));
		}

		private static void CheckPlayer()
		{
			if (!((Object)(object)cachedFor == (Object)(object)Player.m_localPlayer))
			{
				items = (slots = (junk = null));
				slotKeys = null;
				cachedFor = Player.m_localPlayer;
				revision++;
			}
		}
	}
	public static class Finder
	{
		private const float DefaultSeconds = 5f;

		public static void Find(ItemData item)
		{
			if (!StoreActions.Ready(out var player) || item == null)
			{
				return;
			}
			string text = ItemNames.DisplayName(item);
			float seconds = LinkSeconds();
			int num = 0;
			foreach (Container item2 in StoreTargets.Nearby(player))
			{
				int num2 = item2.GetInventory().CountItems(item.m_shared.m_name, -1, false);
				if (num2 > 0)
				{
					num++;
					LinkMarker.Create(player, item2, text + " x" + num2, seconds);
				}
			}
			Messages.Center((num > 0) ? Lang.Format("$ok_store_found", text, num) : Lang.Format("$ok_store_notfound", text));
		}

		public static float LinkSeconds()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			ConfigFile val = (((Object)(object)Plugin.Instance != (Object)null) ? ((BaseUnityPlugin)Plugin.Instance).Config : null);
			ConfigDefinition val2 = new ConfigDefinition("1. Reach", "Link Seconds");
			if (val == null || !val.ContainsKey(val2))
			{
				return 5f;
			}
			try
			{
				return Convert.ToSingle(val[val2].BoxedValue);
			}
			catch (Exception)
			{
				return 5f;
			}
		}
	}
	public sealed class GridMarks : MonoBehaviour
	{
		private const float MaxAge = 0.25f;

		private Inventory inventory;

		private InventoryElement first;

		private int count = -1;

		private int change = -1;

		private int revision = -1;

		private bool show;

		private bool playerGrid;

		private float at = float.MinValue;

		public static GridMarks Of(InventoryGrid grid)
		{
			GridMarks component = ((Component)grid).GetComponent<GridMarks>();
			if (!((Object)(object)component != (Object)null))
			{
				return ((Component)grid).gameObject.AddComponent<GridMarks>();
			}
			return component;
		}

		public bool Current(Inventory now, List<InventoryElement> elements, bool showing, bool forPlayer)
		{
			InventoryElement val = ((elements.Count > 0) ? elements[0] : null);
			float unscaledTime = Time.unscaledTime;
			if (now == inventory && (Object)(object)val == (Object)(object)first && elements.Count == count && InventoryChanges.Count == change && Favourites.Revision == revision && showing == show && forPlayer == playerGrid && unscaledTime - at < 0.25f)
			{
				return true;
			}
			inventory = now;
			first = val;
			count = elements.Count;
			change = InventoryChanges.Count;
			revision = Favourites.Revision;
			show = showing;
			playerGrid = forPlayer;
			at = unscaledTime;
			return false;
		}
	}
	[HarmonyPatch(typeof(Container), "CheckForChanges")]
	public static class GroundPickup
	{
		private static readonly Dictionary<Container, float> nextSweep = new Dictionary<Container, float>();

		private static readonly List<ItemDrop> drops = new List<ItemDrop>();

		private static readonly PruneMark pruneMark = new PruneMark(64);

		[HarmonyPostfix]
		public static void Postfix(Container __instance)
		{
			Tick(__instance);
		}

		public static void Tick(Container container)
		{
			if (!StoreSettings.Enabled.Value || !StoreSettings.GroundPickup.Value || (Object)(object)container == (Object)null)
			{
				return;
			}
			ZNetView nview = container.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner() || container.IsInUse() || !StoreRules.PicksUp(container) || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || !Due(container) || !ContainerScan.IsUsable(container, ContainerUse.Store))
			{
				return;
			}
			using (SaveHolds.Hold(container))
			{
				if (Sweep(container) > 0)
				{
					ContainerScan.Save(container);
				}
			}
		}

		private static bool Due(Container container)
		{
			float time = Time.time;
			float num = Mathf.Max(1f, StoreSettings.PickupInterval.Value);
			if (!nextSweep.TryGetValue(container, out var value))
			{
				if (pruneMark.Due(nextSweep.Count))
				{
					Prune();
				}
				nextSweep[container] = time + num * ((float)(((Object)container).GetInstanceID() & 0xFF) / 256f);
				return false;
			}
			if (time < value)
			{
				return false;
			}
			nextSweep[container] = time + num;
			return true;
		}

		private static void Prune()
		{
			List<Container> list = new List<Container>();
			foreach (Container key in nextSweep.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					list.Add(key);
				}
			}
			foreach (Container item in list)
			{
				nextSweep.Remove(item);
			}
			pruneMark.Pruned(nextSweep.Count);
		}

		private static int Sweep(Container container)
		{
			//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)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)container).transform.position;
			float value = StoreSettings.PickupRange.Value;
			List<Container> list = null;
			int num = 0;
			drops.AddRange(ItemDrop.s_instances);
			foreach (ItemDrop drop in drops)
			{
				if (!((Object)(object)drop == (Object)null) && Eligible(container, drop, position, value))
				{
					list = list ?? PickupOrder.Rivals(container, value);
					if (PickupOrder.IsFirst(container, drop, list, value))
					{
						num += Take(container, drop);
					}
				}
			}
			drops.Clear();
			return num;
		}

		private static bool Eligible(Container container, ItemDrop drop, Vector3 origin, float range)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = origin - ((Component)drop).transform.position;
			if (((Vector3)(ref val)).sqrMagnitude > range * range)
			{
				return false;
			}
			ZNetView nview = drop.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || drop.m_itemData == null || drop.m_itemData.m_shared == null || drop.IsPiece())
			{
				return false;
			}
			if (Age(nview) < (double)StoreSettings.PickupDelay.Value || !Wanted(container, drop.m_itemData))
			{
				return false;
			}
			if (CoreSettings.HonourWards.Value)
			{
				return PrivateArea.CheckAccess(((Component)drop).transform.position, 0f, false, false);
			}
			return true;
		}

		private static double Age(ZNetView view)
		{
			long num = view.GetZDO().GetLong(ZDOVars.s_spawnTime, 0L);
			if (num == 0L || (Object)(object)ZNet.instance == (Object)null)
			{
				return -1.0;
			}
			return (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds;
		}

		internal static bool Wanted(Container container, ItemData item)
		{
			if (StoreRules.Refuses(container, item))
			{
				return false;
			}
			if (StoreRules.Accepts(container, item))
			{
				return true;
			}
			if (StoreSettings.PickupOnlyHeldItems.Value)
			{
				return container.GetInventory().ContainsItemByName(item.m_shared.m_name);
			}
			return true;
		}

		private static bool Owned(ItemDrop drop)
		{
			ZNetView nview = drop.m_nview;
			if (nview.IsOwner())
			{
				return true;
			}
			if (nview.GetZDO().HasOwner())
			{
				drop.RequestOwn();
				return false;
			}
			nview.ClaimOwnership();
			return nview.IsOwner();
		}

		private static int Take(Container container, ItemDrop drop)
		{
			if (!Owned(drop))
			{
				return 0;
			}
			drop.Load();
			ItemData val = drop.m_itemData.Clone();
			int stack = val.m_stack;
			if (stack <= 0)
			{
				return 0;
			}
			if (container.GetInventory().AddItem(val))
			{
				ZNetScene.instance.Destroy(((Component)drop).gameObject);
				return stack;
			}
			int num = stack - val.m_stack;
			if (num > 0)
			{
				drop.m_itemData.m_stack = val.m_stack;
				drop.Save();
			}
			return num;
		}
	}
	public static class HoveredItem
	{
		public static bool Find(InventoryGui gui, out InventoryGrid grid, out Vector2i pos)
		{
			//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)
			grid = null;
			pos = new Vector2i(-1, -1);
			if ((Object)(object)gui == (Object)null)
			{
				return false;
			}
			if (TryGrid(gui.m_playerGrid, out pos))
			{
				grid = gui.m_playerGrid;
				return true;
			}
			if ((Object)(object)gui.m_currentContainer != (Object)null && (Object)(object)gui.m_container != (Object)null && ((Component)gui.m_container).gameObject.activeSelf && TryGrid(gui.m_containerGrid, out pos))
			{
				grid = gui.m_containerGrid;
				return true;
			}
			return false;
		}

		public static ItemData Item(InventoryGrid grid, Vector2i pos)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)grid != (Object)null) || grid.m_inventory == null)
			{
				return null;
			}
			return grid.m_inventory.GetItemAt(pos.x, pos.y);
		}

		private static bool TryGrid(InventoryGrid grid, out Vector2i pos)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			pos = new Vector2i(-1, -1);
			if ((Object)(object)grid == (Object)null || grid.m_inventory == null || !((Component)grid).gameObject.activeInHierarchy)
			{
				return false;
			}
			if ((Object)(object)grid.m_uiGroup != (Object)null && grid.m_uiGroup.IsActive && (ZInput.IsExclusiveGamepadActive() || ZInput.IsTouchActive()))
			{
				pos = grid.m_selected;
				if (pos.x >= 0)
				{
					return pos.y >= 0;
				}
				return false;
			}
			InventoryElement hoveredElement = grid.GetHoveredElement();
			if ((Object)(object)hoveredElement == (Object)null)
			{
				return false;
			}
			pos = grid.GetElementPos(hoveredElement);
			return pos.x >= 0;
		}
	}
	public sealed class LinkMarker : MonoBehaviour
	{
		private static readonly Color LinkColour = new Color(0.44f, 0.76f, 1f, 0.9f);

		private static Material lineMaterial;

		private LineRenderer line;

		private TextMeshPro label;

		private Transform target;

		private float endTime;

		public static void Create(Player player, Container container, string text, float seconds)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("OpenKeep_link");
			LinkMarker linkMarker = val.AddComponent<LinkMarker>();
			linkMarker.target = ((Component)container).transform;
			linkMarker.endTime = Time.time + Mathf.Max(0.5f, seconds);
			linkMarker.line = BuildLine(val);
			linkMarker.label = BuildLabel(val, text);
			linkMarker.Refresh();
		}

		private void Update()
		{
			if (Time.time >= endTime || (Object)(object)target == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Refresh();
			}
		}

		private void Refresh()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_002f: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)Player.m_localPlayer).transform.position + Vector3.up;
			Vector3 val2 = target.position + Vector3.up * 0.5f;
			line.SetPosition(0, val);
			line.SetPosition(1, val2);
			label.transform.position = target.position + Vector3.up * 1.6f;
			Camera main = Camera.main;
			if ((Object)(object)main != (Object)null)
			{
				label.transform.rotation = Quaternion.LookRotation(label.transform.position - ((Component)main).transform.position);
			}
		}

		private static LineRenderer BuildLine(GameObject go)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			LineRenderer obj = go.AddComponent<LineRenderer>();
			obj.useWorldSpace = true;
			obj.positionCount = 2;
			obj.startWidth = 0.06f;
			obj.endWidth = 0.06f;
			((Renderer)obj).material = LineMaterial();
			obj.startColor = LinkColour;
			obj.endColor = LinkColour;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			return obj;
		}

		private static TextMeshPro BuildLabel(GameObject parent, string text)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			GameObject val = new GameObject("label");
			val.SetActive(false);
			val.transform.SetParent(parent.transform, false);
			TextMeshPro val2 = val.AddComponent<TextMeshPro>();
			TMP_FontAsset val3 = LabelFont();
			if ((Object)(object)val3 != (Object)null)
			{
				((TMP_Text)val2).font = val3;
			}
			val.SetActive(true);
			((TMP_Text)val2).text = text;
			((TMP_Text)val2).fontSize = 3.5f;
			((Graphic)val2).color = LinkColour;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val2).rectTransform.sizeDelta = new Vector2(8f, 1.5f);
			return val2;
		}

		private static TMP_FontAsset LabelFont()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.m_containerName != (Object)null && (Object)(object)instance.m_containerName.font != (Object)null)
			{
				return instance.m_containerName.font;
			}
			return TMP_Settings.defaultFontAsset;
		}

		private static Material LineMaterial()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			if ((Object)(object)lineMaterial != (Object)null)
			{
				return lineMaterial;
			}
			lineMaterial = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended") ?? Shader.Find("Standard"))
			{
				color = LinkColour
			};
			return lineMaterial;
		}
	}
	public static class MainGrid
	{
		private const int GameDefaultRows = 4;

		public static int FirstRow(Player player, Inventory inventory)
		{
			if (!((Object)(object)player != (Object)null) || inventory != ((Humanoid)player).GetInventory())
			{
				return 0;
			}
			return 1;
		}

		public static int Rows(Player player, Inventory inventory)
		{
			int height = inventory.GetHeight();
			if ((Object)(object)player == (Object)null || inventory != ((Humanoid)player).GetInventory())
			{
				return height;
			}
			int value = StoreSettings.MainInventoryRows.Value;
			return Math.Min(height, (value > 0) ? value : GameRows(player));
		}

		private static int GameRows(Player player)
		{
			if (PackPanelGrid.TryRead(player, out var _, out var mainRows, out var _))
			{
				return mainRows;
			}
			string s = default(string);
			if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result))
			{
				return result;
			}
			return 4;
		}
	}
	public static class Movable
	{
		public static string Blocker(Player player, Inventory inventory, ItemData item)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (item == null || item.m_shared == null)
			{
				return "";
			}
			if (item.m_equipped || ((Object)(object)player != (Object)null && ((Humanoid)player).IsItemEquiped(item)))
			{
				return "$ok_store_equipped_kept";
			}
			if (item.m_shared.m_questItem || StackMover.IsPending(item))
			{
				return "";
			}
			if ((Object)(object)player != (Object)null && inventory == ((Humanoid)player).GetInventory() && Favourites.IsFavouriteSlot(item.m_gridPos))
			{
				return "$ok_store_favourite_kept";
			}
			if (Favourites.IsFavouriteItem(item))
			{
				return "$ok_store_favourite_kept";
			}
			return null;
		}

		public static bool CanMove(Player player, Inventory inventory, ItemData item)
		{
			return Blocker(player, inventory, item) == null;
		}
	}
	internal static class MoveMessages
	{
		public static void Center(string text)
		{
			if (StoreSettings.MoveMessages.Value)
			{
				Messages.Center(text);
			}
		}

		public static void TopLeft(string text)
		{
			if (StoreSettings.MoveMessages.Value)
			{
				Messages.TopLeft(text);
			}
		}
	}
	internal sealed class Overflow
	{
		private readonly Player player;

		private readonly ItemData item;

		private readonly List<Container> line = new List<Container>();

		private readonly int chosen;

		private readonly int fallback = -1;

		private readonly Action<Overflow> done;

		private int left;

		private int next;

		public List<Container> Took { get; } = new List<Container>();

		public bool RefusalSaid { get; private set; }

		private Overflow(Player player, ItemData item, int amount, Container first, List<Container> rest, Container last, Action<Overflow> done)
		{
			this.player = player;
			this.item = item;
			this.done = done;
			left = amount;
			if ((Object)(object)first != (Object)null)
			{
				line.Add(first);
			}
			chosen = line.Count;
			foreach (Container item2 in rest)
			{
				if ((Object)(object)item2 != (Object)(object)first && (Object)(object)item2 != (Object)(object)last)
				{
					line.Add(item2);
				}
			}
			if ((Object)(object)last != (Object)null && (Object)(object)last != (Object)(object)first)
			{
				fallback = line.Count;
				line.Add(last);
			}
		}

		public static void Send(Player player, ItemData item, int amount, Container first, List<Container> rest, Action<Overflow> done, Container last = null)
		{
			new Overflow(player, item, amount, first, rest, last, done).Step();
		}

		private void Step()
		{
			Container target = NextTarget();
			if ((Object)(object)target == (Object)null)
			{
				done?.Invoke(this);
				return;
			}
			int before = Units();
			bool shared = StoreTargets.IsShared(target);
			StackMover.Reserve(item);
			ChestWriter.Put(target, item, Math.Min(left, before), null, delegate(bool ok)
			{
				Answered(target, before, shared, ok);
			});
		}

		private void Answered(Container target, int before, bool shared, bool ok)
		{
			StackMover.Release(item);
			int num = Math.Max(0, before - Units());
			if (num > 0)
			{
				left -= num;
				Took.Add(target);
			}
			RefusalSaid = shared && !ok;
			Step();
		}

		private Container NextTarget()
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return null;
			}
			while (next < line.Count && left > 0 && Units() > 0 && Movable.CanMove(player, ((Humanoid)player).GetInventory(), item))
			{
				Container val = line[next];
				bool mustHold = next >= chosen && next != fallback;
				next++;
				if (Takes(val, mustHold))
				{
					return val;
				}
			}
			return null;
		}

		private bool Takes(Container container, bool mustHold)
		{
			if ((Object)(object)container == (Object)null || !StoreTargets.IsTarget(container) || StoreRules.Refuses(container, item) || !container.GetInventory().CanAddItem(item, 1))
			{
				return false;
			}
			if (mustHold)
			{
				return container.GetInventory().ContainsItemByName(item.m_shared.m_name);
			}
			return true;
		}

		private int Units()
		{
			Inventory val = (((Object)(object)player != (Object)null) ? ((Humanoid)player).GetInventory() : null);
			if (val == null || !val.ContainsItem(item))
			{
				return 0;
			}
			return item.m_stack;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	public static class PanelButtons
	{
		private const float Width = 78f;

		private const float Height = 26f;

		private const float Gap = 4f;

		private const float BelowEdge = -30f;

		private const string PackPanelStrip = "PackPanel_buttonstrip";

		private const float InsideStrip = 2f;

		private const string Prefix = "OpenKeep_";

		private static readonly List<RectTransform> Placed = new List<RectTransform>();

		private static bool rowInside;

		private static float Offset => (StoreSettings.ButtonRowOffset != null) ? StoreSettings.ButtonRowOffset.Value : 0;

		private static float BottomOf(RectTransform rect)
		{
			return ((rowInside && (Object)(object)InventoryGui.instance != (Object)null && (Object)(object)((Transform)rect).parent == (Object)(object)InventoryGui.instance.m_player) ? 2f : (-30f)) + Offset;
		}

		public static void Follow(InventoryGui gui)
		{
			bool flag = StripShown(gui);
			if (flag != rowInside)
			{
				rowInside = flag;
				Reposition();
			}
		}

		private static bool StripShown(InventoryGui gui)
		{
			if (!PackPanelLink.Present || (Object)(object)gui == (Object)null || (Object)(object)gui.m_player == (Object)null)
			{
				return false;
			}
			Transform val = ((Transform)gui.m_player).Find("PackPanel_buttonstrip");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).gameObject.activeSelf;
			}
			return false;
		}

		[HarmonyPostfix]
		public static void Postfix(InventoryGui __instance)
		{
			Guard.Run("store panel buttons", delegate
			{
				Create(__instance);
			});
		}

		public static void Reposition()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			Placed.RemoveAll((RectTransform rect) => (Object)(object)rect == (Object)null);
			foreach (RectTransform item in Placed)
			{
				item.anchoredPosition = new Vector2(item.anchoredPosition.x, BottomOf(item));
			}
		}

		public static void Create(InventoryGui gui)
		{
			if (!((Object)(object)gui == (Object)null) && !((Object)(object)gui.m_takeAllButton == (Object)null) && !((Object)(object)gui.m_player == (Object)null) && !((Object)(object)gui.m_container == (Object)null))
			{
				bool flag = !PackPanelLink.LaysOutInventory && StoreSettings.TrashOnStatColumn.Value && TrashPlate.TryCreate(gui, delegate
				{
					TrashMode.CanClicked(gui);
				});
				float num = -123f - (flag ? 0f : 15f);
				Add(gui, gui.m_player, "$ok_store_quickstack", num, StoreActions.QuickStack);
				num += 82f;
				Add(gui, gui.m_player, "$ok_store_storeall", num, StoreActions.StoreAll);
				num += 82f;
				Add(gui, gui.m_player, "$ok_store_topup", num, TopUp.Run);
				num += 82f;
				Add(gui, gui.m_player, "$ok_store_sort", num, delegate
				{
					Sorting.SortPlayer(Player.m_localPlayer, quiet: false);
				});
				if (!flag)
				{
					AddTrash(gui, gui.m_player, num + 39f + 4f + 13f);
				}
				Add(gui, gui.m_container, "$ok_store_sort", 0f, Sorting.SortOpenContainer);
			}
		}

		private static void Add(InventoryGui gui, RectTransform panel, string word, float centreX, Action action)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, (Transform)(object)panel);
			((Object)val).name = "OpenKeep_" + word.TrimStart(new char[1] { '$' });
			val.SetActive(true);
			Place((RectTransform)val.transform, centreX, new Vector2(78f, 26f));
			Button component = val.GetComponent<Button>();
			if ((Object)(object)component != (Object)null)
			{
				component.onClick = new ButtonClickedEvent();
				((UnityEvent)component.onClick).AddListener((UnityAction)delegate
				{
					Guard.Run(word, action);
				});
			}
			SetLabel(val, word);
		}

		private static void Place(RectTransform rect, float centreX, Vector2 size)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0.5f, 0f);
			rect.anchorMax = new Vector2(0.5f, 0f);
			rect.pivot = new Vector2(0.5f, 0f);
			rect.anchoredPosition = new Vector2(centreX, BottomOf(rect));
			rect.sizeDelta = size;
			((Transform)rect).localScale = Vector3.one;
			Placed.Add(rect);
		}

		private static void SetLabel(GameObject go, string word)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text componentInChildren = go.GetComponentInChildren<TMP_Text>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				componentInChildren.text = Lang.Get(word);
				componentInChildren.enableAutoSizing = true;
				componentInChildren.fontSizeMax = Mathf.Max(12f, Mathf.Min(componentInChildren.fontSize, 16f));
				componentInChildren.fontSizeMin = 9f;
				componentInChildren.overflowMode = (TextOverflowModes)1;
				componentInChildren.margin = new Vector4(6f, 1f, 6f, 1f);
				componentInChildren.textWrappingMode = (TextWrappingModes)0;
			}
		}

		private static void AddTrash(InventoryGui gui, RectTransform panel, float centreX)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, (Transform)(object)panel);
			((Object)val).name = "OpenKeep_trashcan";
			val.SetActive(true);
			Place((RectTransform)val.transform, centreX, new Vector2(26f, 26f));
			TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.SetActive(false);
			}
			BinIcon(val.transform);
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener((UnityAction)delegate
			{
				Guard.Run("trash can", delegate
				{
					TrashMode.CanClicked(gui);
				});
			});
		}

		private static Image BinIcon(Transform button)
		{
			//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_003d: 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_0048: 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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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)
			GameObject val = new GameObject("icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(button, false);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = new Vector2(4f, 4f);
			val2.offsetMax = new Vector2(-4f, -4f);
			Image component = val.GetComponent<Image>();
			component.sprite = StoreSprites.Bin;
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = false;
			return component;
		}
	}
	internal static class PickupOrder
	{
		private const float HolderLead = 100000f;

		public static List<Container> Rivals(Container container, float range)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			List<Container> list = ContainerScan.Nearby(((Component)container).transform.position, range * 2f, ContainerUse.Store);
			list.RemoveAll((Container rival) => (Object)(object)rival == (Object)(object)container || !StoreRules.PicksUp(rival));
			return list;
		}

		public static bool IsFirst(Container container, ItemDrop drop, List<Container> rivals, float range)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			ItemData itemData = drop.m_itemData;
			Vector3 position = ((Component)drop).transform.position;
			float num = Rank(container, itemData, position);
			float num2 = range * range;
			foreach (Container rival in rivals)
			{
				if (!((Object)(object)rival == (Object)null))
				{
					Vector3 val = ((Component)rival).transform.position - position;
					if (!(((Vector3)(ref val)).sqrMagnitude > num2) && Rank(rival, itemData, position) < num && TakesNow(rival, itemData))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static float Rank(Container container, ItemData item, Vector3 at)
		{
			//IL_002a: 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)
			return (container.GetInventory().ContainsItemByName(item.m_shared.m_name) ? 0f : 100000f) + Vector3.Distance(((Component)container).transform.position, at);
		}

		private static bool TakesNow(Container rival, ItemData item)
		{
			if (StoreRules.PicksUp(rival) && !rival.IsInUse() && GroundPickup.Wanted(rival, item))
			{
				return rival.GetInventory().CanAddItem(item, 1);
			}
			return false;
		}
	}
	public static class Routing
	{
		public static void Route(ItemData item)
		{
			if (!StoreActions.Ready(out var player) || Refused(player, item))
			{
				return;
			}
			string name = ItemNames.DisplayName(item);
			List<Container> list = StoreTargets.Nearby(player);
			list.RemoveAll((Container container) => StoreRules.Refuses(container, item));
			Container val = FindTarget(list, item);
			if ((Object)(object)val == (Object)null)
			{
				Messages.Center(Lang.Format("$ok_store_noroute", name));
			}
			else
			{
				Overflow.Send(player, item, item.m_stack, val, list, delegate(Overflow sent)
				{
					Report(sent, SentWords(sent, name));
				}, StoreTargets.OpenTarget);
			}
		}

		public static void StoreOne(ItemData item)
		{
			if (!StoreActions.Ready(out var player) || Refused(player, item))
			{
				return;
			}
			string name = ItemNames.DisplayName(item);
			Container openTarget = StoreTargets.OpenTarget;
			if ((Object)(object)openTarget == (Object)null && StoreTargets.ViewingOnly())
			{
				return;
			}
			List<Container> list = StoreTargets.Nearby(player);
			openTarget = openTarget ?? Holder(list, item);
			if ((Object)(object)openTarget == (Object)null || StoreRules.Refuses(openTarget, item))
			{
				Messages.Center(Lang.Format("$ok_store_noroute", name));
				return;
			}
			Overflow.Send(player, item, 1, openTarget, list, delegate(Overflow sent)
			{
				Report(sent, Lang.Format("$ok_store_storedone", name));
			});
		}

		internal static string SentWords(Overflow sent, string name)
		{
			if (sent.Took.Count == 0)
			{
				return "";
			}
			string text = StoreTargets.Name(sent.Took[0]);
			if (sent.Took.Count == 1)
			{