Decompiled source of CraftFromContainers v1.1.0

CraftFromContainers.dll

Decompiled 20 hours 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.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CraftFromContainers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("CraftFromContainers")]
[assembly: AssemblyTitle("CraftFromContainers")]
[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 CraftFromContainers
{
	internal static class Containers
	{
		private sealed class Entry
		{
			public Container C;

			public ZNetView NView;

			public Piece Piece;

			public string Prefab;

			public bool Vehicle;

			public bool Excluded;
		}

		internal const string RpcRequestOwn = "CFC_RequestOwn";

		private static readonly FieldRef<Container, ZNetView> NViewRef = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

		private static readonly FieldRef<Container, Piece> PieceRef = AccessTools.FieldRefAccess<Container, Piece>("m_piece");

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

		private static readonly List<Entry> Registry = new List<Entry>();

		private static readonly Dictionary<Container, Entry> ByContainer = new Dictionary<Container, Entry>();

		private static readonly Dictionary<Container, float> LastUsed = new Dictionary<Container, float>();

		private static int _frame = -1;

		private static readonly Dictionary<string, int> OwnedStock = new Dictionary<string, int>();

		private static readonly List<Entry> Owned = new List<Entry>();

		private static readonly List<Entry> NotOwned = new List<Entry>();

		private static readonly List<ItemData> Scratch = new List<ItemData>();

		private static Vector3 _center;

		private static readonly List<Container> NotOwnedView = new List<Container>();

		internal static List<Container> NotOwnedContainers
		{
			get
			{
				Refresh();
				NotOwnedView.Clear();
				foreach (Entry item in NotOwned)
				{
					NotOwnedView.Add(item.C);
				}
				return NotOwnedView;
			}
		}

		internal static void OnAwake(Container c)
		{
			ZNetView val = NViewRef.Invoke(c);
			if (!((Object)(object)val == (Object)null) && val.GetZDO() != null)
			{
				val.Register<long>("CFC_RequestOwn", (Action<long, long>)delegate(long sender, long playerID)
				{
					OnRequestOwn(c, sender, playerID);
				});
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && !ByContainer.ContainsKey(c))
				{
					Piece piece = PieceRef.Invoke(c) ?? ((Component)c).GetComponentInParent<Piece>();
					Entry entry = new Entry
					{
						C = c,
						NView = val,
						Piece = piece,
						Prefab = Utils.GetPrefabName(((Component)c).gameObject),
						Vehicle = ((Object)(object)c.m_wagon != (Object)null || (Object)(object)((Component)c).GetComponentInParent<Ship>() != (Object)null),
						Excluded = (c.m_autoDestroyEmpty || (Object)(object)((Component)c).GetComponent<TombStone>() != (Object)null || (Object)(object)((Component)c).GetComponentInParent<Player>() != (Object)null)
					};
					Registry.Add(entry);
					ByContainer[c] = entry;
				}
			}
		}

		internal static void Invalidate()
		{
			_frame = -1;
		}

		internal static void Refresh()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (_frame == Time.frameCount)
			{
				return;
			}
			_frame = Time.frameCount;
			OwnedStock.Clear();
			Owned.Clear();
			NotOwned.Clear();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			_center = ((Component)localPlayer).transform.position;
			float value = Plugin.Range.Value;
			float range = value * value;
			long playerID = localPlayer.GetPlayerID();
			for (int num = Registry.Count - 1; num >= 0; num--)
			{
				Entry entry = Registry[num];
				if ((Object)(object)entry.C == (Object)null || (Object)(object)entry.NView == (Object)null || !entry.NView.IsValid())
				{
					ByContainer.Remove(entry.C);
					Registry[num] = Registry[Registry.Count - 1];
					Registry.RemoveAt(Registry.Count - 1);
				}
				else if (Eligible(entry, range, playerID))
				{
					if (!entry.NView.IsOwner())
					{
						NotOwned.Add(entry);
					}
					else
					{
						Owned.Add(entry);
						Inventory inventory = entry.C.GetInventory();
						if (inventory != null)
						{
							foreach (ItemData allItem in inventory.GetAllItems())
							{
								if (Usable(allItem))
								{
									OwnedStock.TryGetValue(allItem.m_shared.m_name, out var value2);
									OwnedStock[allItem.m_shared.m_name] = value2 + allItem.m_stack;
								}
							}
						}
					}
				}
			}
			Owned.Sort(delegate(Entry a, Entry b)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: 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_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)
				Vector3 val = ((Component)a.C).transform.position - _center;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				val = ((Component)b.C).transform.position - _center;
				return sqrMagnitude.CompareTo(((Vector3)(ref val)).sqrMagnitude);
			});
		}

		internal static int OwnedCount(string name)
		{
			Refresh();
			if (!OwnedStock.TryGetValue(name, out var value))
			{
				return 0;
			}
			return value;
		}

		private static bool Eligible(Entry e, float range2, long playerID)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			if (e.Excluded)
			{
				return false;
			}
			Container c = e.C;
			Vector3 val = ((Component)c).transform.position - _center;
			if (((Vector3)(ref val)).sqrMagnitude > range2)
			{
				return false;
			}
			if (e.Vehicle && !Plugin.IncludeVehicles.Value)
			{
				return false;
			}
			if (!e.Vehicle && Plugin.PlayerBuiltOnly.Value && ((Object)(object)e.Piece == (Object)null || e.Piece.GetCreator() == 0L))
			{
				return false;
			}
			if (Plugin.Excluded.Count > 0 && Plugin.Excluded.Contains(e.Prefab))
			{
				return false;
			}
			if (!HasAccess(c, e.Piece, playerID))
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false))
			{
				return false;
			}
			if (InUseByOther(e))
			{
				return false;
			}
			return true;
		}

		private static bool HasAccess(Container c, Piece piece, long playerID)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			PrivacySetting privacy = c.m_privacy;
			if ((int)privacy != 0)
			{
				if ((int)privacy == 2)
				{
					return true;
				}
				return false;
			}
			if ((Object)(object)piece != (Object)null)
			{
				return piece.GetCreator() == playerID;
			}
			return false;
		}

		private static bool IsOpenByMe(Container c)
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null && InventoryGui.IsVisible())
			{
				return (Object)(object)OpenContainerRef.Invoke(instance) == (Object)(object)c;
			}
			return false;
		}

		private static bool InUseByOther(Entry e)
		{
			if (IsOpenByMe(e.C))
			{
				return false;
			}
			if ((Object)(object)e.C.m_wagon != (Object)null && e.C.m_wagon.InUse())
			{
				return true;
			}
			if (e.NView.IsOwner())
			{
				return e.C.IsInUse();
			}
			return e.NView.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1;
		}

		internal static bool Usable(ItemData it)
		{
			if (it == null || it.m_stack <= 0)
			{
				return false;
			}
			if (it.m_shared.m_maxQuality > 1)
			{
				return false;
			}
			if (it.m_worldLevel < Game.m_worldLevel)
			{
				return false;
			}
			if (it.m_equipped)
			{
				return false;
			}
			if (Plugin.SkipCustomDataItems.Value && it.m_customData != null && it.m_customData.Count > 0)
			{
				return false;
			}
			return true;
		}

		private static void CollectMatching(Inventory inv, string name)
		{
			Scratch.Clear();
			foreach (ItemData allItem in inv.GetAllItems())
			{
				if (allItem.m_shared.m_name == name && Usable(allItem))
				{
					Scratch.Add(allItem);
				}
			}
		}

		internal static int StageInto(Inventory target, string name, int amount)
		{
			Refresh();
			int num = 0;
			foreach (Entry item in Owned)
			{
				if (num >= amount)
				{
					break;
				}
				if (!item.NView.IsValid() || !item.NView.IsOwner())
				{
					continue;
				}
				Inventory inventory = item.C.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				CollectMatching(inventory, name);
				foreach (ItemData item2 in Scratch)
				{
					int num2 = item2.m_stack;
					int num3 = Mathf.Max(1, item2.m_shared.m_maxStackSize);
					while (num < amount && num2 > 0)
					{
						int num4 = Mathf.Min(new int[3]
						{
							amount - num,
							num2,
							num3
						});
						if (!target.CanAddItem(item2, num4))
						{
							Invalidate();
							return num;
						}
						ItemData val = item2.Clone();
						val.m_stack = num4;
						val.m_equipped = false;
						if (!inventory.RemoveItem(item2, num4))
						{
							break;
						}
						num2 -= num4;
						if (!target.AddItem(val))
						{
							inventory.AddItem(val);
							Plugin.Log.LogWarning((object)("Nie udalo sie dodac " + num4 + "x " + name + " do ekwipunku; zwrocono do skrzyni."));
							Invalidate();
							return num;
						}
						num += num4;
						LastUsed[item.C] = Time.time;
					}
					if (num >= amount)
					{
						break;
					}
				}
			}
			Invalidate();
			return num;
		}

		internal static int RemoveDirect(string name, int amount)
		{
			Refresh();
			int num = 0;
			foreach (Entry item in Owned)
			{
				if (num >= amount)
				{
					break;
				}
				if (!item.NView.IsValid() || !item.NView.IsOwner())
				{
					continue;
				}
				Inventory inventory = item.C.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				CollectMatching(inventory, name);
				foreach (ItemData item2 in Scratch)
				{
					int num2 = Mathf.Min(amount - num, item2.m_stack);
					if (num2 <= 0)
					{
						break;
					}
					if (inventory.RemoveItem(item2, num2))
					{
						num += num2;
						LastUsed[item.C] = Time.time;
					}
					if (num >= amount)
					{
						break;
					}
				}
			}
			Invalidate();
			return num;
		}

		private static void OnRequestOwn(Container c, long sender, long playerID)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)c == (Object)null)
			{
				return;
			}
			ZNetView val = NViewRef.Invoke(c);
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner() || sender == ZDOMan.GetSessionID())
			{
				return;
			}
			if (c.IsInUse() || ((Object)(object)c.m_wagon != (Object)null && c.m_wagon.InUse()))
			{
				Plugin.Debug("Odmowa (skrzynia otwarta): " + ((Object)c).name);
			}
			else
			{
				if (LastUsed.TryGetValue(c, out var value) && Time.time - value < 3f)
				{
					return;
				}
				if (OwnershipRequester.LocallyBusy && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					Vector3 val2 = ((Component)c).transform.position - ((Component)Player.m_localPlayer).transform.position;
					if (((Vector3)(ref val2)).sqrMagnitude <= Plugin.Range.Value * Plugin.Range.Value)
					{
						return;
					}
				}
				Piece piece = PieceRef.Invoke(c) ?? ((Component)c).GetComponentInParent<Piece>();
				if (HasAccess(c, piece, playerID))
				{
					ZDOMan.instance.ForceSendZDO(sender, val.GetZDO().m_uid);
					val.GetZDO().SetOwner(sender);
					Invalidate();
					Plugin.Debug("Przekazano wlasnosc " + ((Object)c).name + " -> " + sender);
				}
			}
		}

		internal static void RequestOwnership(Container c, long playerID)
		{
			ZNetView val = NViewRef.Invoke(c);
			if (!((Object)(object)val == (Object)null) && val.IsValid() && !val.IsOwner())
			{
				if (!val.GetZDO().HasOwner())
				{
					val.ClaimOwnership();
					Invalidate();
				}
				else
				{
					val.InvokeRPC("CFC_RequestOwn", new object[1] { playerID });
				}
			}
		}

		internal static void PruneLastUsed()
		{
			if (LastUsed.Count == 0)
			{
				return;
			}
			List<Container> list = new List<Container>();
			float time = Time.time;
			foreach (KeyValuePair<Container, float> item in LastUsed)
			{
				if ((Object)(object)item.Key == (Object)null || time - item.Value > 10f)
				{
					list.Add(item.Key);
				}
			}
			foreach (Container item2 in list)
			{
				LastUsed.Remove(item2);
			}
		}
	}
	internal static class EpicLootBridge
	{
		internal const string EpicLootGuid = "randyknapp.mods.epicloot";

		private static readonly List<ItemData> NoItems = new List<ItemData>();

		private static Func<bool> _enchantingVisible;

		private static bool _tried;

		internal static bool EnchantingOpen
		{
			get
			{
				try
				{
					return _enchantingVisible != null && _enchantingVisible();
				}
				catch
				{
					return false;
				}
			}
		}

		internal static void TryRegister()
		{
			if (_tried)
			{
				return;
			}
			_tried = true;
			if (!Chainloader.PluginInfos.TryGetValue("randyknapp.mods.epicloot", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = ((object)value.Instance).GetType().Assembly.GetType("EpicLoot.API")?.GetMethod("RegisterInventoryProvider", BindingFlags.Static | BindingFlags.Public);
				if (methodInfo == null)
				{
					Plugin.Log.LogWarning((object)"EpicLoot bez API.RegisterInventoryProvider - stol zaklinania nie bedzie bral ze skrzyn.");
					return;
				}
				Func<List<ItemData>> func = () => NoItems;
				Func<string, int> func2 = (string name) => Usable() ? Containers.OwnedCount(name) : 0;
				Func<string, int, int> func3 = (string name, int amount) => Usable() ? Containers.RemoveDirect(name, amount) : 0;
				Func<ItemData, int, int> func4 = (ItemData item, int amount) => 0;
				bool flag = (bool)methodInfo.Invoke(null, new object[5] { "local.craftfromcontainers", func, func2, func3, func4 });
				Plugin.Log.LogInfo((object)(flag ? "Stol zaklinania EpicLoot pobiera materialy ze skrzyn." : "EpicLoot odrzucil rejestracje dostawcy."));
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int num = 0; num < assemblies.Length; num++)
				{
					Type type = assemblies[num].GetType("EpicLoot_UnityLib.EnchantingTableUI", throwOnError: false);
					if (!(type == null))
					{
						MethodInfo method = type.GetMethod("IsVisible", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
						if (method != null)
						{
							_enchantingVisible = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), method);
						}
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Integracja z EpicLoot nie wstala: " + ex.Message));
			}
		}

		private static bool Usable()
		{
			if (Plugin.Active)
			{
				return Plugin.CraftEnabled.Value;
			}
			return false;
		}
	}
	internal class OwnershipRequester : MonoBehaviour
	{
		internal static bool LocallyBusy;

		private const float Interval = 0.5f;

		private const int BudgetPerTick = 6;

		private const float Cooldown = 5f;

		private readonly Dictionary<Container, float> _asked = new Dictionary<Container, float>();

		private float _next;

		private float _nextPrune;

		private void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			LocallyBusy = (Object)(object)localPlayer != (Object)null && Plugin.Active && IsCraftingOrBuilding(localPlayer);
			if (!LocallyBusy || Time.time < _next)
			{
				return;
			}
			_next = Time.time + 0.5f;
			long playerID = localPlayer.GetPlayerID();
			int num = 6;
			foreach (Container notOwnedContainer in Containers.NotOwnedContainers)
			{
				if (num == 0)
				{
					break;
				}
				if (!_asked.TryGetValue(notOwnedContainer, out var value) || !(Time.time - value < 5f))
				{
					Inventory inventory = notOwnedContainer.GetInventory();
					if (inventory != null && inventory.NrOfItems() != 0)
					{
						_asked[notOwnedContainer] = Time.time;
						num--;
						Containers.RequestOwnership(notOwnedContainer, playerID);
						Plugin.Debug("Prosba o wlasnosc: " + ((Object)notOwnedContainer).name);
					}
				}
			}
			if (!(Time.time >= _nextPrune))
			{
				return;
			}
			_nextPrune = Time.time + 30f;
			List<Container> list = new List<Container>();
			foreach (KeyValuePair<Container, float> item in _asked)
			{
				if ((Object)(object)item.Key == (Object)null || Time.time - item.Value > 5f)
				{
					list.Add(item.Key);
				}
			}
			foreach (Container item2 in list)
			{
				_asked.Remove(item2);
			}
			Containers.PruneLastUsed();
		}

		private static bool IsCraftingOrBuilding(Player player)
		{
			if (Plugin.CraftEnabled.Value && InventoryGui.IsVisible() && (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.instance.InCraftTab())
			{
				return true;
			}
			if (Plugin.CraftEnabled.Value && EpicLootBridge.EnchantingOpen)
			{
				return true;
			}
			if (Plugin.BuildEnabled.Value)
			{
				return ((Character)player).InPlaceMode();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class Container_Awake
	{
		[HarmonyPriority(0)]
		private static void Postfix(Container __instance)
		{
			Containers.OnAwake(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
	internal static class Player_HaveRequirementItems
	{
		[HarmonyPriority(800)]
		private static void Postfix(Player __instance, ref bool __result, Recipe piece, bool discover, int qualityLevel, int amount)
		{
			if (__result || discover || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Plugin.CraftEnabled.Value || !Plugin.Active || (Object)(object)piece == (Object)null || piece.m_resources == null || piece.m_requireOnlyOneIngredient)
			{
				return;
			}
			CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
			Inventory inventory = ((Humanoid)__instance).GetInventory();
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if ((!((Object)(object)currentCraftingStation != (Object)null) || currentCraftingStation.m_upgrader == val.m_upgraderResource) && (!((Object)(object)currentCraftingStation == (Object)null) || !val.m_upgraderResource) && Object.op_Implicit((Object)(object)val.m_resItem))
				{
					int num = val.GetAmount(qualityLevel) * amount;
					SharedData shared = val.m_resItem.m_itemData.m_shared;
					int num2 = 0;
					for (int j = 1; j <= shared.m_maxQuality; j++)
					{
						num2 = Mathf.Max(num2, inventory.CountItems(shared.m_name, j, true));
					}
					if (shared.m_maxQuality <= 1)
					{
						num2 += Containers.OwnedCount(shared.m_name);
					}
					if (num2 < num)
					{
						return;
					}
				}
			}
			__result = true;
		}
	}
	[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
	{
		typeof(Piece),
		typeof(RequirementMode)
	})]
	internal static class Player_HaveRequirements_Piece
	{
		private static readonly FieldRef<Player, Dictionary<string, int>> KnownStations = AccessTools.FieldRefAccess<Player, Dictionary<string, int>>("m_knownStations");

		[HarmonyPriority(800)]
		private static void Postfix(Player __instance, ref bool __result, Piece piece, RequirementMode mode)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Invalid comparison between Unknown and I4
			if (__result || (int)mode == 1 || (Object)(object)piece == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Plugin.BuildEnabled.Value || !Plugin.Active)
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)piece.m_craftingStation))
			{
				if ((int)mode == 2)
				{
					if (!KnownStations.Invoke(__instance).ContainsKey(piece.m_craftingStation.m_name))
					{
						return;
					}
				}
				else if (!Object.op_Implicit((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position)) && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)27))
				{
					return;
				}
			}
			if (piece.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(piece.m_dlc))
			{
				return;
			}
			Inventory inventory = ((Humanoid)__instance).GetInventory();
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if (!Object.op_Implicit((Object)(object)val.m_resItem) || val.m_amount <= 0)
				{
					continue;
				}
				SharedData shared = val.m_resItem.m_itemData.m_shared;
				int num = ((shared.m_maxQuality <= 1) ? Containers.OwnedCount(shared.m_name) : 0);
				if ((int)mode == 2)
				{
					if (!inventory.HaveItem(shared.m_name, true) && num <= 0)
					{
						return;
					}
				}
				else if (inventory.CountItems(shared.m_name, -1, true) + num < val.m_amount)
				{
					return;
				}
			}
			__result = true;
		}
	}
	[HarmonyPatch(typeof(Player), "ConsumeResources")]
	internal static class Player_ConsumeResources
	{
		[HarmonyPriority(800)]
		private static void Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || requirements == null || !Plugin.Active || (InventoryGui.IsVisible() ? (!Plugin.CraftEnabled.Value) : (!Plugin.BuildEnabled.Value)) || itemQuality > 1)
			{
				return;
			}
			CraftingStation currentCraftingStation = __instance.GetCurrentCraftingStation();
			Inventory inventory = ((Humanoid)__instance).GetInventory();
			foreach (Requirement val in requirements)
			{
				if (!Object.op_Implicit((Object)(object)val.m_resItem) || (((Object)(object)currentCraftingStation != (Object)null) ? (currentCraftingStation.m_upgrader != val.m_upgraderResource) : val.m_upgraderResource))
				{
					continue;
				}
				SharedData shared = val.m_resItem.m_itemData.m_shared;
				if (shared.m_maxQuality > 1)
				{
					continue;
				}
				int num = val.GetAmount(qualityLevel) * multiplier;
				if (num <= 0)
				{
					continue;
				}
				int num2 = num - inventory.CountItems(shared.m_name, itemQuality, true);
				if (num2 > 0)
				{
					int num3 = Containers.StageInto(inventory, shared.m_name, num2);
					int num4 = num2 - num3;
					int num5 = ((num4 > 0) ? Containers.RemoveDirect(shared.m_name, num4) : 0);
					num4 -= num5;
					Plugin.Debug($"{shared.m_name}: brakowalo {num2}, przeniesiono {num3}, zdjeto wprost {num5}");
					if (num4 > 0)
					{
						Plugin.Log.LogWarning((object)$"Nie znaleziono w skrzyniach {num4}x {shared.m_name} (brakowalo {num2}).");
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "SetupRequirement")]
	internal static class InventoryGui_SetupRequirement
	{
		private static void Postfix(bool __result, Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier)
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if (!__result || req == null || (Object)(object)req.m_resItem == (Object)null || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || !Plugin.Active || (craft ? (!Plugin.CraftEnabled.Value) : (!Plugin.BuildEnabled.Value)))
			{
				return;
			}
			SharedData shared = req.m_resItem.m_itemData.m_shared;
			if (shared.m_maxQuality > 1)
			{
				return;
			}
			int num = Containers.OwnedCount(shared.m_name);
			if (num <= 0)
			{
				return;
			}
			int num2 = req.GetAmount(quality) * craftMultiplier;
			if (num2 <= 0)
			{
				return;
			}
			Transform obj = elementRoot.Find("res_amount");
			TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				if (((Humanoid)player).GetInventory().CountItems(shared.m_name, -1, true) + num >= num2)
				{
					((Graphic)val).color = Color.white;
				}
				if (Plugin.ShowCounts.Value)
				{
					val.text = num2 + " <size=70%><color=#9ae59a>+" + num + "</color></size>";
				}
			}
		}
	}
	[BepInPlugin("local.craftfromcontainers", "Craft From Containers", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "local.craftfromcontainers";

		public const string NAME = "Craft From Containers";

		public const string VERSION = "1.1.0";

		internal const string DvergerGuid = "MidngightsFX.DvergerAutomation";

		private static readonly string[] ConflictingGuids = new string[2] { "aedenthorn.CraftFromContainers", "buldosik.EpicLootCraftFromContainers" };

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> Range;

		internal static ConfigEntry<bool> CraftEnabled;

		internal static ConfigEntry<bool> BuildEnabled;

		internal static ConfigEntry<bool> PlayerBuiltOnly;

		internal static ConfigEntry<bool> IncludeVehicles;

		internal static ConfigEntry<bool> SkipCustomDataItems;

		internal static ConfigEntry<string> ExcludedContainers;

		internal static ConfigEntry<bool> ShowCounts;

		internal static ConfigEntry<bool> DebugLog;

		internal static readonly HashSet<string> Excluded = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static ConfigEntryBase _dvergerCraft;

		private static bool _dvergerResolved;

		private static bool _dvergerLoaded;

		private static string _conflict;

		private static bool _conflictWarned;

		internal static bool Active
		{
			get
			{
				if (!Enabled.Value)
				{
					return false;
				}
				string text = FindConflict();
				if (text == null)
				{
					return true;
				}
				if (!_conflictWarned)
				{
					_conflictWarned = true;
					Log.LogWarning((object)("Craft From Containers wstrzymany: " + text + " tez pobiera skladniki ze skrzyn, wiec schodzilyby podwojnie. Odinstaluj go (Dverger: wystarczy wylaczyc 'Craft From Storage')."));
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Serwer", "Wlaczony", true, new ConfigDescription("Glowny wlacznik. Ustawiany przez serwer.", (AcceptableValueBase)null, new object[1] { val }));
			Range = ((BaseUnityPlugin)this).Config.Bind<float>("Serwer", "Zasieg", 20f, new ConfigDescription("Promien (m) wokol gracza, z ktorego brane sa skrzynie.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 50f), new object[1] { val }));
			CraftEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Serwer", "Crafting ze skrzyn", true, new ConfigDescription("Czy stacje rzemieslnicze moga brac skladniki ze skrzyn.", (AcceptableValueBase)null, new object[1] { val }));
			BuildEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Serwer", "Budowanie ze skrzyn", true, new ConfigDescription("Czy mlotek moze brac materialy ze skrzyn.", (AcceptableValueBase)null, new object[1] { val }));
			PlayerBuiltOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Serwer", "Tylko skrzynie graczy", true, new ConfigDescription("Tylko skrzynie postawione przez gracza. Wylacza skrzynie w lochach, wraki i inne pojemniki swiata.", (AcceptableValueBase)null, new object[1] { val }));
			IncludeVehicles = ((BaseUnityPlugin)this).Config.Bind<bool>("Serwer", "Wozki i lodzie", false, new ConfigDescription("Czy liczyc ladownie wozkow i lodzi. Domyslnie wylaczone: przejmowanie wlasnosci lodzi przenosi tez jej fizyke.", (AcceptableValueBase)null, new object[1] { val }));
			SkipCustomDataItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Serwer", "Pomijaj przedmioty magiczne", true, new ConfigDescription("Nie zuzywa przedmiotow z dodatkowymi danymi (np. zaklete z EpicLoot, z gniazdami).", (AcceptableValueBase)null, new object[1] { val }));
			ExcludedContainers = ((BaseUnityPlugin)this).Config.Bind<string>("Serwer", "Wykluczone pojemniki", "", new ConfigDescription("Nazwy prefabow pojemnikow do pominiecia, oddzielone przecinkami.", (AcceptableValueBase)null, new object[1] { val }));
			ShowCounts = ((BaseUnityPlugin)this).Config.Bind<bool>("Klient", "Pokazuj ilosci ze skrzyn", true, "Dopisuje przy skladniku ile sztuk jest w skrzyniach (+N).");
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Klient", "Log diagnostyczny", false, "Loguje kazde pobranie ze skrzyni i kazda prosbe o wlasnosc.");
			RebuildExcluded();
			ExcludedContainers.SettingChanged += delegate
			{
				RebuildExcluded();
			};
			new Harmony("local.craftfromcontainers").PatchAll(typeof(Plugin).Assembly);
			((Component)this).gameObject.AddComponent<OwnershipRequester>();
			Log.LogInfo((object)"Craft From Containers 1.1.0 zaladowany.");
		}

		private static void RebuildExcluded()
		{
			Excluded.Clear();
			string[] array = ExcludedContainers.Value.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					Excluded.Add(text);
				}
			}
		}

		private void Start()
		{
			EpicLootBridge.TryRegister();
		}

		private static string FindConflict()
		{
			if (!_dvergerResolved)
			{
				_dvergerResolved = true;
				string[] conflictingGuids = ConflictingGuids;
				foreach (string text in conflictingGuids)
				{
					if (Chainloader.PluginInfos.ContainsKey(text))
					{
						_conflict = text;
						break;
					}
				}
				if (Chainloader.PluginInfos.TryGetValue("MidngightsFX.DvergerAutomation", out var value) && (Object)(object)value.Instance != (Object)null)
				{
					_dvergerLoaded = true;
					foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in value.Instance.Config)
					{
						if (item.Key.Section == "Client config" && item.Key.Key == "Craft From Storage")
						{
							_dvergerCraft = item.Value;
							break;
						}
					}
				}
			}
			if (_conflict != null)
			{
				return _conflict;
			}
			if (!_dvergerLoaded)
			{
				return null;
			}
			if (_dvergerCraft != null)
			{
				object boxedValue = _dvergerCraft.BoxedValue;
				bool flag = default(bool);
				int num;
				if (boxedValue is bool)
				{
					flag = (bool)boxedValue;
					num = 1;
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) == 0)
				{
					return null;
				}
			}
			return "MidngightsFX.DvergerAutomation";
		}

		internal static void Debug(string msg)
		{
			if (DebugLog.Value)
			{
				Log.LogInfo((object)msg);
			}
		}
	}
}