Decompiled source of ExpeditionReady ChestSort v1.0.0

plugins\ExpeditionReady_ChestSort\ExpeditionReady_ChestSort.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ExpeditionReady_ChestSort")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ExpeditionReady_ChestSort")]
[assembly: AssemblyCopyright("Copyright © Goldenrevolver 2022, modifications © LEGIOmods 2026")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially created with the assistance of Generative AI for code changes, localization, documentation, and package preparation.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "OpenAI")]
[assembly: AssemblyMetadata("AI_Agent", "OpenAI Codex")]
[assembly: ComVisible(false)]
[assembly: Guid("beeb50d8-ebd2-4791-9866-4bbf2d810422")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ExpeditionReadyChestSort;

[BepInPlugin("legiomods.expeditionreadychestsort", "ExpeditionReady_ChestSort", "1.0.0")]
public class ExpeditionReadyChestSortPlugin : BaseUnityPlugin
{
	public const string GUID = "legiomods.expeditionreadychestsort";

	public const string NAME = "ExpeditionReady_ChestSort";

	public const string VERSION = "1.0.0";

	private static readonly FieldInfo HumanoidInventoryField = AccessTools.Field(typeof(Humanoid), "m_inventory");

	private static readonly FieldInfo InventoryItemsField = AccessTools.Field(typeof(Inventory), "m_inventory");

	private static readonly FieldInfo ContainerInventoryField = AccessTools.Field(typeof(Container), "m_inventory");

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

	private static readonly FieldInfo PlayerGridField = AccessTools.Field(typeof(InventoryGui), "m_playerGrid");

	private static readonly MethodInfo InventoryChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null);

	private ConfigEntry<bool> modEnabled;

	private ConfigEntry<float> nearbyRange;

	private ConfigEntry<bool> includeHotbar;

	private ConfigEntry<bool> mergeStacksBeforeSort;

	private Button restockButton;

	private Button readyButton;

	private Button sortButton;

	private void Awake()
	{
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable ExpeditionReady_ChestSort.");
		nearbyRange = ((BaseUnityPlugin)this).Config.Bind<float>("Restock", "NearbyChestRange", 15f, "Range in meters for nearby chest restock.");
		includeHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("Restock", "IncludeHotbar", true, "Restock stacks in the hotbar.");
		mergeStacksBeforeSort = ((BaseUnityPlugin)this).Config.Bind<bool>("Sort", "MergeStacksBeforeSort", true, "Merge equal item stacks before sorting a chest.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ExpeditionReady_ChestSort 1.0.0 loaded by BepInEx. GUID=legiomods.expeditionreadychestsort");
	}

	private void Update()
	{
		if (modEnabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)InventoryGui.instance == (Object)null) && InventoryGui.IsVisible())
		{
			EnsureButtons();
		}
	}

	private void EnsureButtons()
	{
		EnsureRestockButton();
		EnsurePortalButton();
		EnsureSortButton();
		if ((Object)(object)sortButton != (Object)null)
		{
			((Component)sortButton).gameObject.SetActive((Object)(object)GetCurrentContainer() != (Object)null);
		}
	}

	private void EnsureRestockButton()
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		Button takeAllButton = InventoryGui.instance.m_takeAllButton;
		if ((Object)(object)takeAllButton == (Object)null)
		{
			return;
		}
		if ((Object)(object)restockButton == (Object)null)
		{
			restockButton = CreateButton(takeAllButton, "ExpeditionReadyChestSort_RestockButton", Text("Restock", "Auffüllen"), (UnityAction)delegate
			{
				Restock(Player.m_localPlayer);
			});
		}
		SetButtonLabel(restockButton, Text("Restock", "Auffüllen"));
		((Component)restockButton).gameObject.SetActive(true);
		PositionPlayerSideButton(restockButton, takeAllButton, 0);
	}

	private void EnsurePortalButton()
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		Button takeAllButton = InventoryGui.instance.m_takeAllButton;
		if ((Object)(object)takeAllButton == (Object)null)
		{
			return;
		}
		if ((Object)(object)readyButton == (Object)null)
		{
			readyButton = CreateButton(takeAllButton, "ExpeditionReadyChestSort_PortalButton", Text("Portal ✓", "Portal ✓"), (UnityAction)delegate
			{
				PortalAuffuellen(Player.m_localPlayer);
			});
		}
		SetButtonLabel(readyButton, Text("Portal ✓", "Portal ✓"));
		((Component)readyButton).gameObject.SetActive(true);
		PositionPlayerSideButton(readyButton, takeAllButton, 1);
	}

	private void EnsureSortButton()
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		InventoryGui instance = InventoryGui.instance;
		Button takeAllButton = instance.m_takeAllButton;
		RectTransform stackAllButtonRectTransform = GetStackAllButtonRectTransform(instance);
		if (!((Object)(object)takeAllButton == (Object)null))
		{
			if ((Object)(object)sortButton == (Object)null)
			{
				sortButton = CreateButton(takeAllButton, "ExpeditionReadyChestSort_SortButton", Text("Sort", "Sortieren"), new UnityAction(SortOpenChest));
			}
			SetButtonLabel(sortButton, Text("Sort", "Sortieren"));
			PositionSortButton(sortButton, stackAllButtonRectTransform ?? ((Component)takeAllButton).GetComponent<RectTransform>());
		}
	}

	private static Button CreateButton(Button template, string objectName, string label, UnityAction onClick)
	{
		GameObject obj = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent);
		((Object)obj).name = objectName;
		obj.SetActive(true);
		Button component = obj.GetComponent<Button>();
		((UnityEventBase)component.onClick).RemoveAllListeners();
		((UnityEvent)component.onClick).AddListener(onClick);
		SetButtonLabel(component, label);
		return component;
	}

	private static void SetButtonLabel(Button button, string label)
	{
		if (!((Object)(object)button == (Object)null))
		{
			Text[] componentsInChildren = ((Component)button).gameObject.GetComponentsInChildren<Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = label;
			}
			TMP_Text[] componentsInChildren2 = ((Component)button).gameObject.GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].text = label;
			}
		}
	}

	private static void PositionPlayerSideButton(Button button, Button template, int row)
	{
		//IL_003f: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		RectTransform playerGridRectTransform = GetPlayerGridRectTransform();
		RectTransform component = ((Component)button).GetComponent<RectTransform>();
		RectTransform component2 = ((Component)template).GetComponent<RectTransform>();
		if (!((Object)(object)component == (Object)null) && !((Object)(object)playerGridRectTransform == (Object)null) && !((Object)(object)component2 == (Object)null))
		{
			((Transform)component).SetParent(((Transform)playerGridRectTransform).parent, false);
			component.anchorMin = playerGridRectTransform.anchorMin;
			component.anchorMax = playerGridRectTransform.anchorMin;
			component.pivot = new Vector2(0.5f, 1f);
			component.sizeDelta = new Vector2(Math.Max(component2.sizeDelta.x, 170f), component2.sizeDelta.y);
			Vector2 anchoredPosition = playerGridRectTransform.anchoredPosition;
			Rect rect = playerGridRectTransform.rect;
			component.anchoredPosition = anchoredPosition + new Vector2(((Rect)(ref rect)).width + 160f, 112f - (float)row * 38f);
			ClampToCanvas(component, 8f);
		}
	}

	private static void PositionSortButton(Button button, RectTransform templateTransform)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = ((Component)button).GetComponent<RectTransform>();
		if (!((Object)(object)component == (Object)null) && !((Object)(object)templateTransform == (Object)null))
		{
			((Transform)component).SetParent(((Transform)templateTransform).parent, false);
			component.anchorMin = templateTransform.anchorMin;
			component.anchorMax = templateTransform.anchorMax;
			component.pivot = new Vector2(0f, 0.5f);
			component.sizeDelta = templateTransform.sizeDelta;
			Canvas.ForceUpdateCanvases();
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			templateTransform.GetWorldCorners(array);
			((Transform)component).position = new Vector3(array[2].x + 25f, (array[0].y + array[2].y) * 0.5f, array[2].z);
		}
	}

	private static RectTransform GetStackAllButtonRectTransform(InventoryGui gui)
	{
		if ((Object)(object)gui == (Object)null)
		{
			return null;
		}
		Button[] componentsInChildren = ((Component)gui).GetComponentsInChildren<Button>(true);
		foreach (Button val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)gui.m_takeAllButton) && ((Component)val).gameObject.activeInHierarchy)
			{
				string text = GetButtonLabel(((Component)val).gameObject).ToLowerInvariant();
				if (text.Contains("stapel") || text.Contains("stack"))
				{
					return ((Component)val).GetComponent<RectTransform>();
				}
			}
		}
		if (!((Object)(object)gui.m_stackAllButton == (Object)null))
		{
			return ((Component)gui.m_stackAllButton).GetComponent<RectTransform>();
		}
		return null;
	}

	private static string GetButtonLabel(GameObject buttonObject)
	{
		List<string> list = new List<string>();
		Text[] componentsInChildren = buttonObject.GetComponentsInChildren<Text>(true);
		foreach (Text val in componentsInChildren)
		{
			if (!string.IsNullOrWhiteSpace(val.text))
			{
				list.Add(val.text);
			}
		}
		TMP_Text[] componentsInChildren2 = buttonObject.GetComponentsInChildren<TMP_Text>(true);
		foreach (TMP_Text val2 in componentsInChildren2)
		{
			if (!string.IsNullOrWhiteSpace(val2.text))
			{
				list.Add(val2.text);
			}
		}
		return string.Join(" ", list);
	}

	private static void ClampToCanvas(RectTransform rectTransform, float padding)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		Canvas componentInParent = ((Component)rectTransform).GetComponentInParent<Canvas>();
		RectTransform val = (RectTransform)(((Object)(object)componentInParent == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
		if (!((Object)(object)val == (Object)null))
		{
			Canvas.ForceUpdateCanvases();
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			Vector3[] array2 = (Vector3[])(object)new Vector3[4];
			rectTransform.GetWorldCorners(array);
			val.GetWorldCorners(array2);
			Vector3 zero = Vector3.zero;
			if (array[0].x < array2[0].x + padding)
			{
				zero.x += array2[0].x + padding - array[0].x;
			}
			if (array[2].x > array2[2].x - padding)
			{
				zero.x -= array[2].x - (array2[2].x - padding);
			}
			if (array[0].y < array2[0].y + padding)
			{
				zero.y += array2[0].y + padding - array[0].y;
			}
			if (array[2].y > array2[2].y - padding)
			{
				zero.y -= array[2].y - (array2[2].y - padding);
			}
			((Transform)rectTransform).position = ((Transform)rectTransform).position + zero;
		}
	}

	private void Restock(Player player)
	{
		if ((Object)(object)player == (Object)null || ((Character)player).IsTeleporting())
		{
			return;
		}
		Inventory playerInventory = GetPlayerInventory(player);
		List<ItemData> list = (from item in GetInventoryItems(playerInventory)
			where ShouldRestock(item)
			orderby item.m_gridPos.y, item.m_gridPos.x
			select item).ToList();
		if (list.Count == 0)
		{
			ShowMessage(player, Text("No restockable stacks in inventory.", "Keine auffüllbaren Stapel im Inventar."));
			return;
		}
		List<Container> restockContainers = GetRestockContainers(player);
		int num = 0;
		foreach (Container item in restockContainers)
		{
			Inventory containerInventory = GetContainerInventory(item);
			if (containerInventory != null)
			{
				num += RestockFromInventory(playerInventory, containerInventory, list);
				if (list.All((ItemData item) => item.m_stack >= item.m_shared.m_maxStackSize))
				{
					break;
				}
			}
		}
		if (num > 0)
		{
			MarkInventoryChanged(playerInventory);
		}
		ShowMessage(player, (num > 0) ? string.Format(Text("Restock: moved {0} items.", "Auffüllen: {0} Items bewegt."), num) : Text("Restock: nothing matching found.", "Auffüllen: nichts Passendes gefunden."));
	}

	private bool ShouldRestock(ItemData item)
	{
		if (item != null && item.m_shared != null && item.m_shared.m_maxStackSize > 1 && item.m_stack < item.m_shared.m_maxStackSize && (includeHotbar.Value || item.m_gridPos.y > 0) && (item.m_customData == null || item.m_customData.Count == 0) && !IsWoodItem(item))
		{
			return IsRestockCategory(item);
		}
		return false;
	}

	private static bool IsRestockCategory(ItemData item)
	{
		//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_000e: Invalid comparison between Unknown and I4
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Invalid comparison between Unknown and I4
		ItemType itemType = item.m_shared.m_itemType;
		if ((int)itemType != 2)
		{
			return (int)itemType == 9;
		}
		return true;
	}

	private static bool IsWoodItem(ItemData item)
	{
		return MatchesAnyName(item, new string[3] { "$item_wood", "Wood", "Holz" });
	}

	private List<Container> GetRestockContainers(Player player)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		List<Container> list = new List<Container>();
		Container currentContainer = GetCurrentContainer();
		if ((Object)(object)currentContainer != (Object)null)
		{
			list.Add(currentContainer);
		}
		float num = Math.Max(0f, nearbyRange.Value);
		if (num <= 0f)
		{
			return list;
		}
		Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		foreach (Container val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)currentContainer) && GetContainerInventory(val) != null && Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position) <= num)
			{
				list.Add(val);
			}
		}
		return list;
	}

	private static int RestockFromInventory(Inventory playerInventory, Inventory sourceInventory, List<ItemData> targets)
	{
		int num = 0;
		for (int num2 = targets.Count - 1; num2 >= 0; num2--)
		{
			ItemData val = targets[num2];
			int num3 = val.m_shared.m_maxStackSize - val.m_stack;
			if (num3 <= 0)
			{
				targets.RemoveAt(num2);
			}
			else
			{
				List<ItemData> inventoryItems = GetInventoryItems(sourceInventory);
				int num4 = inventoryItems.Count - 1;
				while (num4 >= 0 && num3 > 0)
				{
					ItemData val2 = inventoryItems[num4];
					if (CanStack(val2, val))
					{
						int num5 = Math.Min(num3, val2.m_stack);
						playerInventory.MoveItemToThis(sourceInventory, val2, num5, val.m_gridPos.x, val.m_gridPos.y);
						num += num5;
						num3 -= num5;
					}
					num4--;
				}
				if (num3 <= 0)
				{
					targets.RemoveAt(num2);
				}
			}
		}
		MarkInventoryChanged(sourceInventory);
		return num;
	}

	private static bool CanStack(ItemData source, ItemData target)
	{
		if (source != null && target != null && source.m_shared != null && target.m_shared != null && source.m_shared.m_name == target.m_shared.m_name && source.m_quality == target.m_quality)
		{
			if (source.m_customData != null)
			{
				return source.m_customData.Count == 0;
			}
			return true;
		}
		return false;
	}

	private void PortalAuffuellen(Player player)
	{
		if (!((Object)(object)player == (Object)null) && !((Character)player).IsTeleporting())
		{
			Inventory playerInventory = GetPlayerInventory(player);
			List<Container> restockContainers = GetRestockContainers(player);
			int num = 0;
			num += PullToTargetCount(playerInventory, restockContainers, new string[4] { "$item_surtlingcore", "SurtlingCore", "Surtling core", "Surtlingkern" }, 2);
			num += PullToTargetCount(playerInventory, restockContainers, new string[3] { "$item_wood", "Wood", "Holz" }, 10);
			num += PullToTargetCount(playerInventory, restockContainers, new string[4] { "$item_greydwarfeye", "GreydwarfEye", "Greydwarf eye", "Grauzwergenauge" }, 10);
			num += PullToTargetCount(playerInventory, restockContainers, new string[4] { "$item_finewood", "FineWood", "Fine wood", "Feinholz" }, 20);
			if (num > 0)
			{
				MarkInventoryChanged(playerInventory);
			}
			ShowMessage(player, (num > 0) ? string.Format(Text("Portal ✓: moved {0} items.", "Portal ✓: {0} Items bewegt."), num) : Text("Portal ✓: nothing needed or nothing found.", "Portal ✓: nichts benoetigt oder nichts gefunden."));
		}
	}

	private static int PullToTargetCount(Inventory playerInventory, List<Container> containers, string[] itemNames, int targetCount)
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		int num = CountItems(playerInventory, itemNames);
		int num2 = targetCount - num;
		int num3 = 0;
		if (num2 <= 0)
		{
			return 0;
		}
		foreach (Container container in containers)
		{
			Inventory containerInventory = GetContainerInventory(container);
			if (containerInventory == null)
			{
				continue;
			}
			List<ItemData> inventoryItems = GetInventoryItems(containerInventory);
			int num4 = inventoryItems.Count - 1;
			while (num4 >= 0 && num2 > 0)
			{
				ItemData val = inventoryItems[num4];
				if (MatchesAnyName(val, itemNames))
				{
					if (!TryFindDestinationSlot(playerInventory, val, out var destination))
					{
						return num3;
					}
					int num5 = Math.Min(num2, val.m_stack);
					playerInventory.MoveItemToThis(containerInventory, val, num5, destination.x, destination.y);
					num3 += num5;
					num2 -= num5;
				}
				num4--;
			}
			if (num3 > 0)
			{
				MarkInventoryChanged(containerInventory);
			}
			if (num2 <= 0)
			{
				break;
			}
		}
		return num3;
	}

	private static int CountItems(Inventory inventory, string[] itemNames)
	{
		return (from item in GetInventoryItems(inventory)
			where MatchesAnyName(item, itemNames)
			select item).Sum((ItemData item) => item.m_stack);
	}

	private static bool TryFindDestinationSlot(Inventory inventory, ItemData source, out Vector2i destination)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: 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)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		foreach (ItemData inventoryItem in GetInventoryItems(inventory))
		{
			if (CanStack(source, inventoryItem) && inventoryItem.m_stack < inventoryItem.m_shared.m_maxStackSize)
			{
				destination = inventoryItem.m_gridPos;
				return true;
			}
		}
		HashSet<Vector2i> hashSet = new HashSet<Vector2i>(from item in GetInventoryItems(inventory)
			select item.m_gridPos);
		Vector2i val = default(Vector2i);
		for (int num = 0; num < inventory.GetHeight(); num++)
		{
			for (int num2 = 0; num2 < inventory.GetWidth(); num2++)
			{
				((Vector2i)(ref val))..ctor(num2, num);
				if (!hashSet.Contains(val))
				{
					destination = val;
					return true;
				}
			}
		}
		destination = default(Vector2i);
		return false;
	}

	private static bool MatchesAnyName(ItemData item, string[] itemNames)
	{
		if (item?.m_shared == null)
		{
			return false;
		}
		string internalName = item.m_shared.m_name ?? string.Empty;
		string localizedName = ((Localization.instance == null) ? internalName : Localization.instance.Localize(internalName));
		return itemNames.Any((string name) => string.Equals(internalName, name, StringComparison.OrdinalIgnoreCase) || string.Equals(localizedName, name, StringComparison.CurrentCultureIgnoreCase));
	}

	private void SortOpenChest()
	{
		Inventory containerInventory = GetContainerInventory(GetCurrentContainer());
		if (containerInventory == null)
		{
			ShowMessage(Player.m_localPlayer, Text("No chest open.", "Keine Kiste geöffnet."));
			return;
		}
		SortInventory(containerInventory);
		ShowMessage(Player.m_localPlayer, Text("Chest sorted.", "Kiste sortiert."));
	}

	private void SortInventory(Inventory inventory)
	{
		//IL_0024: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
		if (mergeStacksBeforeSort.Value)
		{
			MergeStacks(inventory);
		}
		List<Vector2i> list = new List<Vector2i>();
		for (int i = 0; i < inventory.GetHeight(); i++)
		{
			for (int j = 0; j < inventory.GetWidth(); j++)
			{
				list.Add(new Vector2i(j, i));
			}
		}
		List<ItemData> list2 = GetInventoryItems(inventory).OrderBy<ItemData, string>((ItemData item) => LocalizedName(item), StringComparer.CurrentCultureIgnoreCase).ThenBy((ItemData item) => item.m_shared.m_name).ThenByDescending((ItemData item) => item.m_quality)
			.ThenByDescending((ItemData item) => item.m_stack)
			.ToList();
		for (int num = 0; num < list2.Count && num < list.Count; num++)
		{
			list2[num].m_gridPos = list[num];
		}
		MarkInventoryChanged(inventory);
	}

	private static string LocalizedName(ItemData item)
	{
		if (item?.m_shared == null)
		{
			return string.Empty;
		}
		if (Localization.instance == null)
		{
			return item.m_shared.m_name;
		}
		return Localization.instance.Localize(item.m_shared.m_name);
	}

	private static void MergeStacks(Inventory inventory)
	{
		foreach (List<ItemData> item in from item in GetInventoryItems(inventory).ToList()
			where item?.m_shared != null && item.m_shared.m_maxStackSize > 1 && (item.m_customData == null || item.m_customData.Count == 0)
			group item by item.m_shared.m_name + "|" + item.m_quality into @group
			select @group.ToList())
		{
			if (item.Count <= 1)
			{
				continue;
			}
			int num = item.Sum((ItemData item) => item.m_stack);
			int maxStackSize = item[0].m_shared.m_maxStackSize;
			foreach (ItemData item2 in item)
			{
				item2.m_stack = Math.Min(maxStackSize, num);
				num -= item2.m_stack;
				if (item2.m_stack <= 0)
				{
					inventory.RemoveItem(item2);
				}
			}
		}
	}

	private static void ShowMessage(Player player, string message)
	{
		if ((Object)(object)player != (Object)null)
		{
			((Character)player).Message((MessageType)2, message, 0, (Sprite)null);
		}
	}

	private static string Text(string english, string german)
	{
		if (!IsGerman())
		{
			return english;
		}
		return german;
	}

	private static bool IsGerman()
	{
		string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : string.Empty);
		if (!text.Equals("German", StringComparison.OrdinalIgnoreCase) && !text.Equals("Deutsch", StringComparison.OrdinalIgnoreCase))
		{
			return text.StartsWith("de", StringComparison.OrdinalIgnoreCase);
		}
		return true;
	}

	private static Inventory GetPlayerInventory(Player player)
	{
		object? obj = HumanoidInventoryField?.GetValue(player);
		return (Inventory)((obj is Inventory) ? obj : null);
	}

	private static Inventory GetContainerInventory(Container container)
	{
		if (!((Object)(object)container == (Object)null))
		{
			object? obj = ContainerInventoryField?.GetValue(container);
			return (Inventory)((obj is Inventory) ? obj : null);
		}
		return null;
	}

	private static Container GetCurrentContainer()
	{
		object? obj = CurrentContainerField?.GetValue(InventoryGui.instance);
		return (Container)((obj is Container) ? obj : null);
	}

	private static RectTransform GetPlayerGridRectTransform()
	{
		object? obj = PlayerGridField?.GetValue(InventoryGui.instance);
		Component val = (Component)((obj is Component) ? obj : null);
		if (!((Object)(object)val == (Object)null))
		{
			return val.GetComponent<RectTransform>();
		}
		return null;
	}

	private static List<ItemData> GetInventoryItems(Inventory inventory)
	{
		if (inventory == null)
		{
			return new List<ItemData>();
		}
		return (InventoryItemsField?.GetValue(inventory) as List<ItemData>) ?? new List<ItemData>();
	}

	private static void MarkInventoryChanged(Inventory inventory)
	{
		InventoryChangedMethod?.Invoke(inventory, null);
	}
}