Decompiled source of EvuMagnets v0.4.0

EvuMagnets.Core.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 Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("evu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 imevul")]
[assembly: AssemblyDescription("Craftable magnets that pull nearby items from farther away.")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0+f10db697f00271bee4eca874a2c89cdc8728c21d")]
[assembly: AssemblyProduct("EvuMagnets")]
[assembly: AssemblyTitle("EvuMagnets.Core")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/EvuMods/EvuMagnets")]
[assembly: AssemblyVersion("0.4.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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;
		}
	}
	[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 EvuMagnets.Core
{
	public readonly struct Ingredient
	{
		public string Item { get; }

		public int Amount { get; }

		public Ingredient(string item, int amount)
		{
			Item = item;
			Amount = amount;
		}
	}
	public sealed class MagnetTierInfo
	{
		public string Id { get; }

		public string PrefabName => "evu_magnet_" + Id;

		public string Token => "item_" + PrefabName;

		public string EnglishName { get; }

		public string EnglishDescription { get; }

		public string Station { get; }

		public int StationLevel { get; }

		public float[] Ranges { get; }

		public string Craft { get; }

		public string Upgrades { get; }

		public bool Forged { get; }

		public MagnetTierInfo(string id, string englishName, string englishDescription, string station, int stationLevel, float[] ranges, string craft, string upgrades, bool forged = true)
		{
			Id = id;
			EnglishName = englishName;
			EnglishDescription = englishDescription;
			Station = station;
			StationLevel = stationLevel;
			Ranges = ranges;
			Craft = craft;
			Upgrades = upgrades;
			Forged = forged;
		}
	}
	public static class MagnetCast
	{
		public const string Id = "cast";

		public const string PrefabName = "evu_cast_bloodgold";

		public const string Token = "item_evu_cast_bloodgold";

		public const string EnglishName = "Magnet Cast";

		public const string EnglishDescription = "A black-forged mold. Set it in the frost foundry with liquid frost, and a bloodgold magnet comes out.";

		public const string Station = "blackforge";

		public const int StationLevel = 1;

		public const string Craft = "Iron:10,Thunderstone:1,Gold:10,FrostCore:5";

		public const string Foundry = "piece_FrostFoundry";

		public const string OutputPrefab = "evu_magnet_bloodgold";

		public const float CookTime = 50f;
	}
	public static class MagnetCatalog
	{
		public const string PreviousFlametalCraft = "Iron:10,Flametal:10,Thunderstone:1,Eitr:5";

		public const string PreviousFlametalUpgrades = "Flametal:10,Thunderstone:1;Flametal:20,Thunderstone:2;Flametal:40,Thunderstone:4";

		public static IReadOnlyList<MagnetTierInfo> All { get; } = new MagnetTierInfo[5]
		{
			new MagnetTierInfo("iron", "Iron Magnet", "A rough iron lodestone. It draws loose items in from a short way off.", "forge", 1, new float[4] { 4f, 5f, 6f, 8f }, "Iron:20,Thunderstone:1,Ectoplasm:5", "Iron:10,Thunderstone:1;Iron:20,Thunderstone:2;Iron:40,Thunderstone:4"),
			new MagnetTierInfo("silver", "Silver Magnet", "Cold silver around a thunder stone. The pull reaches farther than iron.", "forge", 2, new float[4] { 8f, 10f, 12f, 14f }, "Iron:10,Silver:10,Thunderstone:1,Obsidian:5", "Silver:10,Thunderstone:1;Silver:20,Thunderstone:2;Silver:40,Thunderstone:4"),
			new MagnetTierInfo("blackmetal", "Black Metal Magnet", "Dark green plains metal. It gathers drops from across a camp.", "forge", 3, new float[4] { 14f, 16f, 18f, 20f }, "Iron:10,BlackMetal:10,Thunderstone:1,Crystal:10", "BlackMetal:10,Thunderstone:1;BlackMetal:20,Thunderstone:2;BlackMetal:40,Thunderstone:4"),
			new MagnetTierInfo("flametal", "Flametal Magnet", "Hot orange flametal. It pulls in everything nearby.", "blackforge", 1, new float[4] { 20f, 22f, 24f, 28f }, "Iron:10,FlametalNew:10,Thunderstone:1,Eitr:5", "FlametalNew:10,Thunderstone:1;FlametalNew:20,Thunderstone:2;FlametalNew:40,Thunderstone:4"),
			new MagnetTierInfo("bloodgold", "Bloodgold Magnet", "Gold rimmed with frost. The frost foundry casts it, and it draws items in from a long way across the snow.", "", 1, new float[1] { 36f }, "", "", forged: false)
		};

		public static bool TryGet(string? prefabName, out MagnetTierInfo? tier)
		{
			tier = null;
			if (prefabName == null || !PickupRules.IsMagnet(prefabName))
			{
				return false;
			}
			string text = prefabName.Substring("evu_magnet_".Length);
			for (int i = 0; i < All.Count; i++)
			{
				if (All[i].Id == text)
				{
					tier = All[i];
					return true;
				}
			}
			return false;
		}

		public static string KeepEdited(string saved, string previous, string current)
		{
			if (!(saved == previous))
			{
				return saved;
			}
			return current;
		}
	}
	public static class PickupRules
	{
		public readonly struct ClaimDistance
		{
			public float Distance { get; }

			public long PlayerId { get; }

			public ClaimDistance(float distance, long playerId)
			{
				Distance = distance;
				PlayerId = playerId;
			}
		}

		public const float VanillaRange = 2f;

		public const float VanillaPickupDistance = 0.3f;

		public const float PickupDistance = 1f;

		public const float HandoffMargin = 0.5f;

		public const float ClaimMargin = 0.75f;

		public const float PullSpeed = 15f;

		public const string PrefabPrefix = "evu_magnet_";

		public static bool IsMagnet(string? prefabName)
		{
			return prefabName?.StartsWith("evu_magnet_", StringComparison.Ordinal) ?? false;
		}

		public static float RangeForQuality(IReadOnlyList<float> radii, int quality)
		{
			if (radii == null || radii.Count == 0)
			{
				return 2f;
			}
			int num = quality - 1;
			if (num < 0)
			{
				num = 0;
			}
			else if (num >= radii.Count)
			{
				num = radii.Count - 1;
			}
			return radii[num];
		}

		public static bool FitsCarry(float carried, float incoming, float maxCarry)
		{
			if (incoming >= 0f)
			{
				return carried + incoming <= maxCarry;
			}
			return false;
		}

		public static bool ShouldMove(int stack, bool fitsInventory, float carried, float incoming, float maxCarry)
		{
			if (stack > 0 && fitsInventory)
			{
				return FitsCarry(carried, incoming, maxCarry);
			}
			return false;
		}

		public static bool GridFits(int stack, int freeStackSpace, int freeCells, int maxStack)
		{
			if (stack <= 0 || freeStackSpace < 0 || freeCells < 0)
			{
				return false;
			}
			int num = ((maxStack <= 0) ? 1 : maxStack);
			return freeStackSpace + (long)freeCells * (long)num >= stack;
		}

		public static bool InExtraRing(float distance, float vanillaRange, float magnetRange)
		{
			if (distance > vanillaRange)
			{
				return distance <= magnetRange;
			}
			return false;
		}

		public static bool NeedsPull(float distanceToOrigin, float vanillaRange, float magnetRange, float handoff)
		{
			float num = vanillaRange - handoff;
			if (num < 0f)
			{
				num = 0f;
			}
			if (distanceToOrigin > num)
			{
				return distanceToOrigin <= magnetRange;
			}
			return false;
		}

		public static bool AllowInWard(bool pullThroughAllWards, bool playerHasAccess)
		{
			return pullThroughAllWards || playerHasAccess;
		}

		public static float Reach(float publishedRange)
		{
			if (!(publishedRange > 2f))
			{
				return 2f;
			}
			return publishedRange;
		}

		public static bool CanReach(float distance, float reach)
		{
			return distance <= reach;
		}

		public static string? ActivePrefab(bool slotExists, string? slotPrefab, IReadOnlyList<string>? equippedPrefabs)
		{
			string text = null;
			int num = 0;
			bool flag = false;
			if (equippedPrefabs != null)
			{
				for (int i = 0; i < equippedPrefabs.Count; i++)
				{
					string text2 = equippedPrefabs[i];
					if (IsMagnet(text2))
					{
						num++;
						if (text == null)
						{
							text = text2;
						}
						if (slotPrefab != null && string.Equals(text2, slotPrefab, StringComparison.Ordinal))
						{
							flag = true;
						}
					}
				}
			}
			if (slotExists)
			{
				if (slotPrefab == null || !IsMagnet(slotPrefab))
				{
					return null;
				}
				if (!flag)
				{
					num++;
				}
				if (num != 1)
				{
					return null;
				}
				return slotPrefab;
			}
			if (num != 1)
			{
				return null;
			}
			return text;
		}

		public static bool TryExchangeMagnetSlot(bool magnetEquipped, int magnetX, int magnetY, int slotX, int slotY, out int magnetToX, out int magnetToY, out int occupantToX, out int occupantToY)
		{
			magnetToX = slotX;
			magnetToY = slotY;
			occupantToX = magnetX;
			occupantToY = magnetY;
			if (!magnetEquipped)
			{
				return false;
			}
			if (magnetX == slotX)
			{
				return magnetY != slotY;
			}
			return true;
		}

		public static bool IsBestClaim(float myDistance, long myId, IReadOnlyList<ClaimDistance> others, float margin)
		{
			if (others == null)
			{
				return true;
			}
			for (int i = 0; i < others.Count; i++)
			{
				ClaimDistance claimDistance = others[i];
				float num = claimDistance.Distance - myDistance;
				if (num < 0f - margin)
				{
					return false;
				}
				if (num <= margin && claimDistance.PlayerId < myId)
				{
					return false;
				}
			}
			return true;
		}

		public static void PullOffset(float itemX, float itemY, float itemZ, float playerX, float playerY, float playerZ, float speed, float dt, out float offsetX, out float offsetY, out float offsetZ)
		{
			float num = playerX - itemX;
			float num2 = playerY - itemY;
			float num3 = playerZ - itemZ;
			double num4 = Math.Sqrt(num * num + num2 * num2 + num3 * num3);
			if (num4 < 0.0001 || speed <= 0f || dt <= 0f)
			{
				offsetX = 0f;
				offsetY = 0f;
				offsetZ = 0f;
				return;
			}
			double num5 = (double)speed * (double)dt;
			if (num4 <= num5)
			{
				offsetX = num;
				offsetY = num2;
				offsetZ = num3;
			}
			else
			{
				double num6 = num5 / num4;
				offsetX = (float)((double)num * num6);
				offsetY = (float)((double)num2 * num6);
				offsetZ = (float)((double)num3 * num6);
			}
		}
	}
	public static class RecipeText
	{
		public static bool TryParseList(string text, out IReadOnlyList<Ingredient> items, out string error)
		{
			items = Array.Empty<Ingredient>();
			error = "";
			if (string.IsNullOrWhiteSpace(text))
			{
				error = "Recipe is empty.";
				return false;
			}
			string[] array = text.Split(new char[1] { ',' });
			List<Ingredient> list = new List<Ingredient>(array.Length);
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (!TryParseOne(array2[i], out var ingredient, out error))
				{
					return false;
				}
				list.Add(ingredient);
			}
			items = list;
			return true;
		}

		public static bool TryParseUpgrades(string text, out IReadOnlyList<IReadOnlyList<Ingredient>> steps, out string error)
		{
			steps = Array.Empty<IReadOnlyList<Ingredient>>();
			error = "";
			if (string.IsNullOrWhiteSpace(text))
			{
				error = "Upgrades are empty.";
				return false;
			}
			string[] array = text.Split(new char[1] { ';' });
			if (array.Length != 3)
			{
				error = "Upgrades need three groups, separated by semicolons.";
				return false;
			}
			List<IReadOnlyList<Ingredient>> list = new List<IReadOnlyList<Ingredient>>(3);
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				if (!TryParseList(array2[i], out IReadOnlyList<Ingredient> items, out error))
				{
					return false;
				}
				list.Add(items);
			}
			steps = list;
			return true;
		}

		public static int AmountFor(int quality, string item, IReadOnlyList<Ingredient> craft, IReadOnlyList<IReadOnlyList<Ingredient>> upgrades)
		{
			if (string.IsNullOrEmpty(item))
			{
				return 0;
			}
			if (quality <= 1)
			{
				return Sum(craft, item);
			}
			int num = quality - 2;
			if (upgrades == null || num < 0 || num >= upgrades.Count)
			{
				return 0;
			}
			return Sum(upgrades[num], item);
		}

		public static IReadOnlyList<Ingredient> Requirements(IReadOnlyList<Ingredient> craft, IReadOnlyList<IReadOnlyList<Ingredient>> upgrades)
		{
			List<string> list = new List<string>();
			AddNames(list, craft);
			if (upgrades != null)
			{
				for (int i = 0; i < upgrades.Count; i++)
				{
					AddNames(list, upgrades[i]);
				}
			}
			Ingredient[] array = new Ingredient[list.Count];
			for (int j = 0; j < list.Count; j++)
			{
				array[j] = new Ingredient(list[j], Sum(craft, list[j]));
			}
			return array;
		}

		private static void AddNames(List<string> names, IReadOnlyList<Ingredient> items)
		{
			if (items == null)
			{
				return;
			}
			for (int i = 0; i < items.Count; i++)
			{
				if (!names.Contains(items[i].Item))
				{
					names.Add(items[i].Item);
				}
			}
		}

		private static int Sum(IReadOnlyList<Ingredient> items, string item)
		{
			if (items == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < items.Count; i++)
			{
				if (string.Equals(items[i].Item, item, StringComparison.Ordinal))
				{
					num += items[i].Amount;
				}
			}
			return num;
		}

		private static bool TryParseOne(string part, out Ingredient ingredient, out string error)
		{
			ingredient = default(Ingredient);
			error = "";
			string text = part.Trim();
			int num = text.IndexOf(':');
			if (num <= 0 || num == text.Length - 1)
			{
				error = "Each ingredient must look like Item:Amount.";
				return false;
			}
			string text2 = text.Substring(0, num).Trim();
			string s = text.Substring(num + 1).Trim();
			if (text2.Length == 0 || !int.TryParse(s, out var result) || result <= 0)
			{
				error = "Each ingredient needs a name and a positive amount.";
				return false;
			}
			ingredient = new Ingredient(text2, result);
			return true;
		}
	}
}

EvuMagnets.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EvuMagnets.Core;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("evu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 imevul")]
[assembly: AssemblyDescription("Craftable magnets that pull nearby items from farther away.")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0+f10db697f00271bee4eca874a2c89cdc8728c21d")]
[assembly: AssemblyProduct("EvuMagnets")]
[assembly: AssemblyTitle("EvuMagnets")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/EvuMods/EvuMagnets")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.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.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;
		}
	}
	[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 EvuMagnets
{
	internal sealed class AdventureBackpackStore : IExtraStore
	{
		private const BindingFlags StaticMethod = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool _resolved;

		private static bool _logged;

		private static MethodInfo? _shouldStore;

		public bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor)
		{
			weightFactor = 1f;
			try
			{
				if (!Ensure() || _shouldStore == null)
				{
					return false;
				}
				object[] parameters = new object[3] { player, item, null };
				return (bool)_shouldStore.Invoke(null, parameters);
			}
			catch (Exception ex)
			{
				ExtraStores.LogOnce(ref _logged, "Adventure Backpacks store check failed: " + Message(ex));
				return false;
			}
		}

		private static bool Ensure()
		{
			if (_resolved)
			{
				return _shouldStore != null;
			}
			_resolved = true;
			_shouldStore = ExtraStores.FindType("AdventureBackpacks.Features.StoreToBackpack")?.GetMethod("ShouldStoreToBackpack", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
			{
				typeof(Player),
				typeof(ItemData),
				typeof(Inventory).MakeByRefType()
			}, null);
			if (_shouldStore == null && ExtraStores.AssemblyLoaded("AdventureBackpacks"))
			{
				ExtraStores.LogOnce(ref _logged, "Adventure Backpacks is loaded, but its store check was not found. A full inventory will not pull into that backpack.");
			}
			return _shouldStore != null;
		}

		private static string Message(Exception ex)
		{
			if (ex.InnerException == null)
			{
				return ex.Message;
			}
			return ex.InnerException.Message;
		}
	}
	internal static class AzuMagnetSlot
	{
		private sealed class CachedCall
		{
			public MethodInfo Method { get; }

			public ParameterInfo[] Parameters { get; }

			public object[] Args { get; }

			private CachedCall(MethodInfo method)
			{
				Method = method;
				Parameters = method.GetParameters();
				Args = new object[Parameters.Length];
			}

			public static CachedCall For(Type api, string name)
			{
				MethodInfo method = api.GetMethod(name, BindingFlags.Static | BindingFlags.Public);
				if (!(method != null))
				{
					return null;
				}
				return new CachedCall(method);
			}
		}

		private const string SlotName = "Magnet";

		private const string ApiTypeName = "AzuEPI.API, AzuExtendedPlayerInventory";

		private static bool _loggedFailure;

		private static Type _api;

		private static CachedCall _slotIndex;

		private static CachedCall _equippedItem;

		private static CachedCall _gridPos;

		private static int _cachedIndex = -1;

		public static bool Exists { get; private set; }

		public static bool Loaded
		{
			get
			{
				Type type = Type.GetType("AzuEPI.API, AzuExtendedPlayerInventory");
				if (type == null)
				{
					return false;
				}
				MethodInfo method = type.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public);
				if (method != null)
				{
					return (bool)method.Invoke(null, null);
				}
				return false;
			}
		}

		public static bool TryGetFakeItemType(out ItemType itemType)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected I4, but got Unknown
			itemType = (ItemType)24;
			Type type = Type.GetType("AzuEPI.API, AzuExtendedPlayerInventory");
			if (type == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public);
			if (method == null || !(bool)method.Invoke(null, null))
			{
				return false;
			}
			MethodInfo method2 = type.GetMethod("GetFakeItemType", BindingFlags.Static | BindingFlags.Public);
			if (method2 == null)
			{
				return false;
			}
			itemType = (ItemType)(int)(ItemType)method2.Invoke(null, null);
			return true;
		}

		public static void Register(IReadOnlyList<string> prefabs)
		{
			Exists = false;
			_api = null;
			_cachedIndex = -1;
			Type type = Type.GetType("AzuEPI.API, AzuExtendedPlayerInventory");
			if (type == null)
			{
				return;
			}
			MethodInfo method = type.GetMethod("IsLoaded", BindingFlags.Static | BindingFlags.Public);
			if (!(method == null) && (bool)method.Invoke(null, null))
			{
				string[] array = new string[prefabs.Count];
				for (int i = 0; i < prefabs.Count; i++)
				{
					array[i] = prefabs[i];
				}
				if (!TryAdd(type, array))
				{
					Plugin.Log.LogWarning((object)"AzuEPI is loaded, but EvuMagnets could not add the Magnet slot.");
					return;
				}
				_api = type;
				_slotIndex = CachedCall.For(type, "TryGetSlotIndexByName");
				_equippedItem = CachedCall.For(type, "TryGetEquippedItem");
				_gridPos = CachedCall.For(type, "GetSlotGridPos");
				Exists = true;
				Plugin.Log.LogInfo((object)"AzuEPI Magnet slot registered.");
			}
		}

		public static bool TryGetEquippedPrefab(out string prefabName)
		{
			prefabName = null;
			if (!Exists || !TrySlotIndex(out var index))
			{
				return false;
			}
			if (!TryEquippedItem(index, out var item) || item == null)
			{
				return false;
			}
			prefabName = PrefabName(item);
			return PickupRules.IsMagnet(prefabName);
		}

		public static bool TryMoveToSlot(Player player, ItemData item)
		{
			if (!Exists || (Object)(object)player == (Object)null || item == null)
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null || !TryGetSlotGrid(inventory, out var x, out var y))
			{
				return false;
			}
			ItemData itemAt = inventory.GetItemAt(x, y);
			if (itemAt != null && itemAt != item)
			{
				return false;
			}
			if (item.m_gridPos.x == x && item.m_gridPos.y == y)
			{
				return true;
			}
			bool num = inventory.MoveItemToThis(inventory, item, item.m_stack, x, y);
			if (!num && !_loggedFailure)
			{
				_loggedFailure = true;
				Plugin.Log.LogWarning((object)"Could not move a magnet into the AzuEPI Magnet slot.");
			}
			return num;
		}

		public static bool TryGetSlotGrid(Inventory inventory, out int x, out int y)
		{
			x = -1;
			y = -1;
			if (!Exists || inventory == null || !TrySlotIndex(out var index))
			{
				return false;
			}
			return TryGrid(inventory, index, out x, out y);
		}

		private static bool TryAdd(Type api, string[] prefabs)
		{
			MethodInfo methodInfo = null;
			MethodInfo methodInfo2 = null;
			MethodInfo[] methods = api.GetMethods(BindingFlags.Static | BindingFlags.Public);
			foreach (MethodInfo methodInfo3 in methods)
			{
				if (methodInfo3.Name != "AddSlot")
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo3.GetParameters();
				if (parameters.Length >= 2 && !(parameters[0].ParameterType != typeof(string)))
				{
					Type parameterType = parameters[1].ParameterType;
					if (parameterType == typeof(string))
					{
						methodInfo2 = methodInfo3;
					}
					else if (parameterType == typeof(string[]) || AcceptsStrings(parameterType))
					{
						methodInfo = methodInfo3;
					}
				}
			}
			if (methodInfo != null)
			{
				return InvokeAdd(methodInfo, prefabs);
			}
			if (methodInfo2 == null)
			{
				return false;
			}
			for (int j = 0; j < prefabs.Length; j++)
			{
				if (!InvokeAdd(methodInfo2, prefabs[j]))
				{
					return false;
				}
			}
			return true;
		}

		private static bool InvokeAdd(MethodInfo method, object prefabs)
		{
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			array[0] = "Magnet";
			array[1] = prefabs;
			for (int i = 2; i < parameters.Length; i++)
			{
				array[i] = ((parameters[i].ParameterType == typeof(int)) ? ((object)(-1)) : Default(parameters[i].ParameterType));
			}
			object obj = method.Invoke(null, array);
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = ((1 == 0) ? 1 : 0);
			}
			else
			{
				num = 1;
			}
			return (byte)((uint)num | (flag ? 1u : 0u)) != 0;
		}

		private static bool TrySlotIndex(out int index)
		{
			index = _cachedIndex;
			if (index >= 0)
			{
				return true;
			}
			if (_api == null || _slotIndex == null)
			{
				return false;
			}
			ParameterInfo[] parameters = _slotIndex.Parameters;
			object[] args = _slotIndex.Args;
			args[0] = "Magnet";
			for (int i = 1; i < parameters.Length; i++)
			{
				args[i] = Default(parameters[i].ParameterType);
			}
			bool flag = (bool)_slotIndex.Method.Invoke(null, args);
			for (int j = 0; j < parameters.Length; j++)
			{
				if (parameters[j].ParameterType == typeof(int).MakeByRefType())
				{
					index = (int)args[j];
				}
			}
			if (flag && index >= 0)
			{
				_cachedIndex = index;
			}
			return flag;
		}

		private static bool TryEquippedItem(int index, out ItemData item)
		{
			item = null;
			if (_equippedItem == null)
			{
				return false;
			}
			ParameterInfo[] parameters = _equippedItem.Parameters;
			object[] args = _equippedItem.Args;
			int num = -1;
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				if (parameterType == typeof(int))
				{
					args[i] = index;
				}
				else if (parameterType.IsByRef && parameterType.GetElementType() == typeof(ItemData))
				{
					num = i;
					args[i] = null;
				}
				else
				{
					args[i] = Default(parameterType);
				}
			}
			bool num2 = (bool)_equippedItem.Method.Invoke(null, args);
			if (num >= 0)
			{
				object obj = args[num];
				item = (ItemData)((obj is ItemData) ? obj : null);
				args[num] = null;
			}
			if (num2)
			{
				return item != null;
			}
			return false;
		}

		private static bool TryGrid(Inventory inventory, int index, out int x, out int y)
		{
			x = -1;
			y = -1;
			if (_gridPos == null)
			{
				return false;
			}
			ParameterInfo[] parameters = _gridPos.Parameters;
			object[] args = _gridPos.Args;
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				if (parameterType == typeof(int))
				{
					args[i] = index;
				}
				else if (typeof(Inventory).IsAssignableFrom(parameterType))
				{
					args[i] = inventory;
				}
				else
				{
					args[i] = Default(parameterType);
				}
			}
			object obj = _gridPos.Method.Invoke(null, args);
			bool flag = false;
			if (obj != null)
			{
				Type type = obj.GetType();
				FieldInfo field = type.GetField("x");
				FieldInfo field2 = type.GetField("y");
				if (field != null && field2 != null)
				{
					x = Convert.ToInt32(field.GetValue(obj));
					y = Convert.ToInt32(field2.GetValue(obj));
					flag = true;
				}
			}
			if (!flag)
			{
				for (int j = 0; j < parameters.Length; j++)
				{
					if (parameters[j].ParameterType == typeof(int).MakeByRefType())
					{
						if (x < 0)
						{
							x = (int)args[j];
						}
						else
						{
							y = (int)args[j];
						}
					}
				}
			}
			for (int k = 0; k < args.Length; k++)
			{
				args[k] = null;
			}
			if (x >= 0 && y >= 0 && x < inventory.GetWidth())
			{
				return y < inventory.GetHeight();
			}
			return false;
		}

		private static bool AcceptsStrings(Type type)
		{
			if (!type.IsGenericType)
			{
				return false;
			}
			Type[] genericArguments = type.GetGenericArguments();
			if (genericArguments.Length == 1)
			{
				return genericArguments[0] == typeof(string);
			}
			return false;
		}

		private static object Default(Type type)
		{
			Type type2 = (type.IsByRef ? type.GetElementType() : type);
			if (type2 == typeof(string))
			{
				return "";
			}
			if (!type2.IsValueType)
			{
				return null;
			}
			return Activator.CreateInstance(type2);
		}

		private static string PrefabName(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return ((Object)item.m_dropPrefab).name;
			}
			return null;
		}
	}
	internal readonly struct StoreHit
	{
		public bool WouldStore { get; }

		public float WeightFactor { get; }

		public static StoreHit None => new StoreHit(wouldStore: false, 1f);

		public StoreHit(bool wouldStore, float weightFactor)
		{
			WouldStore = wouldStore;
			WeightFactor = weightFactor;
		}
	}
	internal interface IExtraStore
	{
		bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor);
	}
	internal static class ExtraStores
	{
		private static readonly IExtraStore[] Stores = new IExtraStore[3]
		{
			new AdventureBackpackStore(),
			new SmoothbrainBackpackStore(),
			new JewelcraftingGemBagStore()
		};

		public static StoreHit Query(Player player, Inventory inventory, ItemData item)
		{
			int num = 0;
			float num2 = 1f;
			for (int i = 0; i < Stores.Length; i++)
			{
				if (Stores[i].TryAccept(player, inventory, item, out var weightFactor))
				{
					num++;
					num2 = weightFactor;
				}
			}
			if (num == 0)
			{
				return StoreHit.None;
			}
			if (num > 1 || float.IsNaN(num2) || float.IsInfinity(num2) || num2 < 0f)
			{
				num2 = 1f;
			}
			return new StoreHit(wouldStore: true, num2);
		}

		internal static Type? FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(fullName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		internal static bool AssemblyLoaded(string simpleName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				if (string.Equals(assemblies[i].GetName().Name, simpleName, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		internal static void LogOnce(ref bool logged, string message)
		{
			if (!logged)
			{
				logged = true;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)message);
				}
			}
		}
	}
	internal static class ItemIcons
	{
		public static Sprite Load(string id)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			string text = "EvuMagnets.icons." + id + ".png";
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
			if (stream == null)
			{
				throw new InvalidOperationException("Missing embedded icon " + text + ".");
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = DecodePng(memoryStream.ToArray(), text);
			((Texture)val).filterMode = (FilterMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		private static Texture2D DecodePng(byte[] png, string name)
		{
			//IL_0092: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!TryDecodeRgba(png, out int width, out int height, out byte[] rgba))
			{
				throw new InvalidOperationException("Could not read icon " + name + ".");
			}
			Color32[] array = (Color32[])(object)new Color32[width * height];
			for (int i = 0; i < height; i++)
			{
				int num = i * width * 4;
				int num2 = (height - 1 - i) * width;
				for (int j = 0; j < width; j++)
				{
					int num3 = num + j * 4;
					array[num2 + j] = new Color32(rgba[num3], rgba[num3 + 1], rgba[num3 + 2], rgba[num3 + 3]);
				}
			}
			Texture2D val = new Texture2D(width, height, (TextureFormat)4, false);
			val.SetPixels32(array);
			val.Apply(false, true);
			return val;
		}

		internal static bool TryDecodeRgba(byte[] png, out int width, out int height, out byte[] rgba)
		{
			width = 0;
			height = 0;
			rgba = Array.Empty<byte>();
			if (png == null || png.Length < 8 || png[0] != 137 || png[1] != 80 || png[2] != 78 || png[3] != 71)
			{
				return false;
			}
			MemoryStream memoryStream = new MemoryStream();
			int num = 8;
			int num2 = 0;
			int num3 = 0;
			int num4;
			for (; num + 8 <= png.Length; num += num4 + 4)
			{
				num4 = ReadInt(png, num);
				num += 4;
				int num5 = ReadInt(png, num);
				num += 4;
				if (num4 < 0 || num + num4 + 4 > png.Length)
				{
					return false;
				}
				switch (num5)
				{
				case 1229472850:
					width = ReadInt(png, num);
					height = ReadInt(png, num + 4);
					num2 = png[num + 8];
					num3 = png[num + 9];
					if (png[num + 12] == 0)
					{
						continue;
					}
					return false;
				case 1229209940:
					memoryStream.Write(png, num, num4);
					continue;
				default:
					continue;
				case 1229278788:
					break;
				}
				break;
			}
			if (width <= 0 || height <= 0 || num2 != 8 || num3 != 6)
			{
				return false;
			}
			byte[] array = Inflate(memoryStream.ToArray());
			int num6 = width * 4;
			if (array.Length < height * (num6 + 1))
			{
				return false;
			}
			rgba = new byte[height * num6];
			byte[] array2 = new byte[num6];
			byte[] array3 = new byte[num6];
			int num7 = 0;
			for (int i = 0; i < height; i++)
			{
				byte filter = array[num7++];
				Buffer.BlockCopy(array, num7, array3, 0, num6);
				num7 += num6;
				Unfilter(filter, array3, array2, num6);
				Buffer.BlockCopy(array3, 0, rgba, i * num6, num6);
				byte[] array4 = array2;
				array2 = array3;
				array3 = array4;
			}
			return true;
		}

		private static void Unfilter(byte filter, byte[] current, byte[] previous, int stride)
		{
			for (int i = 0; i < stride; i++)
			{
				byte b = (byte)((i >= 4) ? current[i - 4] : 0);
				byte b2 = previous[i];
				byte upLeft = (byte)((i >= 4) ? previous[i - 4] : 0);
				current[i] = filter switch
				{
					0 => current[i], 
					1 => (byte)(current[i] + b), 
					2 => (byte)(current[i] + b2), 
					3 => (byte)(current[i] + (b + b2) / 2), 
					4 => (byte)(current[i] + Paeth(b, b2, upLeft)), 
					_ => current[i], 
				};
			}
		}

		private static byte Paeth(byte left, byte up, byte upLeft)
		{
			int num = left + up - upLeft;
			int num2 = Math.Abs(num - left);
			int num3 = Math.Abs(num - up);
			int num4 = Math.Abs(num - upLeft);
			if (num2 <= num3 && num2 <= num4)
			{
				return left;
			}
			if (num3 > num4)
			{
				return upLeft;
			}
			return up;
		}

		private static byte[] Inflate(byte[] zlib)
		{
			if (zlib.Length < 6)
			{
				return Array.Empty<byte>();
			}
			using MemoryStream stream = new MemoryStream(zlib, 2, zlib.Length - 6);
			using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress);
			using MemoryStream memoryStream = new MemoryStream();
			deflateStream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static int ReadInt(byte[] data, int offset)
		{
			return (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3];
		}
	}
	internal sealed class JewelcraftingGemBagStore : IExtraStore
	{
		private const BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool _resolved;

		private static bool _logged;

		private static MethodInfo? _dryRun;

		public bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor)
		{
			weightFactor = 1f;
			try
			{
				if (!Ensure() || _dryRun == null)
				{
					return false;
				}
				return (bool)_dryRun.Invoke(null, new object[3] { inventory, item, true });
			}
			catch (Exception ex)
			{
				ExtraStores.LogOnce(ref _logged, "Jewelcrafting gem bag check failed: " + ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message));
				return false;
			}
		}

		private static bool Ensure()
		{
			if (_resolved)
			{
				return _dryRun != null;
			}
			_resolved = true;
			_dryRun = (ExtraStores.FindType("Jewelcrafting.MiscSetup")?.GetNestedType("AddItemToBag", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetMethod("Do", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
			{
				typeof(Inventory),
				typeof(ItemData),
				typeof(bool)
			}, null);
			if (_dryRun == null && ExtraStores.AssemblyLoaded("Jewelcrafting"))
			{
				ExtraStores.LogOnce(ref _logged, "Jewelcrafting is loaded, but its gem bag check was not found. A full inventory will not pull into that bag.");
			}
			return _dryRun != null;
		}
	}
	internal static class MagnetEquip
	{
		private static readonly List<string> EquippedNames = new List<string>();

		private static int _reconciledId;

		private static bool _loggedNoCell;

		public static void ReconcileAfterLoad(Player? player)
		{
			if ((Object)(object)player == (Object)null || player.m_isLoading || !AzuMagnetSlot.Exists)
			{
				return;
			}
			int instanceID = ((Object)player).GetInstanceID();
			if (_reconciledId == instanceID)
			{
				return;
			}
			_reconciledId = instanceID;
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return;
			}
			ItemData val = DedupeEquipped(player, inventory);
			if (val == null)
			{
				return;
			}
			if (!AzuMagnetSlot.TryGetSlotGrid(inventory, out var x, out var y))
			{
				if (!_loggedNoCell)
				{
					_loggedNoCell = true;
					Plugin.Log.LogInfo((object)"Magnet slot has no grid cell; leaving the magnet where it is.");
				}
			}
			else
			{
				PlaceEquippedMagnet(inventory, val, x, y);
			}
		}

		public static void OnEquipped(Player player, ItemData item)
		{
			if (!((Object)(object)player == (Object)null) && item != null && !player.m_isLoading && PickupRules.IsMagnet(PrefabName(item)))
			{
				if (AzuMagnetSlot.Exists)
				{
					AzuMagnetSlot.TryMoveToSlot(player, item);
				}
				UnequipOtherMagnets(player, item);
			}
		}

		private static void UnequipOtherMagnets(Player player, ItemData keep)
		{
			List<ItemData> equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems();
			for (int i = 0; i < equippedItems.Count; i++)
			{
				ItemData val = equippedItems[i];
				if (val != null && val != keep && PickupRules.IsMagnet(PrefabName(val)))
				{
					((Humanoid)player).UnequipItem(val, false);
				}
			}
		}

		private static ItemData? DedupeEquipped(Player player, Inventory inventory)
		{
			ItemData val = null;
			int num = 0;
			List<ItemData> allItems = inventory.GetAllItems();
			AzuMagnetSlot.TryGetEquippedPrefab(out var prefabName);
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val2 = allItems[i];
				if (val2 != null && val2.m_equipped && PickupRules.IsMagnet(PrefabName(val2)))
				{
					num++;
					if (val == null || (prefabName != null && PrefabName(val2) == prefabName))
					{
						val = val2;
					}
				}
			}
			if (num > 1 && val != null)
			{
				UnequipOtherMagnets(player, val);
			}
			return val;
		}

		private static void PlaceEquippedMagnet(Inventory inventory, ItemData magnet, int slotX, int slotY)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			int num = default(int);
			int num2 = default(int);
			int num3 = default(int);
			int num4 = default(int);
			if (PickupRules.TryExchangeMagnetSlot(magnet.m_equipped, magnet.m_gridPos.x, magnet.m_gridPos.y, slotX, slotY, ref num, ref num2, ref num3, ref num4))
			{
				ItemData itemAt = inventory.GetItemAt(slotX, slotY);
				if (itemAt != null && itemAt != magnet)
				{
					itemAt.m_gridPos = new Vector2i(num3, num4);
				}
				magnet.m_gridPos = new Vector2i(num, num2);
				inventory.Changed(false, false);
			}
		}

		public static string? ActivePrefab(Player? player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			List<ItemData> equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems();
			EquippedNames.Clear();
			for (int i = 0; i < equippedItems.Count; i++)
			{
				string text = PrefabName(equippedItems[i]);
				if (text != null)
				{
					EquippedNames.Add(text);
				}
			}
			AzuMagnetSlot.TryGetEquippedPrefab(out var prefabName);
			return PickupRules.ActivePrefab(AzuMagnetSlot.Exists, prefabName, (IReadOnlyList<string>)EquippedNames);
		}

		public static float ActiveRange(Player player, PluginConfig config)
		{
			if (config == null || !config.Enabled.Value || !config.Active.Value)
			{
				return 2f;
			}
			string text = ActivePrefab(player);
			if (text == null || !config.TryTier(text, out TierConfig tier) || tier == null)
			{
				return 2f;
			}
			int num = 1;
			List<ItemData> equippedItems = ((Humanoid)player).GetInventory().GetEquippedItems();
			for (int i = 0; i < equippedItems.Count; i++)
			{
				if (PrefabName(equippedItems[i]) == text)
				{
					num = equippedItems[i].m_quality;
					break;
				}
			}
			return PickupRules.RangeForQuality((IReadOnlyList<float>)tier.Ranges, num);
		}

		public static string? PrefabName(ItemData? item)
		{
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return null;
			}
			return ((Object)item.m_dropPrefab).name;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class EquipPatch
	{
		[HarmonyPriority(0)]
		private static void Postfix(Humanoid __instance, ItemData item, bool __result)
		{
			if (__result)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val != null)
				{
					MagnetEquip.OnEquipped(val, item);
				}
			}
		}
	}
	internal static class MagnetItems
	{
		private sealed class ParsedTier
		{
			public IReadOnlyList<Ingredient> Craft { get; }

			public IReadOnlyList<IReadOnlyList<Ingredient>> Upgrades { get; }

			public ParsedTier(IReadOnlyList<Ingredient> craft, IReadOnlyList<IReadOnlyList<Ingredient>> upgrades)
			{
				Craft = craft;
				Upgrades = upgrades;
			}
		}

		private static readonly Dictionary<string, Recipe> Recipes = new Dictionary<string, Recipe>(StringComparer.Ordinal);

		private static readonly Dictionary<string, ParsedTier> Parsed = new Dictionary<string, ParsedTier>(StringComparer.Ordinal);

		private static PluginConfig _config = null;

		private static bool _registered;

		public static void Bind(PluginConfig config)
		{
			_config = config;
			foreach (KeyValuePair<string, TierConfig> tier in config.Tiers)
			{
				tier.Value.ListenRecipe(delegate
				{
					ApplyRecipes();
				});
			}
			config.Cast.Listen(delegate
			{
				ApplyRecipes();
			});
		}

		public static void Register()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			if (!_registered)
			{
				_registered = true;
				AddTranslations();
				ItemType itemType = (ItemType)24;
				if (AzuMagnetSlot.TryGetFakeItemType(out var itemType2))
				{
					itemType = itemType2;
					Plugin.Log.LogInfo((object)"AzuEPI is loaded. Magnets use AzuEPI's slot item type.");
				}
				string text = FindCloneSource();
				Plugin.Log.LogInfo((object)("Magnets are cloned from " + text + "."));
				string[] array = new string[MagnetCatalog.All.Count];
				for (int i = 0; i < MagnetCatalog.All.Count; i++)
				{
					MagnetTierInfo val = MagnetCatalog.All[i];
					array[i] = val.PrefabName;
					RegisterTier(val, text, itemType);
				}
				AzuMagnetSlot.Register(array);
				RegisterCast();
				RegisterConversion();
				ApplyRecipes();
			}
		}

		public static void ApplyRecipes()
		{
			if (_config == null)
			{
				return;
			}
			Parsed.Clear();
			IReadOnlyList<Ingredient> readOnlyList = default(IReadOnlyList<Ingredient>);
			string text = default(string);
			IReadOnlyList<IReadOnlyList<Ingredient>> readOnlyList2 = default(IReadOnlyList<IReadOnlyList<Ingredient>>);
			foreach (MagnetTierInfo item in MagnetCatalog.All)
			{
				if (!_config.Tiers.TryGetValue(item.Id, out TierConfig value) || !item.Forged || value.Craft == null || value.Upgrades == null || value.Station == null || value.StationLevel == null)
				{
					continue;
				}
				if (!RecipeText.TryParseList(value.Craft.Value, ref readOnlyList, ref text) || !RecipeText.TryParseUpgrades(value.Upgrades.Value, ref readOnlyList2, ref text))
				{
					Plugin.Log.LogWarning((object)(item.EnglishName + " recipe was not applied: " + text));
					continue;
				}
				Parsed[item.PrefabName] = new ParsedTier(readOnlyList, readOnlyList2);
				if (Recipes.TryGetValue(item.PrefabName, out Recipe value2) && !((Object)(object)value2 == (Object)null))
				{
					CraftingStation val = FindStation(value.Station.Value);
					if ((Object)(object)val == (Object)null)
					{
						Plugin.Log.LogWarning((object)(item.EnglishName + " station was not found: " + value.Station.Value));
					}
					else
					{
						value2.m_craftingStation = val;
					}
					value2.m_minStationLevel = value.StationLevel.Value;
					if (!TryBuildRequirements(RecipeText.Requirements(readOnlyList, readOnlyList2), out Requirement[] requirements))
					{
						value2.m_enabled = false;
						value2.m_resources = Array.Empty<Requirement>();
					}
					else
					{
						value2.m_enabled = true;
						value2.m_resources = requirements;
					}
				}
			}
			ApplyCast();
			ApplyFoundryTime();
		}

		public static bool TryAmount(Requirement requirement, int quality, out int amount)
		{
			amount = 0;
			if (requirement == null)
			{
				return false;
			}
			ItemDrop resItem = requirement.m_resItem;
			if ((Object)(object)resItem == (Object)null || string.IsNullOrEmpty(((Object)resItem).name))
			{
				return false;
			}
			string name = ((Object)resItem).name;
			foreach (KeyValuePair<string, Recipe> recipe in Recipes)
			{
				Requirement[] array = (((Object)(object)recipe.Value != (Object)null) ? recipe.Value.m_resources : null);
				if (array == null || !Parsed.TryGetValue(recipe.Key, out ParsedTier value))
				{
					continue;
				}
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i] == requirement)
					{
						amount = RecipeText.AmountFor(quality, name, value.Craft, value.Upgrades);
						return true;
					}
				}
			}
			return false;
		}

		private static void RegisterTier(MagnetTierInfo tier, string source, ItemType itemType)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(tier.PrefabName, source);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("Could not clone " + source + " for " + tier.PrefabName + "."));
				return;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			SharedData shared = component.m_itemData.m_shared;
			shared.m_name = "$" + tier.Token;
			shared.m_description = "$" + tier.Token + "_desc";
			shared.m_itemType = itemType;
			shared.m_maxStackSize = 1;
			shared.m_weight = 2f;
			shared.m_maxQuality = tier.Ranges.Length;
			shared.m_teleportable = true;
			shared.m_useDurability = false;
			shared.m_durabilityDrain = 0f;
			shared.m_equipStatusEffect = null;
			shared.m_setStatusEffect = null;
			shared.m_fullAdrenalineSE = null;
			shared.m_setName = "";
			shared.m_setSize = 0;
			shared.m_skillType = (SkillType)0;
			shared.m_icons = (Sprite[])(object)new Sprite[1] { ItemIcons.Load(tier.Id) };
			component.m_itemData.m_dropPrefab = val;
			Tint(val, tier.Id);
			if (!tier.Forged)
			{
				ItemManager.Instance.AddItem(new CustomItem(val, false));
				return;
			}
			Recipe val2 = ScriptableObject.CreateInstance<Recipe>();
			((Object)val2).name = "Recipe_" + tier.PrefabName;
			val2.m_item = component;
			val2.m_amount = 1;
			val2.m_enabled = true;
			CustomItem val3 = new CustomItem(val, false);
			val3.Recipe = new CustomRecipe(val2, false, false);
			ItemManager.Instance.AddItem(val3);
			Recipes[tier.PrefabName] = val3.Recipe.Recipe;
		}

		private static void AddTranslations()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text;
			string token;
			for (int i = 0; i < MagnetCatalog.All.Count; i++)
			{
				MagnetTierInfo val = MagnetCatalog.All[i];
				text = "English";
				token = val.Token;
				localization.AddTranslation(ref text, ref token, val.EnglishName);
				text = "English";
				token = val.Token + "_desc";
				localization.AddTranslation(ref text, ref token, val.EnglishDescription);
			}
			text = "English";
			token = "item_evu_cast_bloodgold";
			localization.AddTranslation(ref text, ref token, "Magnet Cast");
			text = "English";
			token = "item_evu_cast_bloodgold_desc";
			localization.AddTranslation(ref text, ref token, "A black-forged mold. Set it in the frost foundry with liquid frost, and a bloodgold magnet comes out.");
		}

		private static void RegisterCast()
		{
			//IL_0058: 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)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("evu_cast_bloodgold", "Iron");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Could not clone Iron for evu_cast_bloodgold.");
				return;
			}
			ItemDrop component = val.GetComponent<ItemDrop>();
			SharedData shared = component.m_itemData.m_shared;
			shared.m_name = "$item_evu_cast_bloodgold";
			shared.m_description = "$item_evu_cast_bloodgold_desc";
			shared.m_itemType = (ItemType)1;
			shared.m_maxStackSize = 10;
			shared.m_weight = 2f;
			shared.m_maxQuality = 1;
			shared.m_teleportable = true;
			shared.m_useDurability = false;
			shared.m_durabilityDrain = 0f;
			shared.m_equipStatusEffect = null;
			shared.m_setStatusEffect = null;
			shared.m_setName = "";
			shared.m_setSize = 0;
			shared.m_skillType = (SkillType)0;
			shared.m_icons = (Sprite[])(object)new Sprite[1] { ItemIcons.Load("cast") };
			component.m_itemData.m_dropPrefab = val;
			Tint(val, "cast");
			Recipe val2 = ScriptableObject.CreateInstance<Recipe>();
			((Object)val2).name = "Recipe_evu_cast_bloodgold";
			val2.m_item = component;
			val2.m_amount = 1;
			val2.m_enabled = true;
			CustomItem val3 = new CustomItem(val, false);
			val3.Recipe = new CustomRecipe(val2, false, false);
			ItemManager.Instance.AddItem(val3);
			Recipes["evu_cast_bloodgold"] = val3.Recipe.Recipe;
		}

		private static void RegisterConversion()
		{
			//IL_0005: 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_0024: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new CookingConversionConfig
			{
				Station = _config.Cast.Foundry.Value,
				FromItem = "evu_cast_bloodgold",
				ToItem = "evu_magnet_bloodgold",
				CookTime = _config.Cast.CookTime.Value
			}));
		}

		private static void ApplyFoundryTime()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(_config.Cast.Foundry.Value);
			CookingStation val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CookingStation>() : null);
			if ((Object)(object)val == (Object)null || val.m_conversion == null)
			{
				return;
			}
			for (int i = 0; i < val.m_conversion.Count; i++)
			{
				ItemConversion val2 = val.m_conversion[i];
				if (val2 != null && (Object)(object)val2.m_from != (Object)null && ((Object)val2.m_from).name == "evu_cast_bloodgold")
				{
					val2.m_cookTime = _config.Cast.CookTime.Value;
					break;
				}
			}
		}

		private static void ApplyCast()
		{
			if (!Recipes.TryGetValue("evu_cast_bloodgold", out Recipe value) || (Object)(object)value == (Object)null)
			{
				return;
			}
			IReadOnlyList<Ingredient> craft = default(IReadOnlyList<Ingredient>);
			string text = default(string);
			if (!RecipeText.TryParseList(_config.Cast.Craft.Value, ref craft, ref text))
			{
				Plugin.Log.LogWarning((object)("Magnet cast recipe was not applied: " + text));
				value.m_enabled = false;
				value.m_resources = Array.Empty<Requirement>();
				return;
			}
			CraftingStation val = FindStation(_config.Cast.Station.Value);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Magnet cast station was not found: " + _config.Cast.Station.Value));
			}
			else
			{
				value.m_craftingStation = val;
			}
			value.m_minStationLevel = _config.Cast.StationLevel.Value;
			if (!TryBuildRequirements(craft, out Requirement[] requirements))
			{
				value.m_enabled = false;
				value.m_resources = Array.Empty<Requirement>();
			}
			else
			{
				value.m_enabled = true;
				value.m_resources = requirements;
			}
		}

		private static string FindCloneSource()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Invalid comparison between Unknown and I4
			string text = null;
			List<GameObject> list = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.m_items : null);
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					ItemDrop val = (((Object)(object)list[i] != (Object)null) ? list[i].GetComponent<ItemDrop>() : null);
					if (!((Object)(object)val == (Object)null) && (int)val.m_itemData.m_shared.m_itemType == 24 && (text == null || string.CompareOrdinal(((Object)list[i]).name, text) < 0))
					{
						text = ((Object)list[i]).name;
					}
				}
			}
			return text ?? "BeltStrength";
		}

		private static CraftingStation? FindStation(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return null;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(name.Trim());
			if (!((Object)(object)prefab != (Object)null))
			{
				return null;
			}
			return prefab.GetComponent<CraftingStation>();
		}

		private static bool TryBuildRequirements(IReadOnlyList<Ingredient> craft, out Requirement[] requirements)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			requirements = (Requirement[])(object)new Requirement[craft.Count];
			for (int i = 0; i < craft.Count; i++)
			{
				Ingredient val = craft[i];
				ItemDrop val2 = FindItem(((Ingredient)(ref val)).Item);
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					val = craft[i];
					log.LogWarning((object)("Recipe item was not found: " + ((Ingredient)(ref val)).Item));
					requirements = Array.Empty<Requirement>();
					return false;
				}
				Requirement[] obj = requirements;
				int num = i;
				Requirement val3 = new Requirement
				{
					m_resItem = val2
				};
				val = craft[i];
				val3.m_amount = ((Ingredient)(ref val)).Amount;
				val3.m_amountPerLevel = 0;
				val3.m_recover = true;
				val3.m_upgraderResource = false;
				obj[num] = val3;
			}
			return true;
		}

		private static ItemDrop? FindItem(string name)
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(name);
			ItemDrop val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return null;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name);
			val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			List<GameObject> items = ObjectDB.instance.m_items;
			if (items == null)
			{
				return null;
			}
			for (int i = 0; i < items.Count; i++)
			{
				if (!((Object)(object)items[i] == (Object)null) && !(((Object)items[i]).name != name))
				{
					val = items[i].GetComponent<ItemDrop>();
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static void Tint(GameObject prefab, string id)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			Color color = (Color)(id switch
			{
				"cast" => new Color(0.78f, 0.74f, 0.62f), 
				"bloodgold" => new Color(0.95f, 0.74f, 0.22f), 
				"flametal" => new Color(0.95f, 0.28f, 0.05f), 
				"blackmetal" => new Color(0.12f, 0.42f, 0.18f), 
				"silver" => new Color(0.78f, 0.82f, 0.86f), 
				_ => new Color(0.45f, 0.42f, 0.4f), 
			});
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if (!((Object)(object)sharedMaterials[j] == (Object)null))
					{
						Material val = new Material(sharedMaterials[j]);
						if (val.HasProperty("_Color"))
						{
							val.color = color;
						}
						sharedMaterials[j] = val;
					}
				}
				componentsInChildren[i].sharedMaterials = sharedMaterials;
			}
		}
	}
	[HarmonyPatch(typeof(Requirement), "GetAmount")]
	internal static class RequirementAmountPatch
	{
		private static void Postfix(Requirement __instance, int qualityLevel, ref int __result)
		{
			if (MagnetItems.TryAmount(__instance, qualityLevel, out var amount))
			{
				__result = amount;
			}
		}
	}
	internal static class MagnetReach
	{
		private static readonly int ReachHash = StringExtensionMethods.GetStableHashCode("EvuMagnets.Reach");

		private static float _published = -1f;

		private static ZDO? _publishedTo;

		public static void Publish(Player player, float range)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			ZNetView nview = ((Character)player).m_nview;
			if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != _publishedTo || range != _published)
				{
					zDO.Set(ReachHash, range);
					_published = range;
					_publishedTo = zDO;
				}
			}
		}

		public static float Of(Player other)
		{
			ZNetView val = (((Object)(object)other != (Object)null) ? ((Character)other).m_nview : null);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return 2f;
			}
			return PickupRules.Reach(val.GetZDO().GetFloat(ReachHash, 0f));
		}
	}
	[HarmonyPatch(typeof(Player), "AutoPickup")]
	internal static class PickupPatch
	{
		private struct Pass
		{
			public float OriginalRange;

			public bool Extend;

			public float Range;
		}

		private const int InitialHits = 128;

		private static Collider[] Hits = (Collider[])(object)new Collider[128];

		private static readonly List<ClaimDistance> Claims = new List<ClaimDistance>();

		private static readonly HashSet<string> Blocked = new HashSet<string>(StringComparer.Ordinal);

		private static bool _loggedDropFailure;

		private static bool _resolvedFreeCells;

		private static MethodInfo? _freeNormalCells;

		private static void Prefix(Player __instance, ref Pass __state)
		{
			__state.OriginalRange = __instance.m_autoPickupRange;
			__state.Extend = ShouldExtend(__instance, out __state.Range);
			MagnetReach.Publish(__instance, __state.Extend ? __state.Range : 0f);
			if (__state.Extend)
			{
				__instance.m_autoPickupRange = 0f;
			}
		}

		private static void Postfix(Player __instance, float dt, Pass __state)
		{
			__instance.m_autoPickupRange = __state.OriginalRange;
			if (__state.Extend)
			{
				PullExtraRing(__instance, dt, __state.Range);
			}
		}

		private static bool ShouldExtend(Player player, out float range)
		{
			range = 2f;
			if ((Object)(object)player == (Object)null || Plugin.Settings == null || !Player.m_enableAutoPickup)
			{
				return false;
			}
			range = MagnetEquip.ActiveRange(player, Plugin.Settings);
			return range > 2f;
		}

		private static void PullExtraRing(Player player, float dt, float range)
		{
			//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_002b: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (((Character)player).IsDead() || ((Character)player).IsTeleporting())
			{
				return;
			}
			Blocked.Clear();
			Vector3 origin = ((Component)player).transform.position + Vector3.up;
			int num = Overlap(origin, range, player.m_autoPickupMask);
			Inventory inventory = ((Humanoid)player).GetInventory();
			for (int i = 0; i < num; i++)
			{
				Collider val = Hits[i];
				Hits[i] = null;
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					PullOne(player, inventory, val, origin, range, dt);
				}
				catch (Exception ex)
				{
					if (!_loggedDropFailure)
					{
						_loggedDropFailure = true;
						Plugin.Log.LogWarning((object)("Skipped a drop the magnet could not read: " + ex.Message));
					}
				}
			}
		}

		private static void PullOne(Player player, Inventory inventory, Collider collider, Vector3 origin, float range, float dt)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody attachedRigidbody = collider.attachedRigidbody;
			if ((Object)(object)attachedRigidbody == (Object)null)
			{
				return;
			}
			ItemDrop component = ((Component)attachedRigidbody).GetComponent<ItemDrop>();
			FloatingTerrainDummy val = null;
			if ((Object)(object)component == (Object)null)
			{
				val = ((Component)attachedRigidbody).GetComponent<FloatingTerrainDummy>();
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_parent != (Object)null)
				{
					component = ((Component)val.m_parent).GetComponent<ItemDrop>();
				}
			}
			if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null || !component.m_autoPickup || component.IsPiece() || ((Humanoid)player).HaveUniqueKey(component.m_itemData.m_shared.m_name))
			{
				return;
			}
			ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
			if ((Object)(object)component2 == (Object)null || !component2.IsValid() || component.InTar())
			{
				return;
			}
			Vector3 position = ((Component)component).transform.position;
			if (!PickupRules.AllowInWard(Plugin.Settings.PullThroughAllWards.Value, PrivateArea.CheckAccess(position, 0f, false, true)))
			{
				return;
			}
			Vector3 position2 = ((Component)player).transform.position;
			float num = HorizontalDistance(position, position2);
			float num2 = Vector3.Distance(position, origin);
			bool flag = num2 < 0.3f;
			bool flag2 = num2 >= 0.3f && num2 <= range;
			if (!flag && !flag2)
			{
				return;
			}
			ItemData itemData = component.m_itemData;
			string name = itemData.m_shared.m_name;
			if (name != null && Blocked.Contains(name))
			{
				return;
			}
			if (component2.IsOwner())
			{
				component.Load();
			}
			int stack = itemData.m_stack;
			float totalWeight = inventory.GetTotalWeight();
			float maxCarryWeight = player.GetMaxCarryWeight();
			bool flag3 = FitsInventory(inventory, itemData, 1);
			bool flag4 = stack > 0 && FitsInventory(inventory, itemData, stack);
			StoreHit store = ((flag3 && flag4) ? StoreHit.None : ExtraStores.Query(player, inventory, itemData));
			if (!CanMove(1, flag3, store, totalWeight, itemData.GetWeight(1), maxCarryWeight))
			{
				if (name != null)
				{
					Blocked.Add(name);
				}
			}
			else
			{
				if (!CanMove(stack, flag4, store, totalWeight, itemData.GetWeight(stack), maxCarryWeight))
				{
					return;
				}
				FillClaims(player, position);
				bool flag5 = PickupRules.IsBestClaim(num, player.GetPlayerID(), (IReadOnlyList<ClaimDistance>)Claims, 0.75f);
				if (!component2.IsOwner())
				{
					if (flag5 && flag2)
					{
						component.RequestOwn();
					}
				}
				else
				{
					if (!flag5 || !component.CanPickup(true))
					{
						return;
					}
					if (flag)
					{
						((Humanoid)player).Pickup(((Component)component).gameObject, true, true);
						return;
					}
					float num3 = default(float);
					float num4 = default(float);
					float num5 = default(float);
					PickupRules.PullOffset(position.x, position.y, position.z, origin.x, origin.y, origin.z, 15f, dt, ref num3, ref num4, ref num5);
					Vector3 val2 = default(Vector3);
					((Vector3)(ref val2))..ctor(num3, num4, num5);
					Stop(attachedRigidbody);
					Stop(((Component)component).GetComponent<Rigidbody>());
					Transform transform = ((Component)component).transform;
					transform.position += val2;
					if ((Object)(object)val != (Object)null)
					{
						Transform transform2 = ((Component)val).transform;
						transform2.position += val2;
					}
				}
			}
		}

		private static bool CanMove(int stack, bool gridFits, StoreHit store, float carried, float weight, float maxCarry)
		{
			bool flag = gridFits || store.WouldStore;
			float num = ((gridFits || !store.WouldStore) ? 1f : store.WeightFactor);
			return PickupRules.ShouldMove(stack, flag, carried, weight * num, maxCarry);
		}

		private static bool FitsInventory(Inventory inventory, ItemData data, int stack)
		{
			SharedData shared = data.m_shared;
			int num = inventory.FindFreeStackSpace(shared.m_name, (float)data.m_worldLevel);
			return PickupRules.GridFits(stack, num, FreeCells(inventory), shared.m_maxStackSize);
		}

		private static int FreeCells(Inventory inventory)
		{
			if (!_resolvedFreeCells)
			{
				_resolvedFreeCells = true;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				for (int i = 0; i < assemblies.Length; i++)
				{
					_freeNormalCells = assemblies[i].GetType("AzuEPI.Core.InventoryHandlers.Capacity")?.GetMethod("FreeNormalCells", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (_freeNormalCells != null)
					{
						break;
					}
				}
			}
			if (_freeNormalCells != null)
			{
				return (int)_freeNormalCells.Invoke(null, new object[1] { inventory });
			}
			return inventory.GetEmptySlots();
		}

		private static int Overlap(Vector3 origin, float range, int mask)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			int num = HitCap();
			if (Hits.Length > num)
			{
				Hits = (Collider[])(object)new Collider[num];
			}
			int num2;
			while (true)
			{
				num2 = Physics.OverlapSphereNonAlloc(origin, range, Hits, mask);
				if (num2 < Hits.Length || Hits.Length >= num)
				{
					return num2;
				}
				int num3 = Hits.Length * 2;
				if (num3 > num)
				{
					num3 = num;
				}
				if (num3 <= Hits.Length)
				{
					break;
				}
				Hits = (Collider[])(object)new Collider[num3];
			}
			return num2;
		}

		private static int HitCap()
		{
			int num = ((Plugin.Settings != null) ? Plugin.Settings.MaxHits.Value : 2048);
			if (num < 128)
			{
				return 128;
			}
			if (num > 2048)
			{
				return 2048;
			}
			return num;
		}

		private static void FillClaims(Player player, Vector3 itemPosition)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			Claims.Clear();
			List<Player> allPlayers = Player.GetAllPlayers();
			for (int i = 0; i < allPlayers.Count; i++)
			{
				Player val = allPlayers[i];
				if (!((Object)(object)val == (Object)null) && val != player && !((Character)val).IsDead() && !((Character)val).IsTeleporting())
				{
					float num = HorizontalDistance(((Component)val).transform.position, itemPosition);
					if (PickupRules.CanReach(num, MagnetReach.Of(val)))
					{
						Claims.Add(new ClaimDistance(num, val.GetPlayerID()));
					}
				}
			}
		}

		private static float HorizontalDistance(Vector3 a, Vector3 b)
		{
			//IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			float num = a.x - b.x;
			float num2 = a.z - b.z;
			return Mathf.Sqrt(num * num + num2 * num2);
		}

		private static void Stop(Rigidbody body)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)body == (Object)null))
			{
				body.linearVelocity = Vector3.zero;
				body.angularVelocity = Vector3.zero;
			}
		}
	}
	[BepInPlugin("evu.evumagnets", "EvuMagnets", "0.4.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.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		private ConfigFileWatcher _configWatcher;

		internal static PluginConfig Settings { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new PluginConfig(((BaseUnityPlugin)this).Config);
			_configWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L);
			MagnetItems.Bind(Settings);
			ItemManager.OnVanillaItemsAvailable += MagnetItems.Register;
			ItemManager.OnItemsRegistered += MagnetItems.ApplyRecipes;
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				MagnetItems.ApplyRecipes();
			};
			Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "evu.evumagnets");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"EvuMagnets loaded.");
		}

		private void Update()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			MagnetEquip.ReconcileAfterLoad(Player.m_localPlayer);
			if (Settings != null)
			{
				KeyboardShortcut value = Settings.Toggle.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && !Typing())
				{
					Settings.Active.Value = !Settings.Active.Value;
				}
			}
		}

		private static bool Typing()
		{
			if ((Object)(object)Console.instance != (Object)null && Console.IsVisible())
			{
				return true;
			}
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return true;
			}
			if ((Object)(object)TextInput.instance != (Object)null)
			{
				return TextInput.IsVisible();
			}
			return false;
		}
	}
	internal sealed class TierConfig
	{
		public ConfigEntry<float> Range1 { get; }

		public ConfigEntry<float>? Range2 { get; }

		public ConfigEntry<float>? Range3 { get; }

		public ConfigEntry<float>? Range4 { get; }

		public ConfigEntry<string>? Craft { get; }

		public ConfigEntry<string>? Upgrades { get; }

		public ConfigEntry<string>? Station { get; }

		public ConfigEntry<int>? StationLevel { get; }

		public float[] Ranges
		{
			get
			{
				if (Range2 != null && Range3 != null && Range4 != null)
				{
					return new float[4] { Range1.Value, Range2.Value, Range3.Value, Range4.Value };
				}
				return new float[1] { Range1.Value };
			}
		}

		public TierConfig(ConfigFile config, MagnetTierInfo tier, int order)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Expected O, but got Unknown
			string englishName = tier.EnglishName;
			Range1 = BindRange(config, englishName, "Range1", tier.Ranges[0], "Pickup radius in meters at quality 1.", order);
			if (tier.Forged)
			{
				Range2 = BindRange(config, englishName, "Range2", tier.Ranges[1], "Pickup radius in meters at quality 2.", order - 1);
				Range3 = BindRange(config, englishName, "Range3", tier.Ranges[2], "Pickup radius in meters at quality 3.", order - 2);
				Range4 = BindRange(config, englishName, "Range4", tier.Ranges[3], "Pickup radius in meters at quality 4.", order - 3);
				ConfigEntry<string> val = config.Bind<string>(englishName, "Craft", tier.Craft, new ConfigDescription("Ingredients for a new magnet. Item prefab names and amounts, separated by commas.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(order - 4) }));
				ConfigEntry<string> val2 = config.Bind<string>(englishName, "Upgrades", tier.Upgrades, new ConfigDescription("Three upgrade steps, separated by semicolons. Each step is Item:Amount pairs separated by commas.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(order - 5) }));
				if (tier.Id == "flametal")
				{
					val.Value = MagnetCatalog.KeepEdited(val.Value, "Iron:10,Flametal:10,Thunderstone:1,Eitr:5", tier.Craft);
					val2.Value = MagnetCatalog.KeepEdited(val2.Value, "Flametal:10,Thunderstone:1;Flametal:20,Thunderstone:2;Flametal:40,Thunderstone:4", tier.Upgrades);
				}
				Craft = val;
				Upgrades = val2;
				Station = config.Bind<string>(englishName, "Station", tier.Station, new ConfigDescription("Crafting station prefab name.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(order - 6) }));
				StationLevel = config.Bind<int>(englishName, "StationLevel", tier.StationLevel, new ConfigDescription("Crafting station level required to make quality 1. Each upgrade asks for one level more.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), new object[1] { ConfigHints.Synced(order - 7) }));
			}
		}

		public void ListenRecipe(EventHandler handler)
		{
			if (Craft != null)
			{
				Craft.SettingChanged += handler;
			}
			if (Upgrades != null)
			{
				Upgrades.SettingChanged += handler;
			}
			if (Station != null)
			{
				Station.SettingChanged += handler;
			}
			if (StationLevel != null)
			{
				StationLevel.SettingChanged += handler;
			}
		}

		private static ConfigEntry<float> BindRange(ConfigFile config, string section, string key, float value, string description, int order)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			return config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 64f), new object[1] { ConfigHints.Synced(order) }));
		}
	}
	internal sealed class PluginConfig
	{
		public ConfigEntry<bool> Enabled { get; }

		public ConfigEntry<bool> PullThroughAllWards { get; }

		public ConfigEntry<bool> Active { get; }

		public ConfigEntry<KeyboardShortcut> Toggle { get; }

		public ConfigEntry<int> MaxHits { get; }

		public IReadOnlyDictionary<string, TierConfig> Tiers { get; }

		public CastConfig Cast { get; }

		public PluginConfig(ConfigFile config)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, new ConfigDescription("When off, magnets do not extend pickup range. Crafted magnets stay in the world.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(100) }));
			PullThroughAllWards = config.Bind<bool>("General", "PullThroughAllWards", false, new ConfigDescription("When on, magnets also pull items that sit inside other players' wards. Players can always pull items inside their own wards.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(90) }));
			Active = config.Bind<bool>("Local", "Active", true, new ConfigDescription("When off, your magnet does not extend pickup. Vanilla auto-pickup stays on. This client only.", (AcceptableValueBase)null, new object[1] { ConfigHints.Local(200) }));
			Toggle = config.Bind<KeyboardShortcut>("Local", "Toggle", new KeyboardShortcut((KeyCode)118, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Key that turns your magnet on or off. This client only.", (AcceptableValueBase)null, new object[1] { ConfigHints.Local(190) }));
			MaxHits = config.Bind<int>("Local", "MaxHits", 2048, new ConfigDescription("Most nearby colliders one magnet pass will search. The search starts at 128 and grows to this cap. Lower it if a large pull hitches. This client only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(128, 2048), new object[1] { ConfigHints.Local(180) }));
			Dictionary<string, TierConfig> dictionary = new Dictionary<string, TierConfig>(StringComparer.Ordinal);
			for (int i = 0; i < MagnetCatalog.All.Count; i++)
			{
				MagnetTierInfo val = MagnetCatalog.All[i];
				dictionary[val.Id] = new TierConfig(config, val, 80 - i * 10);
			}
			Tiers = dictionary;
			Cast = new CastConfig(config);
		}

		public bool TryTier(string? prefabName, out TierConfig? tier)
		{
			tier = null;
			MagnetTierInfo val = default(MagnetTierInfo);
			if (!MagnetCatalog.TryGet(prefabName, ref val) || val == null)
			{
				return false;
			}
			return Tiers.TryGetValue(val.Id, out tier);
		}
	}
	internal sealed class CastConfig
	{
		public ConfigEntry<string> Craft { get; }

		public ConfigEntry<string> Station { get; }

		public ConfigEntry<int> StationLevel { get; }

		public ConfigEntry<string> Foundry { get; }

		public ConfigEntry<float> CookTime { get; }

		public CastConfig(ConfigFile config)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			Craft = config.Bind<string>("Magnet Cast", "Craft", "Iron:10,Thunderstone:1,Gold:10,FrostCore:5", new ConfigDescription("Ingredients for a magnet cast. Item prefab names and amounts, separated by commas.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(20) }));
			Station = config.Bind<string>("Magnet Cast", "Station", "blackforge", new ConfigDescription("Crafting station prefab name.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(19) }));
			StationLevel = config.Bind<int>("Magnet Cast", "StationLevel", 1, new ConfigDescription("Crafting station level required.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7), new object[1] { ConfigHints.Synced(18) }));
			Foundry = config.Bind<string>("Magnet Cast", "Foundry", "piece_FrostFoundry", new ConfigDescription("Frost foundry prefab. Place the cast in it and liquid frost in the fuel slot. Read when a world loads.", (AcceptableValueBase)null, new object[1] { ConfigHints.Synced(17) }));
			CookTime = config.Bind<float>("Magnet Cast", "CookTime", 50f, new ConfigDescription("Seconds the frost foundry takes to turn one cast into a bloodgold magnet.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), new object[1] { ConfigHints.Synced(16) }));
		}

		public void Listen(EventHandler handler)
		{
			Craft.SettingChanged += handler;
			Station.SettingChanged += handler;
			StationLevel.SettingChanged += handler;
			CookTime.SettingChanged += handler;
		}
	}
	internal static class ConfigHints
	{
		public static ConfigurationManagerAttributes Synced(int order)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0019: Expected O, but got Unknown
			return new ConfigurationManagerAttributes
			{
				IsAdminOnly = true,
				Order = order
			};
		}

		public static ConfigurationManagerAttributes Local(int order)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_0019: Expected O, but got Unknown
			return new ConfigurationManagerAttributes
			{
				IsAdminOnly = false,
				Order = order
			};
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "evu.evumagnets";

		public const string Name = "EvuMagnets";

		public const string Version = "0.4.0";
	}
	internal sealed class SmoothbrainBackpackStore : IExtraStore
	{
		private const BindingFlags InstanceAny = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private const BindingFlags StaticAny = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static bool _resolved;

		private static bool _logged;

		private static MethodInfo? _data;

		private static MethodInfo? _get;

		private static MethodInfo? _mayAutoPickup;

		private static MethodInfo? _canAddItem;

		private static MethodInfo? _weightFactor;

		private static MethodInfo? _canAddToInventory;

		private static MethodInfo? _containsName;

		private static FieldInfo? _inventory;

		private static PropertyInfo? _item;

		private static Type? _containerType;

		private static Type? _customType;

		private static FieldInfo? _allowedItems;

		public bool TryAccept(Player player, Inventory inventory, ItemData item, out float weightFactor)
		{
			weightFactor = 1f;
			try
			{
				if (!Ensure() || inventory.m_inventory == null || _data == null || _get == null)
				{
					return false;
				}
				object obj = null;
				long num = long.MinValue;
				List<ItemData> inventory2 = inventory.m_inventory;
				for (int i = 0; i < inventory2.Count; i++)
				{
					ItemData val = inventory2[i];
					if (val == null || !TryContainer(val, out object container) || container == null || !CallBool(_mayAutoPickup, container, item) || !CallBool(_canAddItem, container, item))
					{
						continue;
					}
					object? obj2 = _inventory?.GetValue(container);
					Inventory val2 = (Inventory)((obj2 is Inventory) ? obj2 : null);
					if (val2 != null && !(_canAddToInventory == null) && (bool)_canAddToInventory.Invoke(val2, new object[2] { item, -1 }))
					{
						long num2 = Score(container, val2, item.m_shared.m_name);
						if (num2 > num)
						{
							num = num2;
							obj = container;
						}
					}
				}
				if (obj == null || _weightFactor == null)
				{
					return false;
				}
				weightFactor = (float)_weightFactor.Invoke(obj, null);
				return true;
			}
			catch (Exception ex)
			{
				ExtraStores.LogOnce(ref _logged, "Backpacks store check failed: " + ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message));
				return false;
			}
		}

		private bool TryContainer(ItemData held, out object? container)
		{
			container = null;
			object obj = _data.Invoke(null, new object[1] { held });
			if (obj == null || _get == null || _containerType == null)
			{
				return false;
			}
			container = _get.Invoke(obj, new object[1] { string.Empty });
			return container != null;
		}

		private static bool CallBool(MethodInfo? method, object instance, ItemData item)
		{
			if (method != null)
			{
				return (bool)method.Invoke(instance, new object[1] { item });
			}
			return false;
		}

		private long Score(object container, Inventory bag, string? itemName)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			//IL_002e: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			object? obj = _item?.GetValue(container, null);
			ItemData val = (ItemData)((obj is ItemData) ? obj : null);
			Vector2i val2 = (Vector2i)(((??)val?.m_gridPos) ?? default(Vector2i));
			long num = 1 + val2.x + (long)val2.y * 100L;
			if (itemName != null && _containsName != null && (bool)_containsName.Invoke(bag, new object[1] { itemName }))
			{
				num += 10000;
			}
			Type type = container.GetType();
			if (_customType != null && !_customType.IsInstanceOfType(container) && type != _containerType)
			{
				num *= 400000000;
			}
			else if (_customType != null && _customType.IsInstanceOfType(container) && HasAllowedList(val))
			{
				num *= 20000;
			}
			return num;
		}

		private bool HasAllowedList(ItemData? backpack)
		{
			string text = backpack?.m_shared?.m_name;
			if (text == null || !(_allowedItems?.GetValue(null) is IDictionary dictionary) || !dictionary.Contains(text))
			{
				return false;
			}
			if (dictionary[text] is ICollection collection)
			{
				return collection.Count > 0;
			}
			return false;
		}

		private static bool Ensure()
		{
			if (_resolved)
			{
				return _data != null;
			}
			_resolved = true;
			_containerType = ExtraStores.FindType("Backpacks.ItemContainer");
			_customType = ExtraStores.FindType("Backpacks.CustomBackpack");
			Type? type = ExtraStores.FindType("ItemDataManager.ItemExtensions");
			Type infoType = ExtraStores.FindType("ItemDataManager.ItemInfo");
			_data = type?.GetMethod("Data", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
			_get = GenericGet(infoType);
			if (_get != null && _containerType != null)
			{
				_get = _get.MakeGenericMethod(_containerType);
			}
			_mayAutoPickup = _containerType?.GetMethod("MayAutoPickup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
			_canAddItem = _containerType?.GetMethod("CanAddItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null);
			_weightFactor = _containerType?.GetMethod("WeightFactor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			_inventory = _containerType?.GetField("Inventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_item = _containerType?.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_allowedItems = _customType?.GetField("AllowedItems", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			_canAddToInventory = typeof(Inventory).GetMethod("CanAddItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(ItemData),
				typeof(int)
			}, null);
			_containsName = typeof(Inventory).GetMethod("ContainsItemByName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			int num;
			if (_data != null && _get != null && _mayAutoPickup != null && _canAddItem != null && _weightFactor != null && _inventory != null)
			{
				num = ((_canAddToInventory != null) ? 1 : 0);
				if (num != 0)
				{
					goto IL_0281;
				}
			}
			else
			{
				num = 0;
			}
			if (ExtraStores.AssemblyLoaded("Backpacks"))
			{
				ExtraStores.LogOnce(ref _logged, "Backpacks is loaded, but its auto-fill check was not found. A full inventory will not pull into those backpacks.");
			}
			goto IL_0281;
			IL_0281:
			return (byte)num != 0;
		}

		private static MethodInfo? GenericGet(Type? infoType)
		{
			if (infoType == null)
			{
				return null;
			}
			MethodInfo[] methods = infoType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!(methodInfo.Name != "Get") && methodInfo.IsGenericMethodDefinition)
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string))
					{
						return methodInfo;
					}
				}
			}
			return null;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}