Decompiled source of MagneticWishbone v1.1.1

MagneticWishbone.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using VNEI.Logic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MagneticWishbone")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Riintouge")]
[assembly: AssemblyProduct("MagneticWishbone")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4533b312-0061-4916-b569-170707a29c8f")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.1.0")]
namespace MagneticWishbone;

public class Common
{
	public const string WishbonePrefabName = "Wishbone";

	public const string WishboneUnlocalizedName = "$item_wishbone";

	public const string NoneCraftingStationName = "NoneCraftingStation";

	public const float DefaultMaxAutoPickupDistance = 2f;

	public const float DefaultMaxInteractDistance = 5f;

	public const float MaxAutoPickupDistance = 50f;

	public static InvalidatableLazy<CraftingStation> NoneCraftingStation = new InvalidatableLazy<CraftingStation>(delegate
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		CraftingStation obj = new GameObject().AddComponent<CraftingStation>();
		((Object)obj).name = "NoneCraftingStation";
		obj.m_name = "NoneCraftingStation";
		obj.m_discoverRange = 0f;
		return obj;
	});

	public static CraftingStation FindCraftingStationByUnlocalizedName(string unlocalizedName)
	{
		if (!Utility.IsNullOrWhiteSpace(unlocalizedName))
		{
			foreach (CraftingStation item in Traverse.Create(typeof(CraftingStation)).Field("m_allStations").GetValue() as List<CraftingStation>)
			{
				if (item.m_name.Equals(unlocalizedName))
				{
					return item;
				}
			}
		}
		return NoneCraftingStation.Value;
	}
}
public abstract class CustomRecipe : Recipe
{
	public virtual bool IsCraftable()
	{
		return IsCraftableAt(GetCustomRequiredStation(1));
	}

	public abstract bool IsCraftableAt(CraftingStation station);

	public virtual bool IsUpgradable(int currentQuality)
	{
		return IsUpgradableAt(currentQuality, GetCustomRequiredStation(currentQuality));
	}

	public abstract bool IsUpgradableAt(int currentQuality, CraftingStation station);

	public virtual bool AppliesTo(ItemDrop itemDrop)
	{
		return AppliesTo(itemDrop.m_itemData);
	}

	public virtual bool AppliesTo(ItemData itemData)
	{
		return AppliesTo(itemData.m_shared.m_name);
	}

	public virtual bool AppliesTo(string unlocalizedItemNameOrPrefabName)
	{
		if (!base.m_item.m_itemData.m_shared.m_name.Equals(unlocalizedItemNameOrPrefabName))
		{
			return ((Object)base.m_item).name.Equals(unlocalizedItemNameOrPrefabName);
		}
		return true;
	}

	public virtual bool RegisterWithVNEI()
	{
		if (Chainloader.PluginInfos.ContainsKey("com.maxsch.valheim.vnei"))
		{
			RegisterWithVNEICore();
			return true;
		}
		return false;
	}

