Decompiled source of Carturs Waste Management v1.1.0

plugins/CarturWasteManagement/CarturWasteManagement.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CarturWasteManagement")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6b3d88bc3fe8badb50465fd02db0a0ca0ff6305d")]
[assembly: AssemblyProduct("CarturWasteManagement")]
[assembly: AssemblyTitle("CarturWasteManagement")]
[assembly: AssemblyVersion("1.0.0.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 CarturWasteManagement
{
	[BepInPlugin("com.jekkle.valheim.carturwastemanagement", "Cartur's Waste Management", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.jekkle.valheim.carturwastemanagement";

		public const string PluginName = "Cartur's Waste Management";

		public const string PluginVersion = "1.1.0";

		internal static Sprite CanSprite;

		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			CanSprite = LoadSprite("trashcan_128.png");
			try
			{
				Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "com.jekkle.valheim.carturwastemanagement");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Cartur's Waste Management 1.1.0 loaded - trash can refunds half the item's own recipe, sort button added.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed to patch InventoryGui - no can and no sort button this run. {arg}");
			}
		}

		private Sprite LoadSprite(string fileName)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "assets"), fileName);
			if (!File.Exists(text))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("asset missing: " + text));
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			MethodInfo methodInfo = null;
			MethodInfo[] array = AccessTools.TypeByName("UnityEngine.ImageConversion")?.GetMethods(BindingFlags.Static | BindingFlags.Public) ?? new MethodInfo[0];
			foreach (MethodInfo methodInfo2 in array)
			{
				ParameterInfo[] parameters = methodInfo2.GetParameters();
				if (methodInfo2.Name == "LoadImage" && parameters.Length == 3 && parameters[1].ParameterType == typeof(byte[]))
				{
					methodInfo = methodInfo2;
					break;
				}
			}
			if (!(methodInfo == null))
			{
				object obj = methodInfo.Invoke(null, new object[3]
				{
					val,
					File.ReadAllBytes(text),
					false
				});
				if (obj is bool && (bool)obj)
				{
					return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
				}
			}
			((BaseUnityPlugin)this).Logger.LogWarning((object)("could not decode " + text));
			return null;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	public static class Patch_InventoryGui_Show
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__SortOpenContainer;

			public static UnityAction <1>__DropCarriedItem;

			public static UnityAction <2>__SortPlayerInventory;
		}

		private const float CanSize = 54f;

		private const float ButtonWidth = 54f;

		private const float ButtonHeight = 30f;

		private const float Gap = 6f;

		private static GameObject s_can;

		private static GameObject s_sort;

		private static GameObject s_containerSort;

		private static void Postfix(InventoryGui __instance)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			BuildContainerSort(__instance);
			if (!((Object)(object)s_can != (Object)null) && !((Object)(object)__instance.m_weight == (Object)null))
			{
				RectTransform rectTransform = __instance.m_weight.rectTransform;
				Transform parent = ((Transform)rectTransform).parent;
				RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if (!((Object)(object)val == (Object)null))
				{
					float num = rectTransform.anchoredPosition.y + 30f + 6f;
					float num2 = num + 15f + 27f + 6f;
					s_can = BuildCan(val, new Vector2(rectTransform.anchoredPosition.x, num2));
					s_sort = BuildSort(__instance, val, new Vector2(rectTransform.anchoredPosition.x, num));
				}
			}
		}

		private static void BuildContainerSort(InventoryGui gui)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00ac: 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)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_containerSort != (Object)null || (Object)(object)gui.m_takeAllButton == (Object)null || (Object)(object)gui.m_container == (Object)null)
			{
				return;
			}
			RectTransform val = (((Object)(object)gui.m_stackAllButton != (Object)null) ? ((Component)gui.m_stackAllButton).GetComponent<RectTransform>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				GameObject val2 = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, ((Transform)val).parent);
				((Object)val2).name = "CarturSortContainerButton";
				val2.SetActive(true);
				RectTransform val3 = (RectTransform)val2.transform;
				val3.anchorMin = val.anchorMin;
				val3.anchorMax = val.anchorMax;
				val3.pivot = val.pivot;
				val3.sizeDelta = val.sizeDelta;
				Vector2 anchoredPosition = val.anchoredPosition;
				Rect rect = val.rect;
				val3.anchoredPosition = anchoredPosition - new Vector2(0f, ((Rect)(ref rect)).height + 6f);
				TMP_Text[] componentsInChildren = val2.GetComponentsInChildren<TMP_Text>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].text = "Sort";
				}
				Button component = val2.GetComponent<Button>();
				((UnityEventBase)component.onClick).RemoveAllListeners();
				ButtonClickedEvent onClick = component.onClick;
				object obj = <>O.<0>__SortOpenContainer;
				if (obj == null)
				{
					UnityAction val4 = WasteBin.SortOpenContainer;
					<>O.<0>__SortOpenContainer = val4;
					obj = (object)val4;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				s_containerSort = val2;
				RectTransform component2 = ((Component)gui.m_takeAllButton).GetComponent<RectTransform>();
				RectTransform val5 = (((Object)(object)gui.m_dropButton != (Object)null) ? ((Component)gui.m_dropButton).GetComponent<RectTransform>() : null);
				ManualLogSource log = Plugin.Log;
				string[] obj2 = new string[13]
				{
					"container sort button at ",
					((object)val3.anchoredPosition/*cast due to .constrained prefix*/).ToString(),
					" size ",
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				rect = val3.rect;
				obj2[3] = ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString();
				obj2[4] = "  (place stacks ";
				obj2[5] = ((object)val.anchoredPosition/*cast due to .constrained prefix*/).ToString();
				obj2[6] = " size ";
				rect = val.rect;
				obj2[7] = ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString();
				obj2[8] = ", take all ";
				obj2[9] = (((Object)(object)component2 != (Object)null) ? ((object)component2.anchoredPosition/*cast due to .constrained prefix*/).ToString() : "?");
				obj2[10] = ", drop ";
				obj2[11] = (((Object)(object)val5 != (Object)null) ? ((object)val5.anchoredPosition/*cast due to .constrained prefix*/).ToString() : "none");
				obj2[12] = ")";
				log.LogInfo((object)string.Concat(obj2));
			}
		}

		private static GameObject BuildCan(RectTransform parent, Vector2 pos)
		{
			//IL_0032: 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_003d: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00e5: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			GameObject val = new GameObject("CarturTrashCan", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.sizeDelta = new Vector2(54f, 54f);
			val2.anchoredPosition = pos;
			Image component = val.GetComponent<Image>();
			component.sprite = Plugin.CanSprite;
			component.preserveAspect = true;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			ButtonClickedEvent onClick = component2.onClick;
			object obj = <>O.<1>__DropCarriedItem;
			if (obj == null)
			{
				UnityAction val4 = WasteBin.DropCarriedItem;
				<>O.<1>__DropCarriedItem = val4;
				obj = (object)val4;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			return val;
		}

		private static GameObject BuildSort(InventoryGui gui, RectTransform parent, Vector2 pos)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			if ((Object)(object)gui.m_takeAllButton == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_takeAllButton).gameObject, (Transform)(object)parent);
			((Object)val).name = "CarturSortButton";
			val.SetActive(true);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.sizeDelta = new Vector2(54f, 30f);
			val2.anchoredPosition = pos;
			TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = "Sort";
			}
			Button component = val.GetComponent<Button>();
			((UnityEventBase)component.onClick).RemoveAllListeners();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>O.<2>__SortPlayerInventory;
			if (obj == null)
			{
				UnityAction val4 = WasteBin.SortPlayerInventory;
				<>O.<2>__SortPlayerInventory = val4;
				obj = (object)val4;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			return val;
		}
	}
	internal static class WasteBin
	{
		private static readonly FieldInfo DragItem = AccessTools.Field(typeof(InventoryGui), "m_dragItem");

		private static readonly FieldInfo DragInventory = AccessTools.Field(typeof(InventoryGui), "m_dragInventory");

		private static readonly FieldInfo DragAmount = AccessTools.Field(typeof(InventoryGui), "m_dragAmount");

		private static readonly MethodInfo SetupDragItem = AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null);

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

		private static readonly Type RarityType = AccessTools.TypeByName("EpicLoot.ItemRarity");

		private static readonly MethodInfo EnchantCostFor = ((RarityType == null) ? null : AccessTools.Method(AccessTools.TypeByName("EpicLoot.Crafting.EnchantCostsHelper"), "GetEnchantCost", new Type[2]
		{
			typeof(ItemData),
			RarityType
		}, (Type[])null));

		private static readonly MethodInfo SacrificeProductsFor = AccessTools.Method(AccessTools.TypeByName("EpicLoot.Crafting.EnchantCostsHelper"), "GetSacrificeProducts", new Type[1] { typeof(ItemData) }, (Type[])null);

		private static readonly MethodInfo IsMagicItem = AccessTools.Method(AccessTools.TypeByName("EpicLoot.API"), "IsMagicItem", new Type[1] { typeof(ItemData) }, (Type[])null);

		private static readonly MethodInfo TryGetRarity = AccessTools.Method(AccessTools.TypeByName("EpicLoot.API"), "TryGetRarity", new Type[2]
		{
			typeof(ItemData),
			typeof(int).MakeByRefType()
		}, (Type[])null);

		private static readonly FieldInfo CostItem = AccessTools.Field(AccessTools.TypeByName("EpicLoot.Crafting.ItemAmountConfig"), "Item");

		private static readonly FieldInfo CostAmount = AccessTools.Field(AccessTools.TypeByName("EpicLoot.Crafting.ItemAmountConfig"), "Amount");

		private static readonly MethodInfo VisibleRowsGetter = AccessTools.PropertyGetter(AccessTools.TypeByName("CarturUIHud.Slots"), "VisibleRows");

		private static bool s_boundaryLogged;

		private static readonly FieldInfo CurrentContainer = AccessTools.Field(typeof(InventoryGui), "m_currentContainer");

		private static readonly MethodInfo ContainerSave = AccessTools.Method(typeof(Container), "Save", (Type[])null, (Type[])null);

		private static readonly MethodInfo ContainerCheckAccess = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null);

		private static readonly FieldInfo ContainerWagon = AccessTools.Field(typeof(Container), "m_wagon");

		private const float GatherRange = 20f;

		private static void NotifyChanged(Inventory inv)
		{
			if (inv != null)
			{
				InventoryChanged?.Invoke(inv, new object[2] { false, false });
			}
		}

		internal static void DropCarriedItem()
		{
			InventoryGui instance = InventoryGui.instance;
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)localPlayer == (Object)null))
			{
				object? obj = DragItem?.GetValue(instance);
				ItemData val = (ItemData)((obj is ItemData) ? obj : null);
				object? obj2 = DragInventory?.GetValue(instance);
				Inventory val2 = (Inventory)((obj2 is Inventory) ? obj2 : null);
				if (val != null && val2 != null)
				{
					int amount = Mathf.Clamp((DragAmount?.GetValue(instance) is int num) ? num : val.m_stack, 1, val.m_stack);
					Recycle(localPlayer, val2, val, amount);
					SetupDragItem?.Invoke(instance, new object[3] { null, null, 0 });
					NotifyChanged(val2);
				}
			}
		}

		private static void Recycle(Player player, Inventory from, ItemData item, int amount)
		{
			Recipe val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetRecipe(item) : null);
			int num = (((Object)(object)val != (Object)null) ? Mathf.Max(1, val.m_amount) : 0);
			int num2 = (((Object)(object)val != (Object)null) ? (amount / num) : 0);
			if (num2 > 0)
			{
				Requirement[] resources = val.m_resources;
				foreach (Requirement val2 in resources)
				{
					if (val2 != null && !((Object)(object)val2.m_resItem == (Object)null) && val2.m_recover)
					{
						int num3 = Half(val2.GetAmount(item.m_quality) * num2);
						if (num3 > 0)
						{
							Give(player, ((Component)val2.m_resItem).gameObject, num3);
							Plugin.Log.LogDebug((object)$"returned {num3} {((Object)((Component)val2.m_resItem).gameObject).name}");
						}
					}
				}
			}
			GiveEpicLootRefund(player, item, amount);
			if (item.m_equipped)
			{
				((Humanoid)player).UnequipItem(item, false);
			}
			if (amount >= item.m_stack)
			{
				from.RemoveItem(item);
			}
			else
			{
				from.RemoveItem(item, amount);
			}
		}

		private static int Half(int n)
		{
			return (n + 1) / 2;
		}

		private static void Give(Player player, GameObject prefab, int amount)
		{
			//IL_002d: 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_003d: 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)
			if (!((Humanoid)player).GetInventory().AddItem(prefab, amount))
			{
				ItemDrop component = prefab.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					ItemDrop.DropItem(component.m_itemData, amount, ((Component)player).transform.position + ((Component)player).transform.forward, Quaternion.identity);
				}
			}
		}

		private static void GiveEpicLootRefund(Player player, ItemData item, int amount)
		{
			if (EnchantCostFor == null || SacrificeProductsFor == null || IsMagicItem == null || TryGetRarity == null || CostItem == null || CostAmount == null)
			{
				return;
			}
			bool flag2;
			IEnumerable enumerable;
			try
			{
				object obj = IsMagicItem.Invoke(null, new object[1] { item });
				bool flag = default(bool);
				int num;
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
				flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
				if (flag2)
				{
					object[] array = new object[2] { item, 0 };
					obj = TryGetRarity.Invoke(null, array);
					if (!(obj is bool) || !(bool)obj)
					{
						return;
					}
					object obj2 = Enum.ToObject(RarityType, array[1]);
					enumerable = EnchantCostFor.Invoke(null, new object[2] { item, obj2 }) as IEnumerable;
				}
				else
				{
					enumerable = SacrificeProductsFor.Invoke(null, new object[1] { item }) as IEnumerable;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("EpicLoot cost lookup threw, no magic materials given. " + ex.Message));
				return;
			}
			if (enumerable == null)
			{
				return;
			}
			foreach (object item2 in enumerable)
			{
				string text = CostItem.GetValue(item2) as string;
				int num2 = ((CostAmount.GetValue(item2) is int num3) ? num3 : 0) * amount;
				if (flag2)
				{
					num2 = Half(num2);
				}
				if (num2 > 0 && !string.IsNullOrEmpty(text))
				{
					GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(text) : null);
					if ((Object)(object)val == (Object)null)
					{
						Plugin.Log.LogWarning((object)("EpicLoot material is not in the ObjectDB: " + text));
						continue;
					}
					Give(player, val, num2);
					Plugin.Log.LogDebug((object)$"refunded {num2} {text}");
				}
			}
		}

		private static int VisibleRows(Inventory inv)
		{
			if (VisibleRowsGetter != null && VisibleRowsGetter.Invoke(null, null) is int num && num > 0)
			{
				return num;
			}
			return inv.GetHeight();
		}

		internal static void SortPlayerInventory()
		{
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			int num = VisibleRows(inventory);
			if (!s_boundaryLogged)
			{
				s_boundaryLogged = true;
				Plugin.Log.LogInfo((object)("sort covers rows 1-" + (num - 1) + " of " + num + " visible (" + ((VisibleRowsGetter != null) ? "row count from CarturUIHud.Slots" : "no slot mod found, using the grid height") + ")"));
			}
			List<ItemData> list = new List<ItemData>();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem.m_gridPos.y > 0 && allItem.m_gridPos.y < num)
				{
					list.Add(allItem);
				}
			}
			MergeStacks(inventory, list);
			list.Sort(Compare);
			int width = inventory.GetWidth();
			for (int i = 0; i < list.Count; i++)
			{
				list[i].m_gridPos = new Vector2i(i % width, 1 + i / width);
			}
			NotifyChanged(inventory);
		}

		internal static void SortOpenContainer()
		{
			//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)
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null || !instance.IsContainerOpen())
			{
				return;
			}
			object? obj = CurrentContainer?.GetValue(instance);
			Container val = (Container)((obj is Container) ? obj : null);
			Inventory val2 = ((val != null) ? val.GetInventory() : null);
			if (val2 != null)
			{
				GatherLikeItems(val, val2);
				List<ItemData> list = new List<ItemData>(val2.GetAllItems());
				MergeStacks(val2, list);
				list.Sort(Compare);
				int width = val2.GetWidth();
				for (int i = 0; i < list.Count; i++)
				{
					list[i].m_gridPos = new Vector2i(i % width, i / width);
				}
				NotifyChanged(val2);
			}
		}

		private static void GatherLikeItems(Container target, Inventory inv)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (ItemData allItem in inv.GetAllItems())
			{
				if (allItem?.m_shared != null)
				{
					hashSet.Add(allItem.m_shared.m_name);
				}
			}
			if (hashSet.Count == 0 || (Object)(object)Game.instance == (Object)null)
			{
				return;
			}
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			Vector3 position = ((Component)target).transform.position;
			float rangeSq = 400f;
			int num = 0;
			Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
			foreach (Container val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)target || !Reachable(val, position, rangeSq, playerID))
				{
					continue;
				}
				Inventory inventory = val.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				bool flag = false;
				foreach (ItemData item in new List<ItemData>(inventory.GetAllItems()))
				{
					if (item?.m_shared != null && hashSet.Contains(item.m_shared.m_name) && inv.CanAddItem(item, item.m_stack))
					{
						inv.MoveItemToThis(inventory, item);
						flag = true;
						num++;
					}
				}
				if (flag)
				{
					ContainerSave?.Invoke(val, null);
					NotifyChanged(inventory);
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"sort gathered {num} stack(s) into {Utils.GetPrefabName(((Component)target).gameObject)}.");
			}
		}

		private static bool Reachable(Container other, Vector3 at, float rangeSq, long playerId)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)other).transform.position - at;
			if (((Vector3)(ref val)).sqrMagnitude > rangeSq)
			{
				return false;
			}
			if (other.IsInUse() && !other.IsOwner())
			{
				return false;
			}
			object? obj = ContainerWagon?.GetValue(other);
			Vagon val2 = (Vagon)((obj is Vagon) ? obj : null);
			if (val2 != null && val2.InUse())
			{
				return false;
			}
			if ((Object)(object)((Component)other).GetComponentInParent<Player>() != (Object)null)
			{
				return false;
			}
			object obj2 = ContainerCheckAccess?.Invoke(other, new object[1] { playerId });
			if (!(obj2 is bool) || !(bool)obj2)
			{
				return false;
			}
			return PrivateArea.CheckAccess(((Component)other).transform.position, 0f, false, true);
		}

		private static void MergeStacks(Inventory inv, List<ItemData> items)
		{
			List<ItemData> list = null;
			for (int i = 0; i < items.Count; i++)
			{
				ItemData val = items[i];
				for (int j = i + 1; j < items.Count; j++)
				{
					if (val.m_stack >= val.m_shared.m_maxStackSize)
					{
						break;
					}
					ItemData val2 = items[j];
					if (val2.m_stack > 0 && SameStack(val, val2))
					{
						int num = Mathf.Min(val2.m_stack, val.m_shared.m_maxStackSize - val.m_stack);
						val.m_stack += num;
						val2.m_stack -= num;
						if (val2.m_stack == 0)
						{
							(list ?? (list = new List<ItemData>())).Add(val2);
						}
					}
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (ItemData item in list)
			{
				inv.RemoveItem(item);
				items.Remove(item);
			}
		}

		private static bool SameStack(ItemData a, ItemData b)
		{
			if (a.m_shared.m_maxStackSize > 1 && a.m_shared.m_name == b.m_shared.m_name && a.m_quality == b.m_quality)
			{
				return a.m_worldLevel == b.m_worldLevel;
			}
			return false;
		}

		private static int Compare(ItemData a, ItemData b)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			ref ItemType itemType = ref a.m_shared.m_itemType;
			object target = b.m_shared.m_itemType;
			int num = ((Enum)Unsafe.As<ItemType, ItemType>(ref itemType)/*cast due to .constrained prefix*/).CompareTo(target);
			if (num != 0)
			{
				return num;
			}
			int num2 = string.Compare(a.m_shared.m_name, b.m_shared.m_name, StringComparison.Ordinal);
			if (num2 == 0)
			{
				return b.m_quality.CompareTo(a.m_quality);
			}
			return num2;
		}
	}
}