Decompiled source of CtrlClickSort v1.0.0

plugins/CtrlClickSort.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CtrlClickSort
{
	internal static class ContainerTracker
	{
		private static readonly HashSet<Container> Containers = new HashSet<Container>();

		internal static void Add(Container container)
		{
			Containers.Add(container);
		}

		internal static List<ChestCandidate> FindAccessibleChests(Vector3 point, float range, long playerId)
		{
			//IL_004d: 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)
			Containers.RemoveWhere((Container c) => !Object.op_Implicit((Object)(object)c));
			List<ChestCandidate> list = new List<ChestCandidate>();
			foreach (Container container in Containers)
			{
				if (IsPlayerChest(container))
				{
					float num = Vector3.Distance(point, ((Component)container).transform.position);
					if (!(num > range) && HasAccess(container, playerId))
					{
						list.Add(new ChestCandidate(container, num));
					}
				}
			}
			list.Sort(delegate(ChestCandidate a, ChestCandidate b)
			{
				float distance = a.Distance;
				return distance.CompareTo(b.Distance);
			});
			return list;
		}

		private static bool IsPlayerChest(Container container)
		{
			if (!Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.IsValid() || container.GetInventory() == null)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)container.m_piece) || !container.m_piece.IsPlacedByPlayer())
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)((Component)container).GetComponent<TombStone>()))
			{
				return !Object.op_Implicit((Object)(object)((Component)container).GetComponentInParent<Player>());
			}
			return false;
		}

		private static bool HasAccess(Container container, long playerId)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, false, false))
			{
				return false;
			}
			return container.CheckAccess(playerId);
		}

		internal static bool IsInUse(Container container)
		{
			if (Object.op_Implicit((Object)(object)container.m_wagon) && container.m_wagon.InUse())
			{
				return true;
			}
			ZNetView nview = container.m_nview;
			if (nview.IsOwner())
			{
				return container.IsInUse();
			}
			if (nview.HasOwner())
			{
				return nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1;
			}
			return false;
		}
	}
	internal readonly struct ChestCandidate
	{
		public readonly Container Container;

		public readonly float Distance;

		public ChestCandidate(Container container, float distance)
		{
			Container = container;
			Distance = distance;
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class ContainerAwakePatch
	{
		private static void Postfix(Container __instance)
		{
			if (__instance.GetInventory() != null)
			{
				ContainerTracker.Add(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
	internal static class InventoryGuiOnSelectedItemPatch
	{
		private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldHandle(__instance, grid, item, mod))
			{
				return true;
			}
			return !StackToChest.TryStore(__instance, Player.m_localPlayer, item);
		}

		private static bool ShouldHandle(InventoryGui gui, InventoryGrid grid, ItemData item, Modifier mod)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_002e: 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)
			if (Object.op_Implicit((Object)(object)gui.m_dragGo) || item == null || (Object)(object)gui.m_currentContainer != (Object)null)
			{
				return false;
			}
			if ((int)mod != 2 && (int)mod != 0)
			{
				return false;
			}
			if (!ZInput.GetKey(Plugin.ModifierKey.Value, true))
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsTeleporting() || grid.GetInventory() != ((Humanoid)localPlayer).GetInventory())
			{
				return false;
			}
			return !item.m_shared.m_questItem;
		}
	}
	internal sealed class Messages
	{
		public string Moved;

		public string Remaining;

		public string Equipped;

		public string NoChestHasItem;

		public string InUse;

		public string NoSpace;

		private static readonly Messages English = new Messages
		{
			Moved = "{0} x{1} → {2} ({3} m)",
			Remaining = "{0} x{1} left in inventory",
			Equipped = "{0}: equipped items are not moved",
			NoChestHasItem = "No nearby chest contains {0}",
			InUse = "The chest with {0} is being used by another player",
			NoSpace = "No room for {0} in nearby chests"
		};

		private static readonly Messages Slovak = new Messages
		{
			Moved = "{0} x{1} → {2} ({3} m)",
			Remaining = "{0} x{1} zostáva v inventári",
			Equipped = "{0}: vybavené predmety sa nepresúvajú",
			NoChestHasItem = "Žiadna truhlica v okolí neobsahuje {0}",
			InUse = "Truhlicu s {0} práve používa iný hráč",
			NoSpace = "V truhliciach s {0} nie je miesto"
		};

		private static readonly Messages Czech = new Messages
		{
			Moved = "{0} x{1} → {2} ({3} m)",
			Remaining = "{0} x{1} zůstává v inventáři",
			Equipped = "{0}: vybavené předměty se nepřesouvají",
			NoChestHasItem = "Žádná truhla v okolí neobsahuje {0}",
			InUse = "Truhlu s {0} právě používá jiný hráč",
			NoSpace = "V truhlách s {0} není místo"
		};

		internal static Messages Current
		{
			get
			{
				string selectedLanguage = Localization.instance.GetSelectedLanguage();
				if (!(selectedLanguage == "Slovak"))
				{
					if (selectedLanguage == "Czech")
					{
						return Czech;
					}
					return English;
				}
				return Slovak;
			}
		}
	}
	[BepInPlugin("lukas.CtrlClickSort", "CtrlClickSort", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "lukas.CtrlClickSort";

		public const string PluginName = "CtrlClickSort";

		public const string PluginVersion = "1.0.0";

		internal static ConfigEntry<float> Radius;

		internal static ConfigEntry<KeyCode> ModifierKey;

		internal static ConfigEntry<bool> ShowMessages;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			Radius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Radius", 15f, new ConfigDescription("Radius in metres to search for chests.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			ModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ModifierKey", (KeyCode)306, "Key to hold while left-clicking an item in your inventory. Don't use Shift, vanilla uses it to split stacks.");
			ShowMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMessages", true, "Show on-screen messages about what was moved (or why nothing was).");
			_harmony = new Harmony("lukas.CtrlClickSort");
			_harmony.PatchAll(typeof(Plugin).Assembly);
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class StackToChest
	{
		internal static bool TryStore(InventoryGui gui, Player player, ItemData item)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			List<ChestCandidate> list = ContainerTracker.FindAccessibleChests(((Component)player).transform.position, Plugin.Radius.Value, playerID);
			if (list.Count == 0)
			{
				return false;
			}
			string text = Localize(item.m_shared.m_name);
			Messages current = Messages.Current;
			if (((Humanoid)player).IsItemEquiped(item))
			{
				ShowMessage(player, string.Format(current.Equipped, text));
				return true;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<string> list2 = new List<string>();
			bool flag = false;
			bool flag2 = false;
			foreach (ChestCandidate item2 in list)
			{
				Container container = item2.Container;
				container.Load();
				if (!container.GetInventory().ContainsItemByName(item.m_shared.m_name))
				{
					continue;
				}
				flag = true;
				if (ContainerTracker.IsInUse(container))
				{
					flag2 = true;
					continue;
				}
				int num = MoveInto(container, inventory, item);
				if (num > 0)
				{
					list2.Add(string.Format(current.Moved, text, num, Localize(container.m_name), Mathf.RoundToInt(item2.Distance)));
				}
				if (inventory.ContainsItem(item))
				{
					continue;
				}
				break;
			}
			if (list2.Count > 0)
			{
				gui.m_moveItemEffects.Create(((Component)gui).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
				if (inventory.ContainsItem(item))
				{
					list2.Add(string.Format(current.Remaining, text, item.m_stack));
				}
				ShowMessage(player, string.Join("\n", list2));
			}
			else if (!flag)
			{
				ShowMessage(player, string.Format(current.NoChestHasItem, text));
			}
			else if (flag2)
			{
				ShowMessage(player, string.Format(current.InUse, text));
			}
			else
			{
				ShowMessage(player, string.Format(current.NoSpace, text));
			}
			return true;
		}

		private static int MoveInto(Container container, Inventory playerInventory, ItemData item)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			container.m_nview.ClaimOwnership();
			int stack = item.m_stack;
			bool num = container.GetInventory().AddItem(item);
			int num2 = (num ? stack : (stack - item.m_stack));
			if (num)
			{
				playerInventory.RemoveItem(item);
			}
			else if (num2 > 0)
			{
				playerInventory.Changed(false, false);
			}
			if (num2 > 0)
			{
				ZDOMan.instance.ForceSendZDO(container.m_nview.GetZDO().m_uid);
			}
			return num2;
		}

		private static string Localize(string text)
		{
			return Localization.instance.Localize(text);
		}

		private static void ShowMessage(Player player, string message)
		{
			if (Plugin.ShowMessages.Value)
			{
				((Character)player).Message((MessageType)2, message, 0, (Sprite)null, false);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}