	protected virtual void RegisterWithVNEICore()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		for (int i = 1; i <= base.m_item.m_itemData.m_shared.m_maxQuality; i++)
		{
			if ((i == 1) ? IsCraftable() : IsUpgradable(i - 1))
			{
				Indexing.AddRecipeToItems((RecipeInfo)RegisterWithVNEICore(i));
			}
		}
	}

	protected virtual object RegisterWithVNEICore(int quality)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		RecipeInfo val = new RecipeInfo((Recipe)(object)this, quality);
		val.AddStation(GetCustomRequiredStation(quality).m_name, GetCustomRequiredStationLevel(quality));
		return (object)val;
	}

	public virtual int GetCustomAmount(int quality, out int need, out ItemData singleReqItem)
	{
		return ((Recipe)this).GetAmount(quality, ref need, ref singleReqItem, 1);
	}

	public virtual CraftingStation GetCustomRequiredStation(int quality)
	{
		return ((Recipe)this).GetRequiredStation(quality);
	}

	public virtual int GetCustomRequiredStationLevel(int quality)
	{
		return ((Recipe)this).GetRequiredStationLevel(quality);
	}

	public static Tuple<string, int> ParseItemCountPair(string rawPair)
	{
		if (rawPair == null)
		{
			throw new ArgumentNullException("rawPair");
		}
		int result = 0;
		string[] array = rawPair.Split(new char[1] { ',' });
		if (array.Length < 2)
		{
			throw new ArgumentException("Item count does not name an item!");
		}
		if (array.Length > 2)
		{
			throw new ArgumentException("Item count lists more than an item and a count!");
		}
		if (Utility.IsNullOrWhiteSpace(array[0]))
		{
			throw new ArgumentException("Item name is null or whitespace!");
		}
		if (Utility.IsNullOrWhiteSpace(array[1]))
		{
			throw new ArgumentException("Count is null or whitespace!");
		}
		if (!int.TryParse(array[1], out result))
		{
			throw new NullReferenceException("Cannot parse \"" + array[1] + "\" as an integer!");
		}
		return new Tuple<string, int>(array[0], result);
	}

	public static Dictionary<string, int> ParseRequirementString(string requirementsString)
	{
		if (requirementsString == null)
		{
			return null;
		}
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		if (Utility.IsNullOrWhiteSpace(requirementsString))
		{
			return dictionary;
		}
		try
		{
			string[] array = requirementsString.Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				Tuple<string, int> tuple = ParseItemCountPair(array[i]);
				if (tuple.Item2 > 0)
				{
					if (dictionary.ContainsKey(tuple.Item1))
					{
						dictionary[tuple.Item1] += tuple.Item2;
					}
					else
					{
						dictionary.Add(tuple.Item1, tuple.Item2);
					}
				}
			}
			return dictionary;
		}
		catch (Exception value)
		{
			Console.WriteLine(value);
			return null;
		}
	}

	public static List<T> CreateRequirements<T>(string requirementsString) where T : CustomRequirement, new()
	{
		Dictionary<string, int> dictionary = ParseRequirementString(requirementsString);
		if (dictionary == null)
		{
			return null;
		}
		List<T> list = new List<T>();
		foreach (string key in dictionary.Keys)
		{
			list.Add(new T
			{
				m_resItem = ObjectDB.instance.GetItemPrefab(key).GetComponent<ItemDrop>(),
				m_amount = dictionary[key],
				m_extraAmountOnlyOneIngredient = 0,
				m_amountPerLevel = 0,
				m_recover = true
			});
		}
		return list;
	}
}
public class CustomRequirement : Requirement
{
	public int m_applicableLevel;

