Decompiled source of OrdemDoArtesao v1.0.3

OrdemDoArtesao.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OrdemDoArtesao")]
[assembly: AssemblyProduct("Ordem do Artesao")]
[assembly: AssemblyCompany("Ordem do Artesao contributors")]
[assembly: AssemblyCopyright("Copyright (c) 2026")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyVersion("1.0.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OrdemDoArtesao
{
	internal enum CraftSortMode
	{
		Default,
		NameAscending,
		NameDescending,
		Category,
		Weight
	}
	internal enum CraftCategoryFilter
	{
		All,
		Weapons,
		Armor,
		Tools,
		Food,
		Materials,
		Other
	}
	internal static class CraftingUiController
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__NextCategory;

			public static UnityAction <1>__NextSort;
		}

		private const float RowHeight = 30f;

		private const float RowGap = 5f;

		private const float QueryDebounceSeconds = 0.12f;

		private const int MaxQueryLength = 60;

		private static object _gui;

		private static GameObject _row;

		private static Component _input;

		private static object _categoryLabel;

		private static object _sortLabel;

		private static RectTransform _listRect;

		private static RectTransform _scrollRect;

		private static Vector2 _originalListOffsetMax;

		private static Vector2 _originalScrollOffsetMax;

		private static string _query = string.Empty;

		private static CraftCategoryFilter _category = CraftCategoryFilter.All;

		private static CraftSortMode _sort = CraftSortMode.Default;

		private static bool _refreshing;

		private static bool _queryRefreshPending;

		private static float _queryRefreshAt;

		private static bool _recipeApplyPending;

		private static object _recipeApplyGui;

		private static Type _refreshGuiType;

		private static MethodInfo _refreshMethod;

		private static object[] _refreshArguments;

		private static int _creationFailures;

		internal static bool IsTyping
		{
			get
			{
				if ((Object)(object)_input == (Object)null)
				{
					return false;
				}
				return ReflectionTools.GetBool(_input, "isFocused");
			}
		}

		internal static void Ensure(object gui)
		{
			if (gui == null || _creationFailures >= 3 || (_gui == gui && (Object)(object)_row != (Object)null))
			{
				return;
			}
			Dispose();
			_gui = gui;
			try
			{
				CreateControls(gui);
				RefreshLabels();
				_creationFailures = 0;
			}
			catch (Exception ex)
			{
				_creationFailures++;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Os controles do crafting nao puderam ser criados nesta versao: " + ex));
				}
				Dispose();
			}
		}

		internal static void ScheduleRecipeList(object gui)
		{
			if (_gui == gui && (_sort != CraftSortMode.Default || _category != CraftCategoryFilter.All || !string.IsNullOrWhiteSpace(_query)))
			{
				_recipeApplyGui = gui;
				_recipeApplyPending = true;
			}
		}

		internal static void ApplyPendingRecipeList()
		{
			if (_recipeApplyPending)
			{
				object recipeApplyGui = _recipeApplyGui;
				_recipeApplyPending = false;
				_recipeApplyGui = null;
				if (_gui == recipeApplyGui)
				{
					RecipeListAdapter.Apply(recipeApplyGui, _sort, _category, _query);
				}
			}
		}

		internal static void Tick()
		{
			if (_queryRefreshPending && _gui != null && !_refreshing && !(Time.unscaledTime < _queryRefreshAt))
			{
				RequestRefresh();
			}
		}

		internal static void RefreshLabels()
		{
			SetText(_categoryLabel, CategoryLabel(_category));
			SetText(_sortLabel, SortLabel(_sort));
		}

		internal static void ClearSearch()
		{
			_queryRefreshPending = false;
			if (string.IsNullOrEmpty(_query) && (Object)(object)_input == (Object)null)
			{
				return;
			}
			_query = string.Empty;
			if ((Object)(object)_input != (Object)null)
			{
				MethodInfo methodInfo = ReflectionTools.FindCompatibleMethod(((object)_input).GetType(), "SetTextWithoutNotify", new object[1] { string.Empty });
				if (methodInfo != null)
				{
					methodInfo.Invoke(_input, new object[1] { string.Empty });
				}
				else
				{
					ReflectionTools.Set(_input, "text", string.Empty);
				}
				ReflectionTools.Invoke(_input, "DeactivateInputField");
			}
		}

		internal static void Dispose()
		{
			//IL_0012: 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)
			if ((Object)(object)_listRect != (Object)null)
			{
				_listRect.offsetMax = _originalListOffsetMax;
			}
			if ((Object)(object)_scrollRect != (Object)null)
			{
				_scrollRect.offsetMax = _originalScrollOffsetMax;
			}
			if ((Object)(object)_row != (Object)null)
			{
				Object.Destroy((Object)(object)_row);
			}
			_gui = null;
			_row = null;
			_input = null;
			_categoryLabel = null;
			_sortLabel = null;
			_listRect = null;
			_scrollRect = null;
			_refreshing = false;
			_queryRefreshPending = false;
			_recipeApplyPending = false;
			_recipeApplyGui = null;
			_refreshGuiType = null;
			_refreshMethod = null;
			_refreshArguments = null;
		}

		private static void CreateControls(object gui)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Expected O, but got Unknown
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Expected O, but got Unknown
			RectTransform val = ReflectionTools.AsRectTransform(ReflectionTools.Get(gui, "m_recipeListRoot"));
			_listRect = (RectTransform)(((Object)(object)val == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
			RectTransform val2 = (RectTransform)(((Object)(object)_listRect == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
			if ((Object)(object)_listRect == (Object)null || (Object)(object)val2 == (Object)null)
			{
				throw new MissingMemberException("A area da lista de receitas nao foi encontrada.");
			}
			_originalListOffsetMax = _listRect.offsetMax;
			_row = new GameObject("OrdemDoArtesao.CraftingRow", new Type[1] { typeof(RectTransform) });
			RectTransform val3 = (RectTransform)_row.transform;
			((Transform)val3).SetParent((Transform)(object)val2, false);
			val3.anchorMin = new Vector2(_listRect.anchorMin.x, _listRect.anchorMax.y);
			val3.anchorMax = _listRect.anchorMax;
			val3.pivot = new Vector2(0.5f, 1f);
			val3.offsetMin = new Vector2(_listRect.offsetMin.x, _listRect.offsetMax.y - 30f);
			val3.offsetMax = _listRect.offsetMax;
			_listRect.offsetMax = new Vector2(_listRect.offsetMax.x, _listRect.offsetMax.y - 30f - 5f);
			_scrollRect = ReflectionTools.AsRectTransform(ReflectionTools.Get(gui, "m_recipeListScroll"));
			if ((Object)(object)_scrollRect != (Object)null && (Object)(object)((Transform)_scrollRect).parent == (Object)(object)val2)
			{
				_originalScrollOffsetMax = _scrollRect.offsetMax;
				_scrollRect.offsetMax = new Vector2(_scrollRect.offsetMax.x, _scrollRect.offsetMax.y - 30f - 5f);
			}
			else
			{
				_scrollRect = null;
			}
			object font = ReflectionTools.Get(ReflectionTools.Get(gui, "m_recipeName"), "font");
			_input = CreateSearchInput(val3, font);
			SetStretch((RectTransform)_input.transform, 0f, 0.52f, 0f, -4f);
			GameObject obj = ReflectionTools.AsGameObject(ReflectionTools.Get(gui, "m_stackAllButton"));
			if ((Object)(object)obj == (Object)null)
			{
				throw new MissingMemberException("Botao-base do inventario nao encontrado.");
			}
			object obj2 = <>O.<0>__NextCategory;
			if (obj2 == null)
			{
				UnityAction val4 = NextCategory;
				<>O.<0>__NextCategory = val4;
				obj2 = (object)val4;
			}
			_categoryLabel = CreateButton(obj, val3, "FiltroCategoria", 0.52f, 0.76f, (UnityAction)obj2, ModText.Get("Filtrar receitas por categoria", "Filter recipes by category"));
			object obj3 = <>O.<1>__NextSort;
			if (obj3 == null)
			{
				UnityAction val5 = NextSort;
				<>O.<1>__NextSort = val5;
				obj3 = (object)val5;
			}
			_sortLabel = CreateButton(obj, val3, "OrdemReceitas", 0.76f, 1f, (UnityAction)obj3, ModText.Get("Alternar a ordem da lista de receitas", "Change recipe list sorting"));
		}

		private static Component CreateSearchInput(RectTransform row, object font)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			Type type = ReflectionTools.FindType("TMPro.TMP_InputField");
			Type type2 = ReflectionTools.FindType("TMPro.TextMeshProUGUI");
			if (type == null || type2 == null)
			{
				throw new TypeLoadException("TextMeshPro nao esta disponivel.");
			}
			GameObject val = new GameObject("BuscaReceitas", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)row, false);
			Image val3 = val.AddComponent<Image>();
			Sprite val4 = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite candidate) => (Object)(object)candidate != (Object)null && ((Object)candidate).name == "text_field"));
			if ((Object)(object)val4 != (Object)null)
			{
				val3.sprite = val4;
				val3.type = (Type)1;
				((Graphic)val3).color = Color.white;
			}
			else
			{
				((Graphic)val3).color = new Color(0f, 0f, 0f, 0.68f);
			}
			RectTransform component = new GameObject("TextArea", new Type[2]
			{
				typeof(RectTransform),
				typeof(RectMask2D)
			}).GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)val2, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = new Vector2(8f, 2f);
			component.offsetMax = new Vector2(-8f, -2f);
			Component value = CreateTmpText(component, type2, "Placeholder", font, ModText.Get("Buscar nome ou ID...", "Search name or ID..."), new Color(0.8529f, 0.725f, 0.5331f, 0.5f), italic: true);
			Component value2 = CreateTmpText(component, type2, "Text", font, string.Empty, new Color(0.8529f, 0.725f, 0.5331f, 1f), italic: false);
			Component val5 = val.AddComponent(type);
			ReflectionTools.Set(val5, "textViewport", component);
			ReflectionTools.Set(val5, "textComponent", value2);
			ReflectionTools.Set(val5, "placeholder", value);
			ReflectionTools.Set(val5, "characterLimit", 60);
			ReflectionTools.Set(val5, "caretColor", (object)new Color(1f, 0.631f, 0.235f, 1f));
			ReflectionTools.Set(val5, "selectionColor", (object)new Color(1f, 0.631f, 0.235f, 0.35f));
			ReflectionTools.Set(val5, "targetGraphic", val3);
			if (font != null)
			{
				ReflectionTools.Set(val5, "fontAsset", font);
			}
			ReflectionTools.Set(val5, "pointSize", 16f);
			ReflectionTools.SetEnumProperty(val5, "lineType", "SingleLine");
			object obj = ReflectionTools.Get(val5, "onValueChanged");
			MethodInfo? obj2 = obj?.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo method) => method.Name == "AddListener" && method.GetParameters().Length == 1);
			if (obj2 == null)
			{
				throw new MissingMethodException("TMP_InputField.onValueChanged.AddListener");
			}
			obj2.Invoke(obj, new object[1]
			{
				new UnityAction<string>(OnQueryChanged)
			});
			return val5;
		}

		private static Component CreateTmpText(RectTransform parent, Type textType, string name, object font, string value, Color color, bool italic)
		{
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			Component val3 = val.AddComponent(textType);
			ReflectionTools.Set(val3, "text", value);
			ReflectionTools.Set(val3, "fontSize", 16f);
			ReflectionTools.Set(val3, "color", color);
			ReflectionTools.Set(val3, "raycastTarget", false);
			ReflectionTools.Set(val3, "enableWordWrapping", false);
			if (font != null)
			{
				ReflectionTools.Set(val3, "font", font);
			}
			ReflectionTools.SetEnumProperty(val3, "alignment", "Left");
			ReflectionTools.SetEnumProperty(val3, "overflowMode", "Ellipsis");
			if (italic)
			{
				ReflectionTools.SetEnumProperty(val3, "fontStyle", "Italic");
			}
			return val3;
		}

		private static object CreateButton(GameObject source, RectTransform parent, string name, float minX, float maxX, UnityAction action, string tooltip)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = Object.Instantiate<GameObject>(source, (Transform)(object)parent);
			((Object)obj).name = "OrdemDoArtesao." + name;
			obj.SetActive(true);
			RemoveLocalization(obj);
			HideGamepadHints(obj);
			Transform transform = obj.transform;
			SetStretch((RectTransform)(object)((transform is RectTransform) ? transform : null), minX, maxX, 2f, -2f);
			Button component = obj.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				throw new MissingComponentException("Button");
			}
			((UnityEventBase)component.onClick).RemoveAllListeners();
			((UnityEvent)component.onClick).AddListener(action);
			((Selectable)component).interactable = true;
			SetTooltip(obj, tooltip);
			return FindTmpText(obj);
		}

		private static void NextCategory()
		{
			Array values = Enum.GetValues(typeof(CraftCategoryFilter));
			_category = (CraftCategoryFilter)((int)(_category + 1) % values.Length);
			RefreshLabels();
			RequestRefresh();
		}

		private static void NextSort()
		{
			Array values = Enum.GetValues(typeof(CraftSortMode));
			_sort = (CraftSortMode)((int)(_sort + 1) % values.Length);
			RefreshLabels();
			RequestRefresh();
		}

		private static void OnQueryChanged(string value)
		{
			_query = value ?? string.Empty;
			_queryRefreshPending = true;
			_queryRefreshAt = Time.unscaledTime + 0.12f;
		}

		private static void RequestRefresh()
		{
			_queryRefreshPending = false;
			if (_gui == null || _refreshing)
			{
				return;
			}
			_refreshing = true;
			try
			{
				ResolveRefreshMethod();
				if (_refreshMethod != null)
				{
					_refreshMethod.Invoke(_gui, _refreshArguments);
				}
			}
			finally
			{
				_refreshing = false;
			}
		}

		private static void ResolveRefreshMethod()
		{
			Type type = _gui.GetType();
			if ((object)_refreshGuiType == type)
			{
				return;
			}
			_refreshGuiType = type;
			_refreshMethod = (from method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where method.Name == "UpdateCraftingPanel" && method.GetParameters().All((ParameterInfo parameter) => parameter.ParameterType == typeof(bool))
				orderby method.GetParameters().Length descending
				select method).FirstOrDefault();
			if (_refreshMethod == null)
			{
				_refreshMethod = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo method) => method.Name == "UpdateRecipeList");
			}
			_refreshArguments = ((_refreshMethod == null) ? null : (from parameter in _refreshMethod.GetParameters()
				select (!parameter.ParameterType.IsValueType) ? null : Activator.CreateInstance(parameter.ParameterType)).ToArray());
		}

		private static string CategoryLabel(CraftCategoryFilter category)
		{
			return ModText.Category(category);
		}

		private static string SortLabel(CraftSortMode mode)
		{
			return ModText.Sort(mode);
		}

		private static void SetStretch(RectTransform rect, float minX, float maxX, float left, float right)
		{
			//IL_0007: 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_002d: 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_0050: 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)
			rect.anchorMin = new Vector2(minX, 0f);
			rect.anchorMax = new Vector2(maxX, 1f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.offsetMin = new Vector2(left, 0f);
			rect.offsetMax = new Vector2(right, 0f);
			((Transform)rect).localScale = Vector3.one;
		}

		internal static object FindTmpText(GameObject root)
		{
			Type type = ReflectionTools.FindType("TMPro.TMP_Text");
			if (!(type == null))
			{
				return root.GetComponentInChildren(type, true);
			}
			return null;
		}

		internal static void SetText(object label, string value)
		{
			ReflectionTools.Set(label, "text", value);
			ReflectionTools.Set(label, "fontSize", 14f);
		}

		internal static void RemoveLocalization(GameObject root)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Type type = ReflectionTools.FindType("Localize");
			if (type == null)
			{
				return;
			}
			foreach (Object componentsInChild in ReflectionTools.GetComponentsInChildren(root, type))
			{
				Object.DestroyImmediate(componentsInChild);
			}
		}

		internal static void HideGamepadHints(GameObject root)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			foreach (Transform item in root.transform)
			{
				Transform val = item;
				if (((Object)val).name.StartsWith("gamepad_hint", StringComparison.OrdinalIgnoreCase))
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		internal static void SetTooltip(GameObject root, string value)
		{
			Type type = ReflectionTools.FindType("UITooltip");
			Component val = ((type == null) ? null : root.GetComponent(type));
			if ((Object)(object)val != (Object)null)
			{
				ReflectionTools.Set(val, "m_text", value);
			}
		}
	}
	internal static class InventoryButtons
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Predicate<GameObject> <>9__6_0;

			public static UnityAction <>9__6_1;

			public static UnityAction <>9__6_2;

			public static UnityAction <>9__6_3;

			public static UnityAction <>9__6_4;

			internal bool <Ensure>b__6_0(GameObject button)
			{
				return (Object)(object)button != (Object)null;
			}

			internal void <Ensure>b__6_1()
			{
				InventoryActions.OrganizeContainer(_gui, OrganizeMode.Alphabetical);
			}

			internal void <Ensure>b__6_2()
			{
				InventoryActions.OrganizeContainer(_gui, OrganizeMode.Stacks);
			}

			internal void <Ensure>b__6_3()
			{
				InventoryActions.OrganizePlayer(_gui, OrganizeMode.Alphabetical);
			}

			internal void <Ensure>b__6_4()
			{
				InventoryActions.OrganizePlayer(_gui, OrganizeMode.Stacks);
			}
		}

		private const float ButtonWidth = 64f;

		private const float ButtonHeight = 28f;

		private const float Gap = 4f;

		private static readonly List<GameObject> Buttons = new List<GameObject>();

		private static object _gui;

		private static int _creationFailures;

		internal static void Ensure(object gui)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Expected O, but got Unknown
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Expected O, but got Unknown
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Expected O, but got Unknown
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			if (gui == null || _creationFailures >= 3 || (gui == _gui && Buttons.Count == 4 && Buttons.TrueForAll((GameObject button) => (Object)(object)button != (Object)null)))
			{
				return;
			}
			Dispose();
			_gui = gui;
			try
			{
				GameObject val = ReflectionTools.AsGameObject(ReflectionTools.Get(gui, "m_stackAllButton"));
				RectTransform val2 = (RectTransform)(((Object)(object)val == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
				RectTransform val3 = ReflectionTools.AsRectTransform(ReflectionTools.Get(gui, "m_playerGrid"));
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)((Transform)val3).parent == (Object)null)
				{
					throw new MissingMemberException("Botoes-base ou grade do jogador nao encontrados.");
				}
				Transform parent = ((Transform)val2).parent;
				Transform parent2 = ((parent is RectTransform) ? parent : null);
				object obj = <>c.<>9__6_1;
				if (obj == null)
				{
					UnityAction val4 = delegate
					{
						InventoryActions.OrganizeContainer(_gui, OrganizeMode.Alphabetical);
					};
					<>c.<>9__6_1 = val4;
					obj = (object)val4;
				}
				GameObject val5 = CloneButton(val, (RectTransform)(object)parent2, "BauAZ", "A-Z", (UnityAction)obj, ModText.Get("Organizar este baú em ordem alfabética", "Sort this chest alphabetically"));
				Buttons.Add(val5);
				Transform parent3 = ((Transform)val2).parent;
				Transform parent4 = ((parent3 is RectTransform) ? parent3 : null);
				string label = ModText.Get("Pilhas", "Stacks");
				object obj2 = <>c.<>9__6_2;
				if (obj2 == null)
				{
					UnityAction val6 = delegate
					{
						InventoryActions.OrganizeContainer(_gui, OrganizeMode.Stacks);
					};
					<>c.<>9__6_2 = val6;
					obj2 = (object)val6;
				}
				GameObject val7 = CloneButton(val, (RectTransform)(object)parent4, "BauPilhas", label, (UnityAction)obj2, ModText.Get("Juntar pilhas compatíveis e organizar este baú", "Merge compatible stacks and organize this chest"));
				Buttons.Add(val7);
				PlaceBeside(val2, (RectTransform)val5.transform, 0);
				PlaceBeside(val2, (RectTransform)val7.transform, 1);
				Transform parent5 = ((Transform)val3).parent;
				RectTransform parent6 = (RectTransform)(object)((parent5 is RectTransform) ? parent5 : null);
				object obj3 = <>c.<>9__6_3;
				if (obj3 == null)
				{
					UnityAction val8 = delegate
					{
						InventoryActions.OrganizePlayer(_gui, OrganizeMode.Alphabetical);
					};
					<>c.<>9__6_3 = val8;
					obj3 = (object)val8;
				}
				GameObject val9 = CloneButton(val, parent6, "InventarioAZ", "A-Z", (UnityAction)obj3, ModText.Get("Organizar o inventário (preserva atalhos, equipados e slots bloqueados). Alt+L sobre um slot: bloquear/desbloquear", "Organize inventory (preserves hotbar, equipped items and locked slots). Hover a slot and press Alt+L to lock/unlock"));
				Buttons.Add(val9);
				string label2 = ModText.Get("Pilhas", "Stacks");
				object obj4 = <>c.<>9__6_4;
				if (obj4 == null)
				{
					UnityAction val10 = delegate
					{
						InventoryActions.OrganizePlayer(_gui, OrganizeMode.Stacks);
					};
					<>c.<>9__6_4 = val10;
					obj4 = (object)val10;
				}
				GameObject val11 = CloneButton(val, parent6, "InventarioPilhas", label2, (UnityAction)obj4, ModText.Get("Juntar pilhas e organizar (preserva atalhos, equipados e slots bloqueados). Alt+L: bloquear/desbloquear", "Merge stacks and organize (preserves hotbar, equipped items and locked slots). Alt+L: lock/unlock"));
				Buttons.Add(val11);
				PlaceAboveGrid(val3, (RectTransform)val9.transform, 1);
				PlaceAboveGrid(val3, (RectTransform)val11.transform, 0);
				_creationFailures = 0;
			}
			catch (Exception ex)
			{
				_creationFailures++;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Os botoes de organizacao nao puderam ser criados; F6/F7 continuam disponiveis. " + ex));
				}
				Dispose();
			}
		}

		internal static void Dispose()
		{
			foreach (GameObject button in Buttons)
			{
				if ((Object)(object)button != (Object)null)
				{
					Object.Destroy((Object)(object)button);
				}
			}
			Buttons.Clear();
			_gui = null;
		}

		private static GameObject CloneButton(GameObject source, RectTransform parent, string name, string label, UnityAction action, string tooltip)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null)
			{
				throw new MissingComponentException("RectTransform pai");
			}
			GameObject obj = Object.Instantiate<GameObject>(source, (Transform)(object)parent);
			((Object)obj).name = "OrdemDoArtesao." + name;
			obj.SetActive(true);
			obj.transform.SetAsLastSibling();
			CraftingUiController.RemoveLocalization(obj);
			CraftingUiController.HideGamepadHints(obj);
			CraftingUiController.SetTooltip(obj, tooltip);
			Button component = obj.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				throw new MissingComponentException("Button");
			}
			((UnityEventBase)component.onClick).RemoveAllListeners();
			((UnityEvent)component.onClick).AddListener(action);
			((Selectable)component).interactable = true;
			CraftingUiController.SetText(CraftingUiController.FindTmpText(obj), label);
			return obj;
		}

		private static void PlaceBeside(RectTransform source, RectTransform button, int index)
		{
			//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_001d: 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)
			//IL_002d: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = source.rect;
			float num;
			if (!(((Rect)(ref rect)).height > 8f))
			{
				num = 28f;
			}
			else
			{
				rect = source.rect;
				num = ((Rect)(ref rect)).height;
			}
			float num2 = num;
			button.anchorMin = source.anchorMin;
			button.anchorMax = source.anchorMax;
			button.pivot = new Vector2(0f, source.pivot.y);
			button.sizeDelta = new Vector2(64f, num2);
			float x = source.anchoredPosition.x;
			float num3 = 1f - source.pivot.x;
			rect = source.rect;
			float num4 = x + num3 * ((Rect)(ref rect)).width;
			button.anchoredPosition = new Vector2(num4 + 4f + (float)index * 68f, source.anchoredPosition.y);
			((Transform)button).localScale = Vector3.one;
		}

		private static void PlaceAboveGrid(RectTransform grid, RectTransform button, int indexFromRight)
		{
			//IL_001d: 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)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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)
			Transform parent = ((Transform)grid).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			grid.GetWorldCorners(array);
			Vector3 val2 = ((Transform)val).InverseTransformPoint(array[2]);
			button.anchorMin = Vector2.zero;
			button.anchorMax = Vector2.zero;
			button.pivot = new Vector2(1f, 0f);
			button.sizeDelta = new Vector2(64f, 28f);
			float x = val2.x;
			Rect rect = val.rect;
			float num = x - ((Rect)(ref rect)).xMin - (float)indexFromRight * 68f + Plugin.Instance.PlayerButtonsOffsetX.Value;
			float y = val2.y;
			rect = val.rect;
			button.anchoredPosition = new Vector2(num, y - ((Rect)(ref rect)).yMin + Plugin.Instance.PlayerButtonsOffsetY.Value);
			((Transform)button).localScale = Vector3.one;
		}
	}
	internal enum OrganizeMode
	{
		Alphabetical,
		Stacks
	}
	internal enum ItemCategory
	{
		Weapons,
		Armor,
		Tools,
		Food,
		Materials,
		Other
	}
	internal struct GridPosition
	{
		internal readonly int X;

		internal readonly int Y;

		internal GridPosition(int x, int y)
		{
			X = x;
			Y = y;
		}

		internal int Key(int width)
		{
			return Y * width + X;
		}
	}
	internal static class ItemIdentity
	{
		private sealed class ItemMetadata
		{
			internal static readonly ItemMetadata Empty = new ItemMetadata
			{
				NameToken = string.Empty,
				InternalId = string.Empty,
				Category = ItemCategory.Other
			};

			internal string NameToken;

			internal string InternalId;

			internal ItemCategory Category;

			internal float Weight;
		}

		private static readonly object TypeCacheLock = new object();

		private static readonly Dictionary<Type, bool> ItemDataTypeCache = new Dictionary<Type, bool>();

		private static readonly ConditionalWeakTable<object, ItemMetadata> MetadataCache = new ConditionalWeakTable<object, ItemMetadata>();

		internal static bool IsItemData(object value)
		{
			Type type = value?.GetType();
			if (type == null)
			{
				return false;
			}
			lock (TypeCacheLock)
			{
				if (ItemDataTypeCache.TryGetValue(type, out var value2))
				{
					return value2;
				}
			}
			Type type2 = type;
			bool flag = false;
			while (type2 != null)
			{
				if (string.Equals(type2.FullName, "ItemDrop+ItemData", StringComparison.Ordinal))
				{
					flag = true;
					break;
				}
				type2 = type2.BaseType;
			}
			lock (TypeCacheLock)
			{
				ItemDataTypeCache[type] = flag;
				return flag;
			}
		}

		internal static string GetNameToken(object item)
		{
			return GetMetadata(item).NameToken;
		}

		internal static string GetDisplayName(object item)
		{
			return LocalizedText.FromToken(GetNameToken(item));
		}

		internal static string GetInternalId(object item)
		{
			if (item == null)
			{
				return string.Empty;
			}
			return GetMetadata(item).InternalId;
		}

		internal static ItemCategory GetCategory(object item)
		{
			return GetMetadata(item).Category;
		}

		internal static string GetCategoryLabel(ItemCategory category)
		{
			return ModText.Category(category);
		}

		internal static float GetWeight(object item)
		{
			return GetMetadata(item).Weight;
		}

		internal static string GetTooltipLine(object item)
		{
			ItemMetadata metadata = GetMetadata(item);
			if (string.IsNullOrEmpty(metadata.InternalId))
			{
				return string.Empty;
			}
			return "<color=#8F9AA3><size=80%>" + ModText.Get("ID interno: ", "Internal ID: ") + metadata.InternalId + "</size></color>";
		}

		private static ItemMetadata GetMetadata(object item)
		{
			if (item != null)
			{
				return MetadataCache.GetValue(item, CreateMetadata);
			}
			return ItemMetadata.Empty;
		}

		private static ItemMetadata CreateMetadata(object item)
		{
			object instance = ReflectionTools.Get(item, "m_shared");
			string text = (ReflectionTools.Get(instance, "m_name") as string) ?? string.Empty;
			object obj = ReflectionTools.Get(item, "m_dropPrefab");
			GameObject val = ReflectionTools.AsGameObject(obj);
			string text2 = (((Object)(object)val == (Object)null) ? null : ((Object)val).name);
			if (string.IsNullOrEmpty(text2) && obj != null)
			{
				text2 = ReflectionTools.Get(obj, "name") as string;
			}
			text2 = (string.IsNullOrEmpty(text2) ? (string.IsNullOrEmpty(text) ? item.GetType().Name : text.TrimStart(new char[1] { '$' })) : text2.Replace("(Clone)", string.Empty).Trim());
			string type = ReflectionTools.Get(instance, "m_itemType")?.ToString() ?? string.Empty;
			return new ItemMetadata
			{
				NameToken = text,
				InternalId = text2,
				Category = ParseCategory(type),
				Weight = ReflectionTools.GetFloat(instance, "m_weight")
			};
		}

		private static ItemCategory ParseCategory(string type)
		{
			switch (type)
			{
			case "OneHandedWeapon":
			case "TwoHandedWeapon":
			case "Ammo":
			case "Torch":
			case "Attach_Atgeir":
			case "TwoHandedWeaponLeft":
			case "Bow":
			case "AmmoNonEquipable":
				return ItemCategory.Weapons;
			case "Legs":
			case "Chest":
			case "Hands":
			case "Helmet":
			case "Shield":
			case "Shoulder":
			case "Utility":
				return ItemCategory.Armor;
			case "Tool":
			case "FishingRod":
				return ItemCategory.Tools;
			case "Fish":
			case "Consumable":
				return ItemCategory.Food;
			case "Customization":
			case "Material":
			case "Trophie":
				return ItemCategory.Materials;
			default:
				return ItemCategory.Other;
			}
		}
	}
	internal static class InventoryOrganizer
	{
		private sealed class SortEntry
		{
			internal object Item;

			internal int OriginalIndex;

			internal ItemCategory Category;

			internal string DisplayName;

			internal string InternalId;

			internal int Quality;

			internal int Variant;

			internal int Stack;
		}

		private sealed class StackState
		{
			internal object Item;

			internal int OriginalStack;

			internal int Stack;

			internal int MaxStack;
		}

		private sealed class ItemSnapshot
		{
			internal object Item;

			internal int Stack;

			internal object Position;
		}

		private sealed class PositionAccessor
		{
			internal FieldInfo Field;

			internal ConstructorInfo Constructor;
		}

		private sealed class ChangeNotifier
		{
			internal MethodInfo Method;

			internal object[] Arguments;
		}

		private struct MergeResult
		{
			internal bool Changed;

			internal int Emptied;
		}

		private static readonly object CacheLock = new object();

		private static readonly Dictionary<Type, PositionAccessor> PositionAccessors = new Dictionary<Type, PositionAccessor>();

		private static readonly Dictionary<Type, ChangeNotifier> ChangeNotifiers = new Dictionary<Type, ChangeNotifier>();

		private static readonly StringComparer DisplayNameComparer = StringComparer.CurrentCultureIgnoreCase;

		private static readonly StringComparer InternalIdComparer = StringComparer.OrdinalIgnoreCase;

		internal static bool Organize(object inventory, bool playerInventory, OrganizeMode mode, out string summary)
		{
			summary = string.Empty;
			if (inventory == null)
			{
				summary = "inventario ausente";
				return false;
			}
			IList list = ReflectionTools.AsList(ReflectionTools.Get(inventory, "m_inventory"));
			if (list == null)
			{
				summary = "lista de itens nao encontrada";
				return false;
			}
			List<object> list2 = new List<object>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i] != null)
				{
					list2.Add(list[i]);
				}
			}
			if (list2.Count == 0)
			{
				summary = "inventario vazio";
				return true;
			}
			int num = ReadDimension(inventory, "GetWidth", 8);
			int num2 = ReadDimension(inventory, "GetHeight", 4);
			if (num <= 0 || num2 <= 0)
			{
				summary = "dimensoes invalidas";
				return false;
			}
			HashSet<int> hashSet = new HashSet<int>();
			List<object> list3 = new List<object>(list2.Count);
			Plugin instance = Plugin.Instance;
			if (playerInventory && (Object)(object)instance != (Object)null && instance.PreserveHotbar.Value)
			{
				for (int j = 0; j < num; j++)
				{
					hashSet.Add(j);
				}
			}
			if (playerInventory && (Object)(object)instance != (Object)null && instance.PreserveSpecialSlots.Value)
			{
				for (int k = SpecialSlotCompatibility.GetSortableRows(num2); k < num2; k++)
				{
					for (int l = 0; l < num; l++)
					{
						hashSet.Add(k * num + l);
					}
				}
			}
			if (playerInventory)
			{
				SlotLockRegistry.ReserveInside(num, num2, hashSet);
			}
			foreach (object item4 in list2)
			{
				GridPosition gridPosition = GetGridPosition(item4);
				bool flag = gridPosition.X < 0 || gridPosition.X >= num || gridPosition.Y < 0 || gridPosition.Y >= num2;
				bool flag2 = !flag && hashSet.Contains(gridPosition.Key(num));
				if (flag || flag2 || (playerInventory && ShouldPreservePlayerItem(item4)))
				{
					if (!flag)
					{
						hashSet.Add(gridPosition.Key(num));
					}
				}
				else
				{
					list3.Add(item4);
				}
			}
			List<GridPosition> list4 = new List<GridPosition>(Math.Max(0, num * num2 - hashSet.Count));
			for (int m = 0; m < num2; m++)
			{
				for (int n = 0; n < num; n++)
				{
					GridPosition item = new GridPosition(n, m);
					if (!hashSet.Contains(item.Key(num)))
					{
						list4.Add(item);
					}
				}
			}
			if (list3.Count > list4.Count)
			{
				summary = "nao ha posicoes livres suficientes sem mover slots protegidos";
				return false;
			}
			List<ItemSnapshot> snapshot = CreateSnapshot(list2);
			MergeResult mergeResult = default(MergeResult);
			try
			{
				if (mode == OrganizeMode.Stacks)
				{
					mergeResult = MergeCompatibleStacks(list, list3);
				}
				List<SortEntry> list5 = new List<SortEntry>(list3.Count);
				for (int num3 = 0; num3 < list3.Count; num3++)
				{
					object item2 = list3[num3];
					list5.Add(new SortEntry
					{
						Item = item2,
						OriginalIndex = num3,
						Category = ItemIdentity.GetCategory(item2),
						DisplayName = ItemIdentity.GetDisplayName(item2),
						InternalId = ItemIdentity.GetInternalId(item2),
						Quality = GetQuality(item2),
						Variant = GetVariant(item2),
						Stack = GetStack(item2)
					});
				}
				list5.Sort((mode == OrganizeMode.Alphabetical) ? new Comparison<SortEntry>(CompareAlphabetical) : new Comparison<SortEntry>(CompareStacks));
				if (list5.Count > list4.Count)
				{
					throw new InvalidOperationException("a lista organizada excedeu os slots livres");
				}
				bool flag3 = false;
				for (int num4 = 0; num4 < list5.Count; num4++)
				{
					object item3 = list5[num4].Item;
					GridPosition position = list4[num4];
					GridPosition gridPosition2 = GetGridPosition(item3);
					if (gridPosition2.X != position.X || gridPosition2.Y != position.Y)
					{
						SetGridPosition(item3, position);
						flag3 = true;
					}
				}
				if (flag3 || mergeResult.Changed)
				{
					NotifyChanged(inventory);
				}
				summary = ((mode == OrganizeMode.Stacks) ? $"{list5.Count} itens organizados; {mergeResult.Emptied} pilhas esvaziadas" : $"{list5.Count} itens organizados em A-Z");
				return true;
			}
			catch
			{
				Restore(list, snapshot);
				NotifyChanged(inventory);
				throw;
			}
		}

		private static bool ShouldPreservePlayerItem(object item)
		{
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			if (instance.PreserveEquipped.Value)
			{
				if (!ReflectionTools.GetBool(item, "m_equiped"))
				{
					return ReflectionTools.GetBool(item, "m_equipped");
				}
				return true;
			}
			return false;
		}

		private static MergeResult MergeCompatibleStacks(IList rawItems, List<object> movable)
		{
			Dictionary<string, List<StackState>> dictionary = new Dictionary<string, List<StackState>>(StringComparer.Ordinal);
			List<StackState> list = new List<StackState>();
			foreach (object item in movable)
			{
				int maxStack = GetMaxStack(item);
				if (maxStack > 1 && HasNoCustomData(item))
				{
					StackState stackState = new StackState
					{
						Item = item,
						OriginalStack = GetStack(item),
						MaxStack = maxStack
					};
					stackState.Stack = stackState.OriginalStack;
					list.Add(stackState);
					string key = StackKey(item, maxStack);
					if (!dictionary.TryGetValue(key, out var value))
					{
						value = new List<StackState>();
						dictionary.Add(key, value);
					}
					value.Add(stackState);
				}
			}
			bool changed = false;
			foreach (List<StackState> value2 in dictionary.Values)
			{
				if (value2.Count < 2)
				{
					continue;
				}
				value2.Sort((StackState left, StackState right) => right.Stack.CompareTo(left.Stack));
				int num = 0;
				for (int num2 = value2.Count - 1; num2 > num; num2--)
				{
					StackState stackState2 = value2[num2];
					while (stackState2.Stack > 0 && num < num2)
					{
						StackState stackState3 = value2[num];
						int num3 = stackState3.MaxStack - stackState3.Stack;
						if (num3 <= 0)
						{
							num++;
							continue;
						}
						int num4 = Math.Min(num3, stackState2.Stack);
						stackState3.Stack += num4;
						stackState2.Stack -= num4;
						changed = true;
					}
				}
			}
			HashSet<object> removed = new HashSet<object>();
			foreach (StackState item2 in list)
			{
				if (item2.Stack != item2.OriginalStack)
				{
					SetStack(item2.Item, item2.Stack);
				}
				if (item2.Stack <= 0)
				{
					removed.Add(item2.Item);
				}
			}
			foreach (object item3 in removed)
			{
				rawItems.Remove(item3);
			}
			if (removed.Count > 0)
			{
				movable.RemoveAll((object item) => removed.Contains(item));
			}
			return new MergeResult
			{
				Changed = changed,
				Emptied = removed.Count
			};
		}

		private static string StackKey(object item, int maxStack)
		{
			return string.Join("|", ItemIdentity.GetInternalId(item), ItemIdentity.GetNameToken(item), GetQuality(item).ToString(CultureInfo.InvariantCulture), GetVariant(item).ToString(CultureInfo.InvariantCulture), maxStack.ToString(CultureInfo.InvariantCulture), ReflectionTools.GetInt(item, "m_worldLevel").ToString(CultureInfo.InvariantCulture), ReflectionTools.Get(item, "m_crafterID")?.ToString() ?? string.Empty, (ReflectionTools.Get(item, "m_crafterName") as string) ?? string.Empty);
		}

		private static bool HasNoCustomData(object item)
		{
			object obj = ReflectionTools.Get(item, "m_customData");
			if (obj == null)
			{
				return true;
			}
			if (obj is IDictionary dictionary)
			{
				return dictionary.Count == 0;
			}
			if (ReflectionTools.Get(obj, "Count") is int num)
			{
				return num == 0;
			}
			return false;
		}

		private static int GetMaxStack(object item)
		{
			return Math.Max(1, ReflectionTools.GetInt(ReflectionTools.Get(item, "m_shared"), "m_maxStackSize", 1));
		}

		private static int GetStack(object item)
		{
			return Math.Max(0, ReflectionTools.GetInt(item, "m_stack", 1));
		}

		private static void SetStack(object item, int amount)
		{
			ReflectionTools.Set(item, "m_stack", amount);
		}

		private static int GetQuality(object item)
		{
			return ReflectionTools.GetInt(item, "m_quality", 1);
		}

		private static int GetVariant(object item)
		{
			return ReflectionTools.GetInt(item, "m_variant");
		}

		private static int ReadDimension(object inventory, string methodName, int fallback)
		{
			try
			{
				return (ReflectionTools.Invoke(inventory, methodName) is int num) ? num : fallback;
			}
			catch
			{
				return fallback;
			}
		}

		private static GridPosition GetGridPosition(object item)
		{
			object instance = ReflectionTools.Get(item, "m_gridPos");
			return new GridPosition(ReflectionTools.GetInt(instance, "x", -1), ReflectionTools.GetInt(instance, "y", -1));
		}

		private static void SetGridPosition(object item, GridPosition position)
		{
			PositionAccessor positionAccessor = GetPositionAccessor(item.GetType());
			Type fieldType = positionAccessor.Field.FieldType;
			object obj;
			if (positionAccessor.Constructor != null)
			{
				obj = positionAccessor.Constructor.Invoke(new object[2] { position.X, position.Y });
			}
			else
			{
				obj = Activator.CreateInstance(fieldType);
				if (!ReflectionTools.Set(obj, "x", position.X) || !ReflectionTools.Set(obj, "y", position.Y))
				{
					throw new MissingFieldException(fieldType.FullName, "x/y");
				}
			}
			positionAccessor.Field.SetValue(item, obj);
		}

		private static void NotifyChanged(object inventory)
		{
			ChangeNotifier changeNotifier = GetChangeNotifier(inventory.GetType());
			if (changeNotifier.Method != null)
			{
				changeNotifier.Method.Invoke(inventory, changeNotifier.Arguments);
			}
			else
			{
				(ReflectionTools.Get(inventory, "m_onChanged") as Delegate)?.DynamicInvoke();
			}
		}

		private static List<ItemSnapshot> CreateSnapshot(List<object> items)
		{
			List<ItemSnapshot> list = new List<ItemSnapshot>(items.Count);
			foreach (object item in items)
			{
				list.Add(new ItemSnapshot
				{
					Item = item,
					Stack = GetStack(item),
					Position = ReflectionTools.Get(item, "m_gridPos")
				});
			}
			return list;
		}

		private static void Restore(IList rawItems, List<ItemSnapshot> snapshot)
		{
			rawItems.Clear();
			foreach (ItemSnapshot item in snapshot)
			{
				SetStack(item.Item, item.Stack);
				GetPositionAccessor(item.Item.GetType()).Field.SetValue(item.Item, item.Position);
				rawItems.Add(item.Item);
			}
		}

		private static int CompareAlphabetical(SortEntry left, SortEntry right)
		{
			int num = DisplayNameComparer.Compare(left.DisplayName, right.DisplayName);
			if (num != 0)
			{
				return num;
			}
			num = InternalIdComparer.Compare(left.InternalId, right.InternalId);
			if (num != 0)
			{
				return num;
			}
			num = right.Quality.CompareTo(left.Quality);
			if (num != 0)
			{
				return num;
			}
			num = left.Variant.CompareTo(right.Variant);
			if (num != 0)
			{
				return num;
			}
			num = right.Stack.CompareTo(left.Stack);
			if (num == 0)
			{
				return left.OriginalIndex.CompareTo(right.OriginalIndex);
			}
			return num;
		}

		private static int CompareStacks(SortEntry left, SortEntry right)
		{
			int num = left.Category.CompareTo(right.Category);
			if (num != 0)
			{
				return num;
			}
			num = DisplayNameComparer.Compare(left.DisplayName, right.DisplayName);
			if (num != 0)
			{
				return num;
			}
			num = InternalIdComparer.Compare(left.InternalId, right.InternalId);
			if (num != 0)
			{
				return num;
			}
			num = right.Quality.CompareTo(left.Quality);
			if (num != 0)
			{
				return num;
			}
			num = right.Stack.CompareTo(left.Stack);
			if (num != 0)
			{
				return num;
			}
			num = left.Variant.CompareTo(right.Variant);
			if (num == 0)
			{
				return left.OriginalIndex.CompareTo(right.OriginalIndex);
			}
			return num;
		}

		private static PositionAccessor GetPositionAccessor(Type itemType)
		{
			lock (CacheLock)
			{
				if (PositionAccessors.TryGetValue(itemType, out var value))
				{
					return value;
				}
				FieldInfo fieldInfo = ReflectionTools.FindField(itemType, "m_gridPos");
				if (fieldInfo == null)
				{
					throw new MissingFieldException(itemType.FullName, "m_gridPos");
				}
				PositionAccessor positionAccessor = new PositionAccessor();
				positionAccessor.Field = fieldInfo;
				positionAccessor.Constructor = fieldInfo.FieldType.GetConstructor(new Type[2]
				{
					typeof(int),
					typeof(int)
				});
				PositionAccessor positionAccessor2 = positionAccessor;
				PositionAccessors[itemType] = positionAccessor2;
				return positionAccessor2;
			}
		}

		private static ChangeNotifier GetChangeNotifier(Type inventoryType)
		{
			lock (CacheLock)
			{
				if (ChangeNotifiers.TryGetValue(inventoryType, out var value))
				{
					return value;
				}
				MethodInfo methodInfo = null;
				MethodInfo[] methods = inventoryType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo2 in methods)
				{
					if (methodInfo2.Name != "Changed")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo2.GetParameters();
					bool flag = true;
					ParameterInfo[] array = parameters;
					for (int j = 0; j < array.Length; j++)
					{
						if (array[j].ParameterType != typeof(bool))
						{
							flag = false;
							break;
						}
					}
					if (flag && (methodInfo == null || parameters.Length > methodInfo.GetParameters().Length))
					{
						methodInfo = methodInfo2;
					}
				}
				ChangeNotifier changeNotifier = new ChangeNotifier
				{
					Method = methodInfo
				};
				if (methodInfo != null)
				{
					changeNotifier.Arguments = new object[methodInfo.GetParameters().Length];
					for (int k = 0; k < changeNotifier.Arguments.Length; k++)
					{
						changeNotifier.Arguments[k] = false;
					}
				}
				ChangeNotifiers[inventoryType] = changeNotifier;
				return changeNotifier;
			}
		}
	}
	internal static class InventoryActions
	{
		private static Type _dragGuiType;

		private static MethodInfo _setupDragItem;

		private static readonly object[] ClearDragArguments = new object[3] { null, null, 1 };

		internal static object GetInventoryGuiInstance()
		{
			return ReflectionTools.GetStatic(ReflectionTools.FindType("InventoryGui"), "instance");
		}

		internal static bool IsInventoryVisible()
		{
			Type type = ReflectionTools.FindType("InventoryGui");
			if (type == null)
			{
				return false;
			}
			MethodInfo methodInfo = ReflectionTools.FindStaticMethod(type, "IsVisible", 0);
			if (methodInfo != null)
			{
				object obj = methodInfo.Invoke(null, null);
				if (obj is bool)
				{
					return (bool)obj;
				}
			}
			return GetInventoryGuiInstance() != null;
		}

		internal static void OrganizePreferred(object gui, OrganizeMode mode)
		{
			if (GetCurrentContainer(gui) != null)
			{
				OrganizeContainer(gui, mode);
			}
			else
			{
				OrganizePlayer(gui, mode);
			}
		}

		internal static void OrganizePlayer(object gui, OrganizeMode mode)
		{
			if (CanRun(out var player))
			{
				object inventory = ReflectionTools.Invoke(player, "GetInventory");
				Run(gui, inventory, playerInventory: true, mode, "inventario");
			}
		}

		internal static void OrganizeContainer(object gui, OrganizeMode mode)
		{
			if (!CanRun(out var _))
			{
				return;
			}
			object currentContainer = GetCurrentContainer(gui);
			if (currentContainer == null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Nenhum bau esta aberto para organizar.");
				}
				return;
			}
			object obj = ReflectionTools.Invoke(currentContainer, "IsOwner");
			if (!(obj is bool) || !(bool)obj)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"O cliente ainda nao recebeu a posse temporaria deste bau; organizacao ignorada com seguranca.");
				}
			}
			else
			{
				object inventory = ReflectionTools.Invoke(currentContainer, "GetInventory");
				Run(gui, inventory, playerInventory: false, mode, "bau");
			}
		}

		internal static object GetCurrentContainer(object gui)
		{
			return ReflectionTools.Get(gui, "m_currentContainer");
		}

		private static bool CanRun(out object player)
		{
			player = ReflectionTools.GetStatic(ReflectionTools.FindType("Player"), "m_localPlayer");
			if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.Enabled.Value || player == null)
			{
				return false;
			}
			if (ReflectionTools.Invoke(player, "IsTeleporting") is bool flag)
			{
				return !flag;
			}
			return true;
		}

		private static void Run(object gui, object inventory, bool playerInventory, OrganizeMode mode, string target)
		{
			try
			{
				ClearDraggedItem(gui);
				if (InventoryOrganizer.Organize(inventory, playerInventory, mode, out var summary))
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("Organizacao do " + target + ": " + summary + "."));
					}
				}
				else
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)("O " + target + " nao foi alterado: " + summary + "."));
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)$"Organizacao do {target} falhou; o estado anterior foi restaurado. {arg}");
				}
			}
		}

		private static void ClearDraggedItem(object gui)
		{
			if (gui == null || ReflectionTools.Get(gui, "m_dragItem") == null)
			{
				return;
			}
			Type type = gui.GetType();
			if ((object)_dragGuiType != type)
			{
				_dragGuiType = type;
				_setupDragItem = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo method) => method.Name == "SetupDragItem" && method.GetParameters().Length == 3);
			}
			_setupDragItem?.Invoke(gui, ClearDragArguments);
		}
	}
	internal static class ModText
	{
		internal const string Portuguese = "Português";

		internal const string English = "English";

		internal static bool IsEnglish
		{
			get
			{
				if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.Language != null)
				{
					return Plugin.Instance.Language.Value == "English";
				}
				return false;
			}
		}

		internal static string Get(string portuguese, string english)
		{
			if (!IsEnglish)
			{
				return portuguese;
			}
			return english;
		}

		internal static string Category(CraftCategoryFilter category)
		{
			return category switch
			{
				CraftCategoryFilter.Weapons => Get("Armas", "Weapons"), 
				CraftCategoryFilter.Armor => Get("Armadura", "Armor"), 
				CraftCategoryFilter.Tools => Get("Ferramentas", "Tools"), 
				CraftCategoryFilter.Food => Get("Comida", "Food"), 
				CraftCategoryFilter.Materials => Get("Materiais", "Materials"), 
				CraftCategoryFilter.Other => Get("Outros", "Other"), 
				_ => Get("Todos", "All"), 
			};
		}

		internal static string Category(ItemCategory category)
		{
			return category switch
			{
				ItemCategory.Weapons => Get("Armas", "Weapons"), 
				ItemCategory.Armor => Get("Armaduras", "Armor"), 
				ItemCategory.Tools => Get("Ferramentas", "Tools"), 
				ItemCategory.Food => Get("Comida/consumíveis", "Food/consumables"), 
				ItemCategory.Materials => Get("Materiais", "Materials"), 
				_ => Get("Outros", "Other"), 
			};
		}

		internal static string Sort(CraftSortMode mode)
		{
			return mode switch
			{
				CraftSortMode.NameAscending => "A-Z", 
				CraftSortMode.NameDescending => "Z-A", 
				CraftSortMode.Category => Get("Categoria", "Category"), 
				CraftSortMode.Weight => Get("Peso", "Weight"), 
				_ => Get("Padrão", "Default"), 
			};
		}
	}
	[BepInPlugin("br.gleydson.valheim.ordemdoartesao", "Ordem do Artesao", "1.0.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "br.gleydson.valheim.ordemdoartesao";

		public const string PluginName = "Ordem do Artesao";

		public const string PluginVersion = "1.0.3";

		private Harmony _harmony;

		private bool _languageRefreshPending;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log
		{
			get
			{
				if (!((Object)(object)Instance == (Object)null))
				{
					return ((BaseUnityPlugin)Instance).Logger;
				}
				return null;
			}
		}

		internal ConfigEntry<bool> Enabled { get; private set; }

		internal ConfigEntry<string> Language { get; private set; }

		internal ConfigEntry<bool> ShowInternalId { get; private set; }

		internal ConfigEntry<bool> PreserveHotbar { get; private set; }

		internal ConfigEntry<bool> PreserveEquipped { get; private set; }

		internal ConfigEntry<bool> PreserveSpecialSlots { get; private set; }

		internal ConfigEntry<string> LockedPlayerSlots { get; private set; }

		internal ConfigEntry<bool> ClearSearchOnClose { get; private set; }

		internal ConfigEntry<KeyboardShortcut> OrganizeShortcut { get; private set; }

		internal ConfigEntry<KeyboardShortcut> StackShortcut { get; private set; }

		internal ConfigEntry<KeyboardShortcut> ToggleSlotLockShortcut { get; private set; }

		internal ConfigEntry<float> PlayerButtonsOffsetX { get; private set; }

		internal ConfigEntry<float> PlayerButtonsOffsetY { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Instance = this;
			BindConfiguration();
			SlotLockController.Initialize();
			MarkGameAsModded();
			try
			{
				_harmony = new Harmony("br.gleydson.valheim.ordemdoartesao");
				int num = InstallPatches(_harmony);
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} carregado: {2} metodos conectados. Tudo no cliente, cada item no seu quadrado.", "Ordem do Artesao", "1.0.3", num));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Nao foi possivel iniciar os recursos de interface. " + ex));
				try
				{
					Harmony harmony = _harmony;
					if (harmony != null)
					{
						harmony.UnpatchSelf();
					}
				}
				catch
				{
				}
				_harmony = null;
			}
		}

		private void Update()
		{
			//IL_005b: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (Enabled == null || !Enabled.Value)
			{
				return;
			}
			if (_languageRefreshPending)
			{
				_languageRefreshPending = false;
				RefreshLocalizedInterface();
			}
			try
			{
				CraftingUiController.Tick();
				SlotLockController.Tick();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogDebug((object)("Atualizacao adiada da interface falhou: " + ex.Message));
			}
			KeyboardShortcut value = ToggleSlotLockShortcut.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !CraftingUiController.IsTyping)
			{
				try
				{
					if (InventoryActions.IsInventoryVisible())
					{
						SlotLockController.ToggleHoveredSlot();
					}
					return;
				}
				catch (Exception ex2)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Nao foi possivel alternar a trava deste slot: " + ex2.Message));
					return;
				}
			}
			value = OrganizeShortcut.Value;
			bool flag = ((KeyboardShortcut)(ref value)).IsDown();
			int num;
			if (!flag)
			{
				value = StackShortcut.Value;
				num = (((KeyboardShortcut)(ref value)).IsDown() ? 1 : 0);
			}
			else
			{
				num = 0;
			}
			bool flag2 = (byte)num != 0;
			if (!flag && !flag2)
			{
				return;
			}
			try
			{
				if (InventoryActions.IsInventoryVisible())
				{
					InventoryActions.OrganizePreferred(InventoryActions.GetInventoryGuiInstance(), (!flag) ? OrganizeMode.Stacks : OrganizeMode.Alphabetical);
				}
			}
			catch (Exception ex3)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Atalho de organizacao falhou sem alterar mais itens: " + ex3.Message));
			}
		}

		private void OnDestroy()
		{
			try
			{
				if (Language != null)
				{
					Language.SettingChanged -= OnLanguageChanged;
				}
				CraftingUiController.Dispose();
				InventoryButtons.Dispose();
				SlotLockController.Dispose();
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			finally
			{
				_harmony = null;
				Instance = null;
			}
		}

		private void LateUpdate()
		{
			if (Enabled == null || !Enabled.Value)
			{
				return;
			}
			try
			{
				CraftingUiController.ApplyPendingRecipeList();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Filtro adiado de receitas falhou sem afetar o inventario: " + ex.Message));
			}
		}

		private void BindConfiguration()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			Language = ((BaseUnityPlugin)this).Config.Bind<string>("Geral", "Idioma / Language", "Português", new ConfigDescription("Idioma dos textos do mod. / Language used by the mod interface.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Português", "English" }), Array.Empty<object>()));
			Language.SettingChanged += OnLanguageChanged;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Geral", "Ativado", true, "Ativa as ferramentas de interface, busca e organizacao. / Enables the UI, search and organization tools.");
			ShowInternalId = ((BaseUnityPlugin)this).Config.Bind<bool>("Geral", "MostrarIdInterno", true, "Mostra o nome interno/prefab do item ao final do tooltip.");
			PreserveHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("Organizacao", "PreservarBarraRapida", true, "Nao move os oito atalhos da primeira linha ao organizar o inventario do jogador.");
			PreserveEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Organizacao", "PreservarEquipados", true, "Nao move itens marcados como equipados ao organizar o inventario do jogador.");
			PreserveSpecialSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("Organizacao", "PreservarSlotsEspeciais", true, "Protege as areas de equipamento e atalhos do Equipment and Quick Slots, inclusive quando vazias.");
			LockedPlayerSlots = ((BaseUnityPlugin)this).Config.Bind<string>("Organizacao", "SlotsBloqueados", string.Empty, "Coordenadas dos slots bloqueados pelo jogador. Edite no jogo com o atalho BloquearSlot.");
			ClearSearchOnClose = ((BaseUnityPlugin)this).Config.Bind<bool>("Crafting", "LimparBuscaAoFechar", true, "Limpa o texto de busca quando a janela do inventario e fechada.");
			OrganizeShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Atalhos", "OrganizarAZ", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Organiza o bau aberto; sem bau aberto, organiza o inventario. Use KeyCode.None para desativar.");
			StackShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Atalhos", "JuntarPilhas", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Junta pilhas compativeis e organiza o bau aberto; sem bau aberto, usa o inventario.");
			ToggleSlotLockShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Atalhos", "BloquearSlot", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Com o inventario aberto, passe o mouse sobre um slot e use este atalho para bloquear/desbloquear.");
			PlayerButtonsOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "BotoesInventarioX", 0f, "Ajuste horizontal dos botoes A-Z/Pilhas do inventario.");
			PlayerButtonsOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Interface", "BotoesInventarioY", 4f, "Ajuste vertical dos botoes A-Z/Pilhas do inventario.");
		}

		private void OnLanguageChanged(object sender, EventArgs eventArgs)
		{
			_languageRefreshPending = true;
		}

		private static void RefreshLocalizedInterface()
		{
			object inventoryGuiInstance = InventoryActions.GetInventoryGuiInstance();
			CraftingUiController.Dispose();
			InventoryButtons.Dispose();
			if (inventoryGuiInstance != null && InventoryActions.IsInventoryVisible())
			{
				CraftingUiController.Ensure(inventoryGuiInstance);
				InventoryButtons.Ensure(inventoryGuiInstance);
			}
		}

		private static void MarkGameAsModded()
		{
			try
			{
				Type type = ReflectionTools.FindType("Game");
				((type == null) ? null : AccessTools.Field(type, "isModded"))?.SetValue(null, true);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)("Nao foi necessario/possivel marcar Game.isModded: " + ex.Message));
				}
			}
		}

		private static int InstallPatches(Harmony harmony)
		{
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			Type type = RequireType("InventoryGui");
			int num = 0;
			num += PatchAllNamed(harmony, type, "Awake", null, "InventoryGuiAwakePostfix");
			num += PatchAllNamed(harmony, type, "Show", null, "InventoryGuiShowPostfix");
			num += PatchAllNamed(harmony, type, "Hide", "InventoryGuiHidePrefix", null);
			num += PatchAllNamed(harmony, type, "UpdateRecipeList", null, "UpdateRecipeListPostfix");
			Type type2 = ReflectionTools.FindType("Chat");
			if (type2 != null)
			{
				num += PatchAllNamed(harmony, type2, "HasFocus", null, "ChatHasFocusPostfix");
			}
			Type itemData = RequireType("ItemDrop+ItemData");
			List<MethodInfo> source = (from candidate in AccessTools.GetDeclaredMethods(itemData)
				where candidate.Name == "GetTooltip" && candidate.ReturnType == typeof(string)
				select candidate).ToList();
			List<MethodInfo> list = source.Where((MethodInfo method) => method.IsStatic && method.GetParameters().Length != 0 && itemData.IsAssignableFrom(method.GetParameters()[0].ParameterType)).ToList();
			IEnumerable<MethodInfo> enumerable;
			if (list.Count <= 0)
			{
				enumerable = source.Where((MethodInfo method) => !method.IsStatic);
			}
			else
			{
				IEnumerable<MethodInfo> enumerable2 = list;
				enumerable = enumerable2;
			}
			foreach (MethodInfo item in enumerable)
			{
				HarmonyMethod val = new HarmonyMethod(typeof(Plugin), item.IsStatic ? "StaticTooltipPostfix" : "InstanceTooltipPostfix", (Type[])null);
				harmony.Patch((MethodBase)item, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			return num;
		}

		private static int PatchAllNamed(Harmony harmony, Type type, string methodName, string prefixName, string postfixName)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			List<MethodInfo> list = (from method in AccessTools.GetDeclaredMethods(type)
				where method.Name == methodName
				select method).ToList();
			if (list.Count == 0)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Metodo opcional " + type.Name + "." + methodName + " nao foi encontrado."));
				}
				return 0;
			}
			HarmonyMethod val = ((prefixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), prefixName, (Type[])null));
			HarmonyMethod val2 = ((postfixName == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), postfixName, (Type[])null));
			foreach (MethodInfo item in list)
			{
				harmony.Patch((MethodBase)item, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			return list.Count;
		}

		private static Type RequireType(string name)
		{
			Type type = ReflectionTools.FindType(name);
			if (type == null)
			{
				throw new TypeLoadException("Tipo do Valheim nao encontrado: " + name);
			}
			return type;
		}

		private static void InventoryGuiAwakePostfix(object __instance)
		{
			SafeUi(delegate
			{
				LocalizedText.ClearCache();
				CraftingUiController.Ensure(__instance);
				InventoryButtons.Ensure(__instance);
				SlotLockController.Ensure(__instance);
			}, "criacao dos controles");
		}

		private static void InventoryGuiShowPostfix(object __instance)
		{
			SafeUi(delegate
			{
				CraftingUiController.Ensure(__instance);
				InventoryButtons.Ensure(__instance);
				CraftingUiController.RefreshLabels();
				SlotLockController.Ensure(__instance);
			}, "abertura do inventario");
		}

		private static void InventoryGuiHidePrefix()
		{
			if ((Object)(object)Instance != (Object)null && Instance.ClearSearchOnClose.Value)
			{
				SafeUi(CraftingUiController.ClearSearch, "limpeza da busca");
			}
		}

		private static void UpdateRecipeListPostfix(object __instance)
		{
			if (!((Object)(object)Instance == (Object)null) && Instance.Enabled.Value)
			{
				CraftingUiController.ScheduleRecipeList(__instance);
			}
		}

		private static void ChatHasFocusPostfix(ref bool __result)
		{
			if (!__result && CraftingUiController.IsTyping)
			{
				__result = true;
			}
		}

		private static void InstanceTooltipPostfix(object __instance, ref string __result)
		{
			AppendInternalId(__instance, ref __result);
		}

		private static void StaticTooltipPostfix(object[] __args, ref string __result)
		{
			AppendInternalId((__args != null && __args.Length != 0) ? __args[0] : null, ref __result);
		}

		private static void AppendInternalId(object item, ref string tooltip)
		{
			if ((Object)(object)Instance == (Object)null || !Instance.Enabled.Value || !Instance.ShowInternalId.Value || item == null || (!string.IsNullOrEmpty(tooltip) && (tooltip.IndexOf("ID interno:", StringComparison.Ordinal) >= 0 || tooltip.IndexOf("Internal ID:", StringComparison.Ordinal) >= 0)))
			{
				return;
			}
			try
			{
				string tooltipLine = ItemIdentity.GetTooltipLine(item);
				if (!string.IsNullOrEmpty(tooltipLine))
				{
					tooltip = (string.IsNullOrEmpty(tooltip) ? tooltipLine : (tooltip + "\n" + tooltipLine));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)("Nao foi possivel acrescentar o ID interno: " + ex.Message));
				}
			}
		}

		private static void SafeUi(Action action, string operation)
		{
			try
			{
				action();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Falha isolada na " + operation + ": " + ex.Message));
				}
			}
		}
	}
	internal static class RecipeListAdapter
	{
		private sealed class RecipeEntry
		{
			internal object Pair;

			internal object Item;

			internal GameObject InterfaceElement;

			internal int OriginalIndex;

			internal ItemCategory Category;

			internal string DisplayName;

			internal string InternalId;

			internal string NameToken;

			internal float Weight;

			internal bool CanCraft;

			internal int Quality;
		}

		private static readonly CompareInfo SearchComparer = CultureInfo.InvariantCulture.CompareInfo;

		private static readonly StringComparer NameComparer = StringComparer.CurrentCultureIgnoreCase;

		internal static void Apply(object gui, CraftSortMode sort, CraftCategoryFilter category, string query)
		{
			string text = (string.IsNullOrWhiteSpace(query) ? string.Empty : query.Trim());
			bool flag = text.Length > 0;
			bool flag2 = category != CraftCategoryFilter.All;
			bool flag3 = sort != CraftSortMode.Default;
			if (!flag && !flag2 && !flag3)
			{
				return;
			}
			IList list = ReflectionTools.AsList(ReflectionTools.Get(gui, "m_availableRecipes"));
			if (list == null || list.Count == 0)
			{
				return;
			}
			List<RecipeEntry> list2 = new List<RecipeEntry>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				list2.Add(CreateEntry(list[i], i, flag || flag3, flag, flag3, sort == CraftSortMode.Weight));
			}
			List<RecipeEntry> list3 = new List<RecipeEntry>(list2.Count);
			foreach (RecipeEntry item in list2)
			{
				if (Matches(item, category, text))
				{
					list3.Add(item);
				}
				else if ((Object)(object)item.InterfaceElement != (Object)null)
				{
					Object.Destroy((Object)(object)item.InterfaceElement);
				}
			}
			if (flag3)
			{
				Sort(list3, sort);
			}
			if (HasSameOrder(list2, list3))
			{
				return;
			}
			list.Clear();
			foreach (RecipeEntry item2 in list3)
			{
				list.Add(item2.Pair);
			}
			Relayout(gui, list3);
		}

		private static RecipeEntry CreateEntry(object pair, int index, bool readDisplayName, bool readSearchFields, bool readRankFields, bool readWeight)
		{
			object itemData = GetItemData(pair);
			ItemCategory category = ((itemData == null) ? ItemCategory.Other : ItemIdentity.GetCategory(itemData));
			return new RecipeEntry
			{
				Pair = pair,
				Item = itemData,
				InterfaceElement = ReflectionTools.AsGameObject(GetPairMember(pair, "InterfaceElement")),
				OriginalIndex = index,
				Category = category,
				DisplayName = ((itemData != null && readDisplayName) ? ItemIdentity.GetDisplayName(itemData) : string.Empty),
				InternalId = ((itemData != null && readSearchFields) ? ItemIdentity.GetInternalId(itemData) : string.Empty),
				NameToken = ((itemData != null && readSearchFields) ? ItemIdentity.GetNameToken(itemData) : string.Empty),
				Weight = ((itemData != null && readWeight) ? ItemIdentity.GetWeight(itemData) : 0f),
				CanCraft = (readRankFields && ReadCanCraft(pair)),
				Quality = ((!(itemData != null && readRankFields)) ? 1 : ReflectionTools.GetInt(itemData, "m_quality", 1))
			};
		}

		private static bool Matches(RecipeEntry entry, CraftCategoryFilter filter, string query)
		{
			if (entry.Item == null)
			{
				if (filter == CraftCategoryFilter.All)
				{
					return query.Length == 0;
				}
				return false;
			}
			if (!MatchesCategory(entry.Category, filter))
			{
				return false;
			}
			if (query.Length == 0)
			{
				return true;
			}
			if (!Contains(entry.DisplayName, query, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) && !Contains(entry.InternalId, query, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) && !Contains(entry.NameToken, query, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace))
			{
				return Contains(ItemIdentity.GetCategoryLabel(entry.Category), query, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace);
			}
			return true;
		}

		private static bool Contains(string value, string query, CompareOptions options)
		{
			if (!string.IsNullOrEmpty(value))
			{
				return SearchComparer.IndexOf(value, query, options) >= 0;
			}
			return false;
		}

		private static bool MatchesCategory(ItemCategory category, CraftCategoryFilter filter)
		{
			return filter switch
			{
				CraftCategoryFilter.Weapons => category == ItemCategory.Weapons, 
				CraftCategoryFilter.Armor => category == ItemCategory.Armor, 
				CraftCategoryFilter.Tools => category == ItemCategory.Tools, 
				CraftCategoryFilter.Food => category == ItemCategory.Food, 
				CraftCategoryFilter.Materials => category == ItemCategory.Materials, 
				CraftCategoryFilter.Other => category == ItemCategory.Other, 
				_ => true, 
			};
		}

		private static void Sort(List<RecipeEntry> entries, CraftSortMode mode)
		{
			entries.Sort((RecipeEntry left, RecipeEntry right) => CompareEntries(left, right, mode));
		}

		private static int CompareEntries(RecipeEntry left, RecipeEntry right, CraftSortMode mode)
		{
			int num = 0;
			switch (mode)
			{
			case CraftSortMode.Category:
				num = left.Category.CompareTo(right.Category);
				break;
			case CraftSortMode.Weight:
				num = left.Weight.CompareTo(right.Weight);
				break;
			}
			if (num != 0)
			{
				return num;
			}
			num = ((mode == CraftSortMode.NameDescending) ? NameComparer.Compare(right.DisplayName, left.DisplayName) : NameComparer.Compare(left.DisplayName, right.DisplayName));
			if (num != 0)
			{
				return num;
			}
			num = right.CanCraft.CompareTo(left.CanCraft);
			if (num != 0)
			{
				return num;
			}
			num = right.Quality.CompareTo(left.Quality);
			if (num == 0)
			{
				return left.OriginalIndex.CompareTo(right.OriginalIndex);
			}
			return num;
		}

		private static bool HasSameOrder(IList<RecipeEntry> original, IList<RecipeEntry> visible)
		{
			if (original.Count != visible.Count)
			{
				return false;
			}
			for (int i = 0; i < original.Count; i++)
			{
				if (!object.Equals(original[i].Pair, visible[i].Pair))
				{
					return false;
				}
			}
			return true;
		}

		private static void Relayout(object gui, IList<RecipeEntry> entries)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			float num = ReflectionTools.GetFloat(gui, "m_recipeListSpace", 64f);
			for (int i = 0; i < entries.Count; i++)
			{
				GameObject interfaceElement = entries[i].InterfaceElement;
				RectTransform val = (RectTransform)(((Object)(object)interfaceElement == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
				if ((Object)(object)val != (Object)null)
				{
					val.anchoredPosition = new Vector2(0f, (float)i * (0f - num));
				}
			}
			RectTransform val2 = ReflectionTools.AsRectTransform(ReflectionTools.Get(gui, "m_recipeListRoot"));
			if (!((Object)(object)val2 == (Object)null))
			{
				Rect rect = val2.rect;
				float num2 = ReflectionTools.GetFloat(gui, "m_recipeListBaseSize", ((Rect)(ref rect)).height);
				val2.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(num2, (float)entries.Count * num));
			}
		}

		private static object GetItemData(object pair)
		{
			object pairMember = GetPairMember(pair, "ItemData");
			if (pairMember != null)
			{
				return pairMember;
			}
			return ReflectionTools.Get(ReflectionTools.Get(GetPairMember(pair, "Recipe"), "m_item"), "m_itemData");
		}

		private static object GetPairMember(object pair, string name)
		{
			return ReflectionTools.Get(pair, name);
		}

		private static bool ReadCanCraft(object pair)
		{
			object pairMember = GetPairMember(pair, "CanCraft");
			bool flag = default(bool);
			int num;
			if (pairMember is bool)
			{
				flag = (bool)pairMember;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}
	}
	internal static class ReflectionTools
	{
		private struct MemberKey : IEquatable<MemberKey>
		{
			private readonly Type _type;

			private readonly string _name;

			private readonly bool _isStatic;

			internal MemberKey(Type type, string name, bool isStatic)
			{
				_type = type;
				_name = name;
				_isStatic = isStatic;
			}

			public bool Equals(MemberKey other)
			{
				if ((object)_type == other._type && _isStatic == other._isStatic)
				{
					return string.Equals(_name, other._name, StringComparison.Ordinal);
				}
				return false;
			}

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

			public override int GetHashCode()
			{
				int num = ((((!(_type == null)) ? _type.GetHashCode() : 0) * 397) ^ ((_name != null) ? _name.GetHashCode() : 0)) * 397;
				bool isStatic = _isStatic;
				return num ^ isStatic.GetHashCode();
			}
		}

		private struct MethodKey : IEquatable<MethodKey>
		{
			private readonly Type _type;

			private readonly string _name;

			private readonly int _parameterCount;

			private readonly bool _isStatic;

			internal MethodKey(Type type, string name, int parameterCount, bool isStatic)
			{
				_type = type;
				_name = name;
				_parameterCount = parameterCount;
				_isStatic = isStatic;
			}

			public bool Equals(MethodKey other)
			{
				if ((object)_type == other._type && _parameterCount == other._parameterCount && _isStatic == other._isStatic)
				{
					return string.Equals(_name, other._name, StringComparison.Ordinal);
				}
				return false;
			}

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

			public override int GetHashCode()
			{
				int num = ((((((!(_type == null)) ? _type.GetHashCode() : 0) * 397) ^ ((_name != null) ? _name.GetHashCode() : 0)) * 397) ^ _parameterCount) * 397;
				bool isStatic = _isStatic;
				return num ^ isStatic.GetHashCode();
			}
		}

		internal const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		internal const BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly object CacheLock = new object();

		private static readonly Dictionary<MemberKey, FieldInfo> FieldCache = new Dictionary<MemberKey, FieldInfo>();

		private static readonly Dictionary<MemberKey, PropertyInfo> PropertyCache = new Dictionary<MemberKey, PropertyInfo>();

		private static readonly Dictionary<MethodKey, MethodInfo> MethodCache = new Dictionary<MethodKey, MethodInfo>();

		private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>(StringComparer.Ordinal);

		internal static Type FindType(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			lock (CacheLock)
			{
				if (TypeCache.TryGetValue(name, out var value))
				{
					return value;
				}
			}
			Type type = AccessTools.TypeByName(name);
			if (type != null)
			{
				lock (CacheLock)
				{
					TypeCache[name] = type;
				}
			}
			return type;
		}

		internal static FieldInfo FindField(Type type, string name)
		{
			return FindField(type, name, isStatic: false);
		}

		internal static PropertyInfo FindProperty(Type type, string name)
		{
			return FindProperty(type, name, isStatic: false);
		}

		internal static object Get(object instance, string name)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			FieldInfo fieldInfo = FindField(type, name, isStatic: false);
			if (fieldInfo != null)
			{
				return fieldInfo.GetValue(instance);
			}
			PropertyInfo propertyInfo = FindProperty(type, name, isStatic: false);
			if (!(propertyInfo == null))
			{
				return propertyInfo.GetValue(instance, null);
			}
			return null;
		}

		internal static T Get<T>(object instance, string name, T fallback = default(T))
		{
			object obj = Get(instance, name);
			if (obj is T)
			{
				return (T)obj;
			}
			try
			{
				return (obj == null) ? fallback : ((T)Convert.ChangeType(obj, typeof(T)));
			}
			catch
			{
				return fallback;
			}
		}

		internal static bool Set(object instance, string name, object value)
		{
			if (instance == null)
			{
				return false;
			}
			Type type = instance.GetType();
			FieldInfo fieldInfo = FindField(type, name, isStatic: false);
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(instance, value);
				return true;
			}
			PropertyInfo propertyInfo = FindProperty(type, name, isStatic: false);
			if (propertyInfo != null && propertyInfo.CanWrite)
			{
				propertyInfo.SetValue(instance, value, null);
				return true;
			}
			return false;
		}

		internal static object GetStatic(Type type, string name)
		{
			if (type == null)
			{
				return null;
			}
			FieldInfo fieldInfo = FindField(type, name, isStatic: true);
			if (fieldInfo != null)
			{
				return fieldInfo.GetValue(null);
			}
			PropertyInfo propertyInfo = FindProperty(type, name, isStatic: true);
			if (!(propertyInfo == null))
			{
				return propertyInfo.GetValue(null, null);
			}
			return null;
		}

		internal static MethodInfo FindMethod(Type type, string name, int? parameterCount = null)
		{
			return FindMethod(type, name, parameterCount, isStatic: false);
		}

		internal static MethodInfo FindStaticMethod(Type type, string name, int? parameterCount = null)
		{
			return FindMethod(type, name, parameterCount, isStatic: true);
		}

		internal static object Invoke(object instance, string name, params object[] arguments)
		{
			if (instance == null)
			{
				return null;
			}
			object[] array = arguments ?? Array.Empty<object>();
			MethodInfo methodInfo = ((array.Length == 0) ? FindMethod(instance.GetType(), name, 0) : FindCompatibleMethod(instance.GetType(), name, array));
			if (!(methodInfo == null))
			{
				return methodInfo.Invoke(instance, array);
			}
			return null;
		}

		internal static MethodInfo FindCompatibleMethod(Type type, string name, object[] arguments)
		{
			while (type != null)
			{
				foreach (MethodInfo item in from candidate in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
					where candidate.Name == name
					select candidate)
				{
					ParameterInfo[] parameters = item.GetParameters();
					if (parameters.Length != arguments.Length)
					{
						continue;
					}
					bool flag = true;
					for (int num = 0; num < parameters.Length; num++)
					{
						object obj = arguments[num];
						if (obj == null)
						{
							if (parameters[num].ParameterType.IsValueType && Nullable.GetUnderlyingType(parameters[num].ParameterType) == null)
							{
								flag = false;
								break;
							}
						}
						else if (!parameters[num].ParameterType.IsInstanceOfType(obj) && !CanNumericConvert(obj.GetType(), parameters[num].ParameterType))
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						return item;
					}
				}
				type = type.BaseType;
			}
			return null;
		}

		internal static GameObject AsGameObject(object value)
		{
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (val != null)
			{
				return val;
			}
			Component val2 = (Component)((value is Component) ? value : null);
			if (val2 != null)
			{
				return val2.gameObject;
			}
			return null;
		}

		internal static RectTransform AsRectTransform(object value)
		{
			GameObject val = AsGameObject(value);
			if (!((Object)(object)val == (Object)null))
			{
				Transform transform = val.transform;
				return (RectTransform)(object)((transform is RectTransform) ? transform : null);
			}
			return (RectTransform)((value is RectTransform) ? value : null);
		}

		internal static IList AsList(object value)
		{
			return value as IList;
		}

		internal static int GetInt(object instance, string name, int fallback = 0)
		{
			object obj = Get(instance, name);
			if (obj is int)
			{
				return (int)obj;
			}
			return fallback;
		}

		internal static float GetFloat(object instance, string name, float fallback = 0f)
		{
			object obj = Get(instance, name);
			if (obj is float)
			{
				return (float)obj;
			}
			if (!(obj is double num))
			{
				return fallback;
			}
			return (float)num;
		}

		internal static bool GetBool(object instance, string name, bool fallback = false)
		{
			object obj = Get(instance, name);
			if (obj is bool)
			{
				return (bool)obj;
			}
			return fallback;
		}

		internal static IEnumerable<object> GetComponentsInChildren(GameObject root, Type type)
		{
			if ((Object)(object)root == (Object)null || type == null)
			{
				return Enumerable.Empty<object>();
			}
			return root.GetComponentsInChildren(type, true).Cast<object>();
		}

		internal static void SetEnumProperty(object instance, string propertyName, string enumName)
		{
			PropertyInfo propertyInfo = ((instance == null) ? null : FindProperty(instance.GetType(), propertyName));
			if (propertyInfo == null || !propertyInfo.CanWrite || !propertyInfo.PropertyType.IsEnum)
			{
				return;
			}
			try
			{
				propertyInfo.SetValue(instance, Enum.Parse(propertyInfo.PropertyType, enumName, ignoreCase: true), null);
			}
			catch
			{
			}
		}

		private static FieldInfo FindField(Type type, string name, bool isStatic)
		{
			if (type == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			MemberKey key = new MemberKey(type, name, isStatic);
			lock (CacheLock)
			{
				if (FieldCache.TryGetValue(key, out var value))
				{
					return value;
				}
			}
			BindingFlags bindingAttr = (BindingFlags)((isStatic ? 56 : 52) | 2);
			Type type2 = type;
			FieldInfo fieldInfo = null;
			while (type2 != null && fieldInfo == null)
			{
				fieldInfo = type2.GetField(name, bindingAttr);
				type2 = type2.BaseType;
			}
			lock (CacheLock)
			{
				FieldCache[key] = fieldInfo;
				return fieldInfo;
			}
		}

		private static PropertyInfo FindProperty(Type type, string name, bool isStatic)
		{
			if (type == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			MemberKey key = new MemberKey(type, name, isStatic);
			lock (CacheLock)
			{
				if (PropertyCache.TryGetValue(key, out var value))
				{
					return value;
				}
			}
			BindingFlags bindingAttr = (BindingFlags)((isStatic ? 56 : 52) | 2);
			Type type2 = type;
			PropertyInfo propertyInfo = null;
			while (type2 != null && propertyInfo == null)
			{
				propertyInfo = type2.GetProperty(name, bindingAttr);
				type2 = type2.BaseType;
			}
			lock (CacheLock)
			{
				PropertyCache[key] = propertyInfo;
				return propertyInfo;
			}
		}

		private static MethodInfo FindMethod(Type type, string name, int? parameterCount, bool isStatic)
		{
			if (type == null || string.IsNullOrEmpty(name))
			{
				return null;
			}
			MethodKey key = new MethodKey(type, name, parameterCount ?? (-1), isStatic);
			lock (CacheLock)
			{
				if (MethodCache.TryGetValue(key, out var value))
				{
					return value;
				}
			}
			BindingFlags bindingAttr = (BindingFlags)((isStatic ? 56 : 52) | 2);
			Type type2 = type;
			MethodInfo methodInfo = null;
			while (type2 != null && methodInfo == null)
			{
				methodInfo = type2.GetMethods(bindingAttr).FirstOrDefault((MethodInfo candidate) => candidate.Name == name && (!parameterCount.HasValue || candidate.GetParameters().Length == parameterCount.Value));
				type2 = type2.BaseType;
			}
			lock (CacheLock)
			{
				MethodCache[key] = methodInfo;
				return methodInfo;
			}
		}

		private static bool CanNumericConvert(Type from, Type to)
		{
			TypeCode typeCode = Type.GetTypeCode(from);
			TypeCode typeCode2 = Type.GetTypeCode(to);
			if (typeCode >= TypeCode.SByte && typeCode <= TypeCode.Decimal && typeCode2 >= TypeCode.SByte)
			{
				return typeCode2 <= TypeCode.Decimal;
			}
			return false;
		}
	}
	internal static class LocalizedText
	{
		private static readonly object CacheLock = new object();

		private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>(StringComparer.Ordinal);

		private static object _localization;

		private static MethodInfo _localize;

		internal static string FromToken(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return string.Empty;
			}
			lock (CacheLock)
			{
				if (Cache.TryGetValue(token, out var value))
				{
					return value;
				}
				try
				{
					object obj = ReflectionTools.GetStatic(ReflectionTools.FindType("Localization"), "instance");
					if (obj == null)
					{
						return token;
					}
					if (_localization != obj)
					{
						Cache.Clear();
						_localization = obj;
						_localize = ReflectionTools.FindCompatibleMethod(obj.GetType(), "Localize", new object[1] { token });
					}
					object obj2 = _localize?.Invoke(obj, new object[1] { token });
					string text = (string.IsNullOrEmpty(obj2 as string) ? token : ((string)obj2));
					Cache[token] = text;
					return text;
				}
				catch
				{
					return token;
				}
			}
		}

		internal static void ClearCache()
		{
			lock (CacheLock)
			{
				Cache.Clear();
				_localization = null;
				_localize = null;
			}
		}
	}
	internal static class SlotLockController
	{
		private const string MarkerName = "OrdemDoArtesao.SlotBloqueado";

		private static readonly List<GameObject> Markers = new List<GameObject>();

		private static object _gui;

		private static bool _refreshPending;

		private static int _refreshFrame;

		internal static void Initialize()
		{
			SlotLockRegistry.Load(Plugin.Instance?.LockedPlayerSlots?.Value);
		}

		internal static void Ensure(object gui)
		{
			if (gui != null)
			{
				if (_gui != gui)
				{
					DestroyMarkers();
					_gui = gui;
				}
				_refreshPending = SlotLockRegistry.Count > 0;
				_refreshFrame = Time.frameCount + 1;
			}
		}

		internal static void Tick()
		{
			if (_refreshPending && Time.frameCount >= _refreshFrame)
			{
				_refreshPending = false;
				RefreshMarkers();
			}
		}

		internal static bool ToggleHoveredSlot()
		{
			//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_002f: 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)
			if (_gui == null)
			{
				_gui = InventoryActions.GetInventoryGuiInstance();
			}
			if (!TryGetGrid(_gui, out var elements, out var width, out var rows))
			{
				return false;
			}
			Vector2 val = Vector2.op_Implicit(Input.mousePosition);
			int num = Math.Min(elements.Count, width * rows);
			for (int i = 0; i < num; i++)
			{
				GameObject val2 = ReflectionTools.AsGameObject(elements[i]);
				RectTransform val3 = (RectTransform)(((Object)(object)val2 == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
				if (!((Object)(object)val2 == (Object)null) && val2.activeInHierarchy && !((Object)(object)val3 == (Object)null) && RectTransformUtility.RectangleContainsScreenPoint(val3, val))
				{
					int num2 = i % width;
					int num3 = i / width;
					bool flag = SlotLockRegistry.Toggle(num2, num3);
					if (Plugin.Instance?.LockedPlayerSlots != null)
					{
						Plugin.Instance.LockedPlayerSlots.Value = SlotLockRegistry.Serialize();
					}
					RefreshMarkers();
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)string.Format("Slot ({0}, {1}) {2}. A organizacao {3}.", num2 + 1, num3 + 1, flag ? "bloqueado" : "desbloqueado", flag ? "nao tocara nele" : "voltara a usa-lo"));
					}
					return true;
				}
			}
			return false;
		}

		internal static void Dispose()
		{
			DestroyMarkers();
			_gui = null;
			_refreshPending = false;
		}

		private static void RefreshMarkers()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			DestroyMarkers();
			if (SlotLockRegistry.Count == 0 || !TryGetGrid(_gui, out var elements, out var width, out var rows))
			{
				return;
			}
			int num = Math.Min(elements.Count, width * rows);
			for (int i = 0; i < num; i++)
			{
				int x = i % width;
				int y = i / width;
				if (SlotLockRegistry.IsLocked(x, y))
				{
					GameObject val = ReflectionTools.AsGameObject(elements[i]);
					if (!((Object)(object)val == (Object)null))
					{
						GameObject val2 = new GameObject("OrdemDoArtesao.SlotBloqueado", new Type[2]
						{
							typeof(RectTransform),
							typeof(Image)
						});
						RectTransform val3 = (RectTransform)val2.transform;