Decompiled source of SafeItemMove v1.0.0

SafeItemMove.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("SafeItemMove")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SafeItemMove")]
[assembly: AssemblyTitle("SafeItemMove")]
[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 SafeItemMove
{
	[BepInPlugin("pieter.valheim.safeitemmove", "Safe Item Move", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class Snapshot
		{
			public Inventory From;

			public Inventory To;

			public readonly Dictionary<string, int> Counts = new Dictionary<string, int>();

			public readonly Dictionary<string, ItemData> Samples = new Dictionary<string, ItemData>();

			public bool Container;

			public string Description;
		}

		public const string Guid = "pieter.valheim.safeitemmove";

		public const string Name = "Safe Item Move";

		public const string Version = "1.0.0";

		private static ManualLogSource _log;

		private static readonly FieldRef<InventoryGui, Container> CurrentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer");

		private void Awake()
		{
			_log = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(typeof(Plugin), "pieter.valheim.safeitemmove");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Watching inventory drag and drop for vanished items.");
		}

		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Before(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, out Snapshot __state)
		{
			//IL_0028: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			__state = null;
			Inventory val = ((__instance != null) ? __instance.GetInventory() : null);
			if (val == null || fromInventory == null || item?.m_shared == null)
			{
				return;
			}
			try
			{
				ItemData itemAt = val.GetItemAt(pos.x, pos.y);
				Snapshot snapshot = new Snapshot
				{
					From = fromInventory,
					To = val
				};
				ItemData[] array = (ItemData[])(object)new ItemData[2] { item, itemAt };
				foreach (ItemData val2 in array)
				{
					if (val2?.m_shared != null && !snapshot.Counts.ContainsKey(val2.m_shared.m_name))
					{
						snapshot.Counts[val2.m_shared.m_name] = Count(snapshot, val2.m_shared.m_name);
						snapshot.Samples[val2.m_shared.m_name] = val2.Clone();
					}
				}
				Container val3 = (((Object)(object)InventoryGui.instance != (Object)null) ? CurrentContainer.Invoke(InventoryGui.instance) : null);
				Inventory val4 = (((Object)(object)val3 != (Object)null) ? val3.GetInventory() : null);
				snapshot.Container = val4 != null && (fromInventory == val4 || val == val4);
				snapshot.Description = $"{item.m_shared.m_name} x{amount} from ({item.m_gridPos.x},{item.m_gridPos.y}) " + $"to ({pos.x},{pos.y})" + ((itemAt != null) ? $" holding {itemAt.m_shared.m_name} x{itemAt.m_stack}" : "");
				__state = snapshot;
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("Could not snapshot a drop: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		[HarmonyFinalizer]
		[HarmonyPriority(0)]
		private static Exception After(Exception __exception, Snapshot __state)
		{
			if (__state == null)
			{
				return __exception;
			}
			try
			{
				foreach (KeyValuePair<string, int> count in __state.Counts)
				{
					int num = count.Value - Count(__state, count.Key);
					if (num > 0)
					{
						string key = count.Key;
						if (__state.Container)
						{
							_log.LogWarning((object)$"{key} x{num} not back yet after moving {__state.Description} (container, left alone)");
							continue;
						}
						_log.LogWarning((object)$"{key} x{num} vanished while moving {__state.Description}; giving it back.");
						GiveBack(__state, __state.Samples[count.Key], num);
					}
				}
			}
			catch (Exception ex)
			{
				_log.LogWarning((object)("Could not check a drop: " + ex.Message));
			}
			return __exception;
		}

		private static int Count(Snapshot s, string name)
		{
			int num = Sum(s.From, name);
			if (s.To != s.From)
			{
				num += Sum(s.To, name);
			}
			return num;
		}

		private static int Sum(Inventory inventory, string name)
		{
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem?.m_shared != null && allItem.m_shared.m_name == name)
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		private static void GiveBack(Snapshot s, ItemData sample, int missing)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_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_0096: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			int val = Math.Max(1, sample.m_shared.m_maxStackSize);
			while (missing > 0)
			{
				ItemData val2 = sample.Clone();
				val2.m_stack = Math.Min(val, missing);
				missing -= val2.m_stack;
				if (!s.From.AddItem(val2) && (s.To == s.From || !s.To.AddItem(val2)))
				{
					Player localPlayer = Player.m_localPlayer;
					if (!((Object)(object)localPlayer == (Object)null))
					{
						Vector3 val3 = ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward + Vector3.up;
						ItemDrop.DropItem(val2, val2.m_stack, val3, Quaternion.identity);
						_log.LogWarning((object)$"No room for {val2.m_shared.m_name} x{val2.m_stack}; dropped it at your feet.");
					}
				}
			}
		}
	}
}