	public virtual int GetCustomAmount(int qualityLevel)
	{
		if (m_applicableLevel == 0)
		{
			return ((Requirement)this).GetAmount(qualityLevel);
		}
		if (m_applicableLevel != qualityLevel)
		{
			return 0;
		}
		return base.m_amount;
	}
}
[BepInPlugin("com.riintouge.magneticwishbone", "Magnetic Wishbone", "1.1.1")]
[BepInProcess("valheim.exe")]
public class MagneticWishbone : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Humanoid))]
	private class HumanoidPatch
	{
		internal static float MaxMagneticRange(Player player)
		{
			float num = 2f;
			if (!IsEnabled.Value)
			{
				return num;
			}
			foreach (ItemData equippedItem in ((Humanoid)player).GetInventory().GetEquippedItems())
			{
				if (equippedItem.m_shared.m_name.Equals("$item_wishbone"))
				{
					int num2 = Mathf.Min(equippedItem.m_quality, MaxAllowedQuality());
					if (num2 >= 2)
					{
						num = Mathf.Max(num, Tier2PickupRadius.Value);
					}
					if (num2 >= 3)
					{
						num = Mathf.Max(num, Tier3PickupRadius.Value);
					}
					if (num2 >= 4)
					{
						num = Mathf.Max(num, Tier4PickupRadius.Value);
					}
				}
			}
			return num;
		}

		[HarmonyPatch("EquipItem")]
		[HarmonyPostfix]
		private static void EquipItemPostfix(ref bool __result, ref Humanoid __instance, ref ItemData item, ref bool triggerEquipEffects)
		{
			if (__result && item != null && item.m_equipped && item.m_shared.m_name.Equals("$item_wishbone"))
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer == (Object)(object)__instance)
				{
					localPlayer.m_autoPickupRange = MaxMagneticRange(localPlayer);
				}
			}
		}

		[HarmonyPatch("UnequipItem")]
		[HarmonyPostfix]
		private static void UnequipItemPostfix(ref Humanoid __instance, ref ItemData item, ref bool triggerEquipEffects)
		{
			if (item != null && !item.m_equipped && item.m_shared.m_name.Equals("$item_wishbone"))
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer == (Object)(object)__instance)
				{
					localPlayer.m_autoPickupRange = MaxMagneticRange(localPlayer);
				}
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui))]
	private class InventoryGuiPatch
	{
		[HarmonyPatch("AddRecipeToList")]
		[HarmonyPrefix]
		private static bool AddRecipeToListPrefix(ref InventoryGui __instance, ref Player player, ref Recipe recipe, ref ItemData item, ref bool canCraft)
		{
			if (IsEnabled.Value && !canCraft && recipe is CustomRecipe)
			{
				CustomRecipe customRecipe = (CustomRecipe)(object)recipe;
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				if ((__instance.InCraftTab() && !customRecipe.IsCraftableAt(currentCraftingStation)) || (!__instance.InCraftTab() && !customRecipe.IsUpgradableAt(item.m_quality, currentCraftingStation)))
				{
					return false;
				}
			}
			return true;
		}

		[HarmonyPatch("UpdateRecipeList")]
		[HarmonyPrefix]
		private static void UpdateRecipeListPrefix(ref InventoryGui __instance, ref List<Recipe> recipes)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!IsEnabled.Value || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			MagneticWishboneRecipe[] source = new MagneticWishboneRecipe[1] { MagneticWishboneRecipe.Instance.Value };
			List<ItemData> list = (from x in ((Humanoid)localPlayer).GetInventory().GetAllItems()
				where x != null
				select x).ToList();
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			foreach (CustomRecipe item in source.Where((CustomRecipe x) => ((Recipe)x).m_enabled))
			{
				if (__instance.InCraftTab())
				{
					if (item.IsCraftableAt(currentCraftingStation))
					{
						recipes.Add((Recipe)(object)item);
					}
					continue;
				}
				foreach (ItemData item2 in list)
				{
					if (item.AppliesTo(item2) && item.IsUpgradableAt(item2.m_quality, currentCraftingStation))
					{
						recipes.Add((Recipe)(object)item);
						break;
					}
				}
			}
		}
	}

	internal class MagneticWishboneRecipe : CustomRecipe
	{
		public static InvalidatableLazy<MagneticWishboneRecipe> Instance = new InvalidatableLazy<MagneticWishboneRecipe>(() => (MagneticWishboneRecipe)(object)ScriptableObject.CreateInstance(typeof(MagneticWishboneRecipe)));

		protected MagneticWishboneRecipe()
		{
			((Recipe)this).m_item = ObjectDB.instance.GetItemPrefab("Wishbone").GetComponent<ItemDrop>();
			((Recipe)this).m_amount = 1;
			((Recipe)this).m_enabled = true;
			((Recipe)this).m_qualityResultAmountMultiplier = 1f;
			((Recipe)this).m_craftingStation = Common.NoneCraftingStation.Value;
			((Recipe)this).m_repairStation = Common.NoneCraftingStation.Value;
			((Recipe)this).m_minStationLevel = 1;
			((Recipe)this).m_requireOnlyOneIngredient = false;
			try
			{
				List<Requirement> list = new List<Requirement>();
				if (AllowTier4.Value || AllowTier3.Value || AllowTier2.Value)
				{
					List<CustomRequirement> list2 = CustomRecipe.CreateRequirements<CustomRequirement>(Tier2Ingredients.Value);
					list2.ForEach(delegate(CustomRequirement x)
					{
						x.m_applicableLevel = 2;
					});
					list.AddRange((IEnumerable<Requirement>)list2);
				}
				if (AllowTier4.Value || AllowTier3.Value)
				{
					List<CustomRequirement> list3 = CustomRecipe.CreateRequirements<CustomRequirement>(Tier3Ingredients.Value);
					list3.ForEach(delegate(CustomRequirement x)
					{
						x.m_applicableLevel = 3;
					});
					list.AddRange((IEnumerable<Requirement>)list3);
				}
				if (AllowTier4.Value)
				{
					List<CustomRequirement> list4 = CustomRecipe.CreateRequirements<CustomRequirement>(Tier4Ingredients.Value);
					list4.ForEach(delegate(CustomRequirement x)
					{
						x.m_applicableLevel = 4;
					});
					list.AddRange((IEnumerable<Requirement>)list4);
				}
				((Recipe)this).m_resources = list.ToArray();
			}
			catch (Exception value)
			{
				((Recipe)this).m_enabled = false;
				Console.WriteLine(value);
			}
			RegisterWithVNEI();
		}

		public override bool IsCraftable()
		{
			return false;
		}

		public override bool IsCraftableAt(CraftingStation station)
		{
			return false;
		}

		public override bool IsUpgradable(int currentQuality)
		{
			return currentQuality < MaxAllowedQuality();
		}

		public override bool IsUpgradableAt(int currentQuality, CraftingStation station)
		{
			CraftingStation customRequiredStation = GetCustomRequiredStation(currentQuality + 1);
			if ((station == null || station.m_name == null) && (customRequiredStation == null || customRequiredStation.m_name == null))
			{
				return true;
			}
			if (station == null || station.m_name == null || customRequiredStation == null || customRequiredStation.m_name == null)
			{
				return false;
			}
			if (!customRequiredStation.m_name.Equals(station.m_name))
			{
				return false;
			}
			if (GetCustomRequiredStationLevel(currentQuality + 1) > station.GetLevel(true))
			{
				return false;
			}
			return true;
		}

		public override CraftingStation GetCustomRequiredStation(int quality)
		{
			switch (quality)
			{
			case 2:
				if (!AllowTier2.Value)
				{
					return Common.NoneCraftingStation.Value;
				}
				return Common.FindCraftingStationByUnlocalizedName(Tier2CraftingStation.Value.Split(new char[1] { ',' })[0]);
			case 3:
				if (!AllowTier3.Value)
				{
					return Common.NoneCraftingStation.Value;
				}
				return Common.FindCraftingStationByUnlocalizedName(Tier3CraftingStation.Value.Split(new char[1] { ',' })[0]);
			case 4:
				if (!AllowTier4.Value)
				{
					return Common.NoneCraftingStation.Value;
				}
				return Common.FindCraftingStationByUnlocalizedName(Tier4CraftingStation.Value.Split(new char[1] { ',' })[0]);
			default:
				return Common.NoneCraftingStation.Value;
			}
		}

		public override int GetCustomRequiredStationLevel(int quality)
		{
			try
			{
				switch (quality)
				{
				case 2:
					return AllowTier2.Value ? int.Parse(Tier2CraftingStation.Value.Split(new char[1] { ',' })[1]) : 999;
				case 3:
					return AllowTier3.Value ? int.Parse(Tier3CraftingStation.Value.Split(new char[1] { ',' })[1]) : 999;
				case 4:
					return AllowTier4.Value ? int.Parse(Tier4CraftingStation.Value.Split(new char[1] { ',' })[1]) : 999;
				}
			}
			catch (Exception)
			{
			}
			return 999;
		}
	}

	[HarmonyPatch(typeof(ObjectDB))]
	private class ObjectDBPatch
	{
		public static void UpdateWishboneMaxQuality()
		{
			ObjectDB instance = ObjectDB.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				GameObject itemPrefab = instance.GetItemPrefab("Wishbone");
				obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
			}
			SharedData val = (SharedData)obj;
			if (val != null)
			{
				val.m_maxQuality = MaxAllowedQuality();
			}
		}

		[HarmonyPatch("Awake")]
		[HarmonyPrefix]
		private static void AwakePrefix()
		{
			MagneticWishboneRecipe.Instance.Value = null;
		}

		[HarmonyPatch("UpdateRegisters")]
		[HarmonyPostfix]
		private static void UpdateRegistersPostfix()
		{
			UpdateWishboneMaxQuality();
		}
	}

	[HarmonyPatch(typeof(Requirement))]
	private class PieceRequirementPatch
	{
		[HarmonyPatch("GetAmount")]
		[HarmonyPrefix]
		private static bool GetAmountPrefix(ref int __result, ref Requirement __instance, ref int qualityLevel)
		{
			if (__instance is CustomRequirement)
			{
				__result = ((CustomRequirement)(object)__instance).GetCustomAmount(qualityLevel);
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Recipe))]
	private class RecipePatch
	{
		[HarmonyPatch("GetRequiredStation")]
		[HarmonyPrefix]
		private static bool GetRequiredStationPrefix(ref CraftingStation __result, ref Recipe __instance, ref int quality)
		{
			if (__instance is CustomRecipe)
			{
				__result = ((CustomRecipe)(object)__instance).GetCustomRequiredStation(quality);
				return false;
			}
			return true;
		}

		[HarmonyPatch("GetRequiredStationLevel")]
		[HarmonyPrefix]
		private static bool GetRequiredStationLevelPrefix(ref int __result, ref Recipe __instance, ref int quality)
		{
			if (__instance is CustomRecipe)
			{
				__result = ((CustomRecipe)(object)__instance).GetCustomRequiredStationLevel(quality);
				return false;
			}
			return true;
		}
	}

	public static ConfigEntry<bool> IsEnabled;

	public static ConfigEntry<bool> AllowTier2;

	public static ConfigEntry<string> Tier2CraftingStation;

	public static ConfigEntry<string> Tier2Ingredients;

	public static ConfigEntry<float> Tier2PickupRadius;

	public static ConfigEntry<bool> AllowTier3;

	public static ConfigEntry<string> Tier3CraftingStation;

	public static ConfigEntry<string> Tier3Ingredients;

	public static ConfigEntry<float> Tier3PickupRadius;

	public static ConfigEntry<bool> AllowTier4;

	public static ConfigEntry<string> Tier4CraftingStation;

	public static ConfigEntry<string> Tier4Ingredients;

	public static ConfigEntry<float> Tier4PickupRadius;

	private readonly Harmony Harmony = new Harmony("com.riintouge.magneticwishbone");

	private readonly ConfigurationManagerAttributes AdminOnlyAttribute = new ConfigurationManagerAttributes
	{
		IsAdminOnly = true
	};

	private void Awake()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Expected O, but got Unknown
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Expected O, but got Unknown
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Expected O, but got Unknown
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Expected O, but got Unknown
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Expected O, but got Unknown
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Expected O, but got Unknown
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_027a: Expected O, but got Unknown
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Expected O, but got Unknown
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Expected O, but got Unknown
		IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "Enable", true, new ConfigDescription("Whether this plugin has any effect when loaded.", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		AllowTier2 = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Basic", "AllowTier2", true, new ConfigDescription("Whether the Wishbone can be upgraded to quality level 2, and functions as such.", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier2CraftingStation = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Basic", "Tier2CraftingStation", "$piece_forge,1", new ConfigDescription("A string of the form \"UnlocalizedName,StationLevel\".", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier2Ingredients = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Basic", "Tier2Ingredients", "IronScrap,20;Root,5", new ConfigDescription("A string of the form \"ItemName1,Amount;...;ItemNameN,Amount\".", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier2PickupRadius = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Basic", "Tier2PickupRadius", 5f, new ConfigDescription("The auto-pickup range of the player, in meters, when a once-upgraded Wishbone is equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), new object[1] { AdminOnlyAttribute }));
		AllowTier3 = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Improved", "AllowTier3", true, new ConfigDescription("Whether the Wishbone can be upgraded to quality level 3, and functions as such.", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier3CraftingStation = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Improved", "Tier3CraftingStation", "$piece_artisanstation,1", new ConfigDescription("A string of the form \"UnlocalizedName,StationLevel\".", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier3Ingredients = ((BaseUnityPlugin)this).Config.Bind<string>("3 - Improved", "Tier3Ingredients", "MechanicalSpring,1;Thunderstone,1;Resin,5", new ConfigDescription("A string of the form \"ItemName1,Amount;...;ItemNameN,Amount\".", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier3PickupRadius = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Improved", "Tier3PickupRadius", 10f, new ConfigDescription("The auto-pickup range of the player, in meters, when a twice-upgraded Wishbone is equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), new object[1] { AdminOnlyAttribute }));
		AllowTier4 = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Advanced", "AllowTier4", false, new ConfigDescription("Whether the Wishbone can be upgraded to quality level 4, and functions as such.", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier4CraftingStation = ((BaseUnityPlugin)this).Config.Bind<string>("4 - Advanced", "Tier4CraftingStation", "$piece_magetable,4", new ConfigDescription("A string of the form \"UnlocalizedName,StationLevel\".", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier4Ingredients = ((BaseUnityPlugin)this).Config.Bind<string>("4 - Advanced", "Tier4Ingredients", "DarkCore,1;Wisp,1;SilverNecklace,1;LinenThread,5", new ConfigDescription("A string of the form \"ItemName1,Amount;...;ItemNameN,Amount\".", (AcceptableValueBase)null, new object[1] { AdminOnlyAttribute }));
		Tier4PickupRadius = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Advanced", "Tier4PickupRadius", 15f, new ConfigDescription("The auto-pickup range of the player, in meters, when a thrice-upgraded Wishbone is equipped.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f), new object[1] { AdminOnlyAttribute }));
		Harmony.PatchAll();
		((BaseUnityPlugin)this).Config.SettingChanged += Config_SettingChanged;
		SynchronizationManager.OnConfigurationSynchronized += SynchronizationManager_OnConfigurationSynchronized;
	}

	private void Config_SettingChanged(object sender, SettingChangedEventArgs e)
	{
		if (e.ChangedSetting == IsEnabled)
		{
			((Recipe)MagneticWishboneRecipe.Instance.Value).m_enabled = IsEnabled.Value;
		}
		else if (e.ChangedSetting == AllowTier2)
		{
			if (!AllowTier2.Value)
			{
				AllowTier3.Value = false;
			}
			ObjectDBPatch.UpdateWishboneMaxQuality();
			MagneticWishboneRecipe.Instance.Value = null;
		}
		else if (e.ChangedSetting == AllowTier3)
		{
			if (AllowTier3.Value)
			{
				AllowTier2.Value = true;
			}
			else
			{
				AllowTier4.Value = false;
			}
			ObjectDBPatch.UpdateWishboneMaxQuality();
			MagneticWishboneRecipe.Instance.Value = null;
		}
		else if (e.ChangedSetting == AllowTier4)
		{
			if (AllowTier4.Value)
			{
				AllowTier3.Value = true;
			}
			ObjectDBPatch.UpdateWishboneMaxQuality();
			MagneticWishboneRecipe.Instance.Value = null;
		}
		else if (e.ChangedSetting == Tier2Ingredients || e.ChangedSetting == Tier3Ingredients || e.ChangedSetting == Tier4Ingredients)
		{
			MagneticWishboneRecipe.Instance.Value = null;
		}
		else if (e.ChangedSetting == Tier2PickupRadius || e.ChangedSetting == Tier3PickupRadius || e.ChangedSetting == Tier4PickupRadius)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				localPlayer.m_autoPickupRange = HumanoidPatch.MaxMagneticRange(localPlayer);
			}
		}
	}

	private void SynchronizationManager_OnConfigurationSynchronized(object sender, ConfigurationSynchronizationEventArgs e)
	{
		ObjectDBPatch.UpdateWishboneMaxQuality();
		MagneticWishboneRecipe.Instance.Value = null;
	}

	public static int MaxAllowedQuality()
	{
		if (!AllowTier4.Value)
		{
			if (!AllowTier3.Value)
			{
				if (!AllowTier2.Value)
				{
					return 1;
				}
				return 2;
			}
			return 3;
		}
		return 4;
	}
}
public class InvalidatableLazy<T>
{
	private Func<T> producer;

	private T value;

	public T Value
	{
		get
		{
			lock (producer)
			{
				if (value == null)
				{
					value = producer();
				}
				return value;
			}
		}
		set
		{
			lock (producer)
			{
				if (value != null)
				{
					throw new ArgumentException("value");
				}
				this.value = default(T);
			}
		}
	}

	public InvalidatableLazy(Func<T> producer)
	{
		if (producer == null)
		{
			throw new ArgumentNullException("producer");
		}
		this.producer = producer;
	}
}