Decompiled source of EpicLootCraftFromContainers v0.1.0

EpicLootCraftFromContainers.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.Versioning;
using BepInEx;
using BepInEx.Logging;
using CraftFromContainers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("EpicLootCraftFromContainers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EpicLootCraftFromContainers")]
[assembly: AssemblyTitle("EpicLootCraftFromContainers")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EpicLootCraftFromContainers
{
	[BepInPlugin("buldosik.EpicLootCraftFromContainers", "EpicLoot CraftFromContainers Bridge", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "buldosik.EpicLootCraftFromContainers";

		public const string PluginName = "EpicLoot CraftFromContainers Bridge";

		public const string PluginVersion = "0.1.0";

		private const string ProviderId = "buldosik.EpicLootCraftFromContainers";

		private static ManualLogSource Log;

		private static MethodInfo? _unregisterProvider;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				RegisterEpicLootProvider();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to register EpicLoot inventory provider: {arg}");
			}
		}

		private void OnDestroy()
		{
			try
			{
				_unregisterProvider?.Invoke(null, new object[1] { "buldosik.EpicLootCraftFromContainers" });
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to unregister EpicLoot inventory provider: " + ex.GetBaseException().Message));
			}
		}

		private static void RegisterEpicLootProvider()
		{
			Type type = Type.GetType("EpicLoot.API, EpicLoot");
			if (type == null)
			{
				Log.LogError((object)"EpicLoot.API was not found.");
				return;
			}
			Type[] types = new Type[5]
			{
				typeof(string),
				typeof(Func<List<ItemData>>),
				typeof(Func<string, int>),
				typeof(Func<string, int, int>),
				typeof(Func<ItemData, int, int>)
			};
			MethodInfo method = type.GetMethod("RegisterInventoryProvider", BindingFlags.Static | BindingFlags.Public, null, types, null);
			if (method == null || method.ReturnType != typeof(bool))
			{
				Log.LogError((object)"EpicLoot RegisterInventoryProvider API with the expected signature was not found.");
				return;
			}
			if (!(bool)method.Invoke(null, new object[5]
			{
				"buldosik.EpicLootCraftFromContainers",
				new Func<List<ItemData>>(GetItems),
				new Func<string, int>(CountItem),
				new Func<string, int, int>(RemoveItem),
				new Func<ItemData, int, int>(RemoveExactItem)
			}))
			{
				Log.LogError((object)"EpicLoot rejected the CraftFromContainers inventory provider registration.");
				return;
			}
			_unregisterProvider = type.GetMethod("UnregisterInventoryProvider", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
			Log.LogInfo((object)"Registered CraftFromContainers as an EpicLoot enchanting material provider.");
		}

		private static bool CfcIsActive()
		{
			try
			{
				Type typeFromHandle = typeof(BepInExPlugin);
				object obj = typeFromHandle.GetField("modEnabled", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
				if (obj != null)
				{
					object obj2 = obj.GetType().GetProperty("Value")?.GetValue(obj);
					if (obj2 is bool && !(bool)obj2)
					{
						return false;
					}
				}
				MethodInfo method = typeFromHandle.GetMethod("AllowByKey", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null && method.Invoke(null, null) is bool result)
				{
					return result;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not read CraftFromContainers enabled state: " + ex.GetBaseException().Message));
			}
			return true;
		}

		private static bool LeaveOneEnabled()
		{
			try
			{
				object obj = typeof(BepInExPlugin).GetField("leaveOne", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
				object obj2 = (obj?.GetType().GetProperty("Value"))?.GetValue(obj);
				if (obj2 is bool)
				{
					return (bool)obj2;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not read CraftFromContainers LeaveOne setting: " + ex.GetBaseException().Message));
			}
			return false;
		}

		private static List<Container> NearbyContainers()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !CfcIsActive())
			{
				return new List<Container>();
			}
			try
			{
				return BepInExPlugin.GetNearbyContainers(((Component)localPlayer).transform.position) ?? new List<Container>();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("CraftFromContainers GetNearbyContainers failed: " + ex.GetBaseException().Message));
				return new List<Container>();
			}
		}

		private static bool IsMaterial(ItemData? item)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (item?.m_shared != null)
			{
				return (int)item.m_shared.m_itemType == 1;
			}
			return false;
		}

		private static List<ItemData> GetItems()
		{
			List<ItemData> list = new List<ItemData>();
			int num = (LeaveOneEnabled() ? 1 : 0);
			foreach (Container item in NearbyContainers())
			{
				Inventory val = SafeGetInventory(item);
				if (val == null)
				{
					continue;
				}
				List<ItemData> source = (from item in val.GetAllItems().Where(IsMaterial)
					select item.Clone()).ToList();
				if (num > 0)
				{
					foreach (IGrouping<string, ItemData> item2 in from i in source
						group i by i.m_shared.m_name)
					{
						ItemData val2 = ((IEnumerable<ItemData>)item2).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_stack > 0));
						if (val2 != null)
						{
							val2.m_stack--;
						}
					}
				}
				list.AddRange(source.Where((ItemData i) => i.m_stack > 0));
			}
			return list;
		}

		private static int CountItem(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return 0;
			}
			int num = (LeaveOneEnabled() ? 1 : 0);
			int num2 = 0;
			foreach (Container item in NearbyContainers())
			{
				Inventory val = SafeGetInventory(item);
				if (val != null)
				{
					int num3 = val.CountItems(name, -1, true);
					num2 += Math.Max(0, num3 - num);
				}
			}
			return num2;
		}

		private static int RemoveItem(string name, int amount)
		{
			if (string.IsNullOrEmpty(name) || amount <= 0)
			{
				return 0;
			}
			int num = amount;
			int num2 = (LeaveOneEnabled() ? 1 : 0);
			foreach (Container item in NearbyContainers())
			{
				if (num <= 0)
				{
					break;
				}
				Inventory val = SafeGetInventory(item);
				if (val != null)
				{
					int num3 = val.CountItems(name, -1, true);
					int val2 = Math.Max(0, num3 - num2);
					int num4 = Math.Min(num, val2);
					if (num4 > 0)
					{
						val.RemoveItem(name, num4, -1, true);
						SaveContainer(item);
						num -= num4;
					}
				}
			}
			return amount - num;
		}

		private static int RemoveExactItem(ItemData requestedItem, int amount)
		{
			if (requestedItem?.m_shared == null || amount <= 0)
			{
				return 0;
			}
			string name = requestedItem.m_shared.m_name;
			int quality = requestedItem.m_quality;
			int worldLevel = requestedItem.m_worldLevel;
			int num = amount;
			int num2 = (LeaveOneEnabled() ? 1 : 0);
			foreach (Container item in NearbyContainers())
			{
				if (num <= 0)
				{
					break;
				}
				Inventory val = SafeGetInventory(item);
				if (val == null)
				{
					continue;
				}
				List<ItemData> list = (from i in val.GetAllItems()
					where IsMaterial(i) && i.m_shared.m_name == name && i.m_quality == quality && i.m_worldLevel == worldLevel
					select i).ToList();
				if (list.Count == 0)
				{
					continue;
				}
				int num3 = list.Sum((ItemData i) => i.m_stack);
				int val2 = Math.Max(0, num3 - num2);
				int num4 = Math.Min(num, val2);
				if (num4 <= 0)
				{
					continue;
				}
				int num5 = num4;
				foreach (ItemData item2 in list)
				{
					if (num5 <= 0)
					{
						break;
					}
					int num6 = Math.Min(num5, item2.m_stack);
					if (num6 > 0 && val.RemoveItem(item2, num6))
					{
						num5 -= num6;
					}
				}
				SaveContainer(item);
				int num7 = num4 - num5;
				num -= num7;
			}
			return amount - num;
		}

		private static Inventory? SafeGetInventory(Container container)
		{
			try
			{
				return (container != null) ? container.GetInventory() : null;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed reading container inventory: " + ex.GetBaseException().Message));
				return null;
			}
		}

		private static void SaveContainer(Container container)
		{
			try
			{
				typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(container, null);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed saving container: " + ex.GetBaseException().Message));
			}
		}
	}
}