Decompiled source of MegingjordExtended v2.2.0

Gafteds.UpgradeableMegingjord.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ConditionalConfigSyncAPI;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Gafteds.UpgradeableMegingjord")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Megingjord Extended - upgrade the vanilla Megingjord through 7 quality levels at the forge.")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("Gafteds.UpgradeableMegingjord")]
[assembly: AssemblyTitle("Gafteds.UpgradeableMegingjord")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ConditionalConfigSyncAPI
{
	public enum SyncMode
	{
		AlwaysServerControlled,
		Conditional,
		AlwaysClientControlled
	}
	public enum RequirementMode
	{
		Fixed,
		Conditional
	}
	public sealed class ConfigSync
	{
		public const string PluginGuid = "_shudnal.ConditionalConfigSync";

		public const string MinimumCcsVersion = "1.0.10";

		private static readonly Version MinimumSupportedCcsVersion = new Version("1.0.10");

		private const string BridgeTypeName = "ConditionalConfigSync.SoftDependencyBridge";

		private const int MinimumBridgeApiVersion = 1;

		private readonly string _name;

		private readonly string _displayName;

		private readonly string _currentVersion;

		private readonly string _minimumRequiredVersion;

		private readonly bool _modRequired;

		private readonly RequirementMode _requirementMode;

		private readonly bool _allowClientConfigUpdatesWhenUnlocked;

		private readonly ManualLogSource _logger;

		private Type _bridgeType;

		private PropertyInfo _apiVersionProperty;

		private PropertyInfo _runtimeReadyProperty;

		private MethodInfo _createConfigSyncMethod;

		private MethodInfo _registerConfigEntryMethod;

		private MethodInfo _registerLockingConfigEntryMethod;

		private object _configSyncInstance;

		private bool _permanentFailure;

		private bool _permanentFailureLogged;

		private string _failureReason;

		public bool IsAvailable
		{
			get
			{
				if (EnsureBridge())
				{
					return IsRuntimeReady();
				}
				return false;
			}
		}

		public bool IsActive => _configSyncInstance != null;

		public string FailureReason => _failureReason;

		public ConfigSync(string name, string displayName, string currentVersion, string minimumRequiredVersion = null, bool modRequired = false, RequirementMode requirementMode = RequirementMode.Fixed, bool allowClientConfigUpdatesWhenUnlocked = false, ManualLogSource logger = null)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				throw new ArgumentException("A stable mod GUID is required.", "name");
			}
			_name = name;
			_displayName = (string.IsNullOrWhiteSpace(displayName) ? name : displayName);
			_currentVersion = currentVersion;
			_minimumRequiredVersion = minimumRequiredVersion;
			_modRequired = modRequired;
			_requirementMode = requirementMode;
			_allowClientConfigUpdatesWhenUnlocked = allowClientConfigUpdatesWhenUnlocked;
			_logger = logger;
		}

		public bool TryActivate()
		{
			return EnsureContext();
		}

		public ConfigEntry<T> Bind<T>(ConfigFile configFile, string section, string key, T defaultValue, string description, SyncMode syncMode = SyncMode.Conditional, bool serverControlledByDefault = true)
		{
			if (configFile == null)
			{
				throw new ArgumentNullException("configFile");
			}
			ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description);
			RegisterConfigEntry<T>(val, syncMode, serverControlledByDefault);
			return val;
		}

		public ConfigEntry<T> Bind<T>(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription description, SyncMode syncMode = SyncMode.Conditional, bool serverControlledByDefault = true)
		{
			if (configFile == null)
			{
				throw new ArgumentNullException("configFile");
			}
			ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description);
			RegisterConfigEntry<T>(val, syncMode, serverControlledByDefault);
			return val;
		}

		public bool RegisterConfigEntry<T>(ConfigEntry<T> entry, SyncMode syncMode = SyncMode.Conditional, bool serverControlledByDefault = true)
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			if (!EnsureContext())
			{
				return false;
			}
			try
			{
				Invoke(_registerConfigEntryMethod, null, new object[4]
				{
					_configSyncInstance,
					entry,
					syncMode.ToString(),
					serverControlledByDefault
				});
				return true;
			}
			catch (Exception exception)
			{
				LogWarning("Failed to register config entry '" + ((ConfigEntryBase)entry).Definition.Section + " -> " + ((ConfigEntryBase)entry).Definition.Key + "' with Conditional Config Sync. The entry remains a normal local BepInEx setting. " + GetInnermostMessage(exception));
				return false;
			}
		}

		public bool RegisterLockingConfigEntry<T>(ConfigEntry<T> entry) where T : IConvertible
		{
			if (entry == null)
			{
				throw new ArgumentNullException("entry");
			}
			if (!EnsureContext())
			{
				return false;
			}
			try
			{
				Invoke(_registerLockingConfigEntryMethod, null, new object[2] { _configSyncInstance, entry });
				return true;
			}
			catch (Exception exception)
			{
				LogWarning("Failed to register locking config entry '" + ((ConfigEntryBase)entry).Definition.Section + " -> " + ((ConfigEntryBase)entry).Definition.Key + "' with Conditional Config Sync. The entry remains a normal local BepInEx setting. " + GetInnermostMessage(exception));
				return false;
			}
		}

		public ConfigEntry<T> BindLocking<T>(ConfigFile configFile, string section, string key, T defaultValue, string description) where T : IConvertible
		{
			if (configFile == null)
			{
				throw new ArgumentNullException("configFile");
			}
			ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description);
			RegisterLockingConfigEntry<T>(val);
			return val;
		}

		public ConfigEntry<T> BindLocking<T>(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription description) where T : IConvertible
		{
			if (configFile == null)
			{
				throw new ArgumentNullException("configFile");
			}
			ConfigEntry<T> val = configFile.Bind<T>(section, key, defaultValue, description);
			RegisterLockingConfigEntry<T>(val);
			return val;
		}

		private bool EnsureContext()
		{
			if (_configSyncInstance != null)
			{
				return true;
			}
			if (_permanentFailure || !EnsureBridge() || !IsRuntimeReady())
			{
				return false;
			}
			try
			{
				_configSyncInstance = Invoke(_createConfigSyncMethod, null, new object[7]
				{
					_name,
					_displayName,
					_currentVersion,
					_minimumRequiredVersion,
					_modRequired,
					_requirementMode.ToString(),
					_allowClientConfigUpdatesWhenUnlocked
				});
				if (_configSyncInstance == null)
				{
					SetPermanentFailure("Conditional Config Sync returned no consumer context.", null);
					return false;
				}
				return true;
			}
			catch (Exception exception)
			{
				SetPermanentFailure("Failed to create the Conditional Config Sync consumer context.", exception);
				return false;
			}
		}

		private bool EnsureBridge()
		{
			if (_bridgeType != null)
			{
				return true;
			}
			if (_permanentFailure)
			{
				return false;
			}
			try
			{
				if (!Chainloader.PluginInfos.TryGetValue("_shudnal.ConditionalConfigSync", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
				{
					return false;
				}
				if (value.Metadata == null || value.Metadata.Version == null || value.Metadata.Version.CompareTo(MinimumSupportedCcsVersion) < 0)
				{
					return false;
				}
				Type type = ((object)value.Instance).GetType().Assembly.GetType("ConditionalConfigSync.SoftDependencyBridge", throwOnError: false);
				if (type == null)
				{
					SetPermanentFailure("The installed Conditional Config Sync version does not expose the optional soft-dependency bridge.", null);
					return false;
				}
				PropertyInfo property = type.GetProperty("ApiVersion", BindingFlags.Static | BindingFlags.Public);
				PropertyInfo property2 = type.GetProperty("IsRuntimeReady", BindingFlags.Static | BindingFlags.Public);
				MethodInfo method = type.GetMethod("CreateConfigSync", BindingFlags.Static | BindingFlags.Public, null, new Type[7]
				{
					typeof(string),
					typeof(string),
					typeof(string),
					typeof(string),
					typeof(bool),
					typeof(string),
					typeof(bool)
				}, null);
				MethodInfo method2 = type.GetMethod("RegisterConfigEntry", BindingFlags.Static | BindingFlags.Public, null, new Type[4]
				{
					typeof(object),
					typeof(ConfigEntryBase),
					typeof(string),
					typeof(bool)
				}, null);
				MethodInfo method3 = type.GetMethod("RegisterLockingConfigEntry", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(object),
					typeof(ConfigEntryBase)
				}, null);
				if (property == null || property2 == null || method == null || method2 == null || method3 == null)
				{
					SetPermanentFailure("The installed Conditional Config Sync soft-dependency bridge is incomplete or incompatible.", null);
					return false;
				}
				if (!(property.GetValue(null, null) is int num) || num < 1)
				{
					SetPermanentFailure("The installed Conditional Config Sync soft-dependency bridge version is not supported.", null);
					return false;
				}
				_bridgeType = type;
				_apiVersionProperty = property;
				_runtimeReadyProperty = property2;
				_createConfigSyncMethod = method;
				_registerConfigEntryMethod = method2;
				_registerLockingConfigEntryMethod = method3;
				return true;
			}
			catch (Exception exception)
			{
				SetPermanentFailure("Failed to resolve the Conditional Config Sync soft-dependency bridge.", exception);
				return false;
			}
		}

		private bool IsRuntimeReady()
		{
			try
			{
				object value = _runtimeReadyProperty.GetValue(null, null);
				bool flag = default(bool);
				int num;
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch (Exception exception)
			{
				SetPermanentFailure("Failed to query the Conditional Config Sync runtime state.", exception);
				return false;
			}
		}

		private static object Invoke(MethodInfo method, object target, object[] arguments)
		{
			try
			{
				return method.Invoke(target, arguments);
			}
			catch (TargetInvocationException ex) when (ex.InnerException != null)
			{
				ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
				throw;
			}
		}

		private void SetPermanentFailure(string message, Exception exception)
		{
			_permanentFailure = true;
			_failureReason = ((exception == null) ? message : (message + " " + GetInnermostMessage(exception)));
			if (!_permanentFailureLogged)
			{
				_permanentFailureLogged = true;
				LogWarning(_failureReason);
			}
		}

		private void LogWarning(string message)
		{
			if (_logger != null)
			{
				_logger.LogWarning((object)message);
			}
		}

		private static string GetInnermostMessage(Exception exception)
		{
			Exception ex = exception;
			while (ex.InnerException != null)
			{
				ex = ex.InnerException;
			}
			return ex.Message;
		}
	}
}
namespace Gafteds.UpgradeableMegingjord
{
	[HarmonyPatch(typeof(Player), "GetMaxCarryWeight")]
	internal static class GetMaxCarryWeight_Patch
	{
		private static void Postfix(Player __instance, ref float __result)
		{
			Inventory val = (((Object)(object)__instance != (Object)null) ? ((Humanoid)__instance).GetInventory() : null);
			if (val == null)
			{
				return;
			}
			int num = 0;
			foreach (ItemData allItem in val.GetAllItems())
			{
				if (allItem == null || !allItem.m_equipped)
				{
					continue;
				}
				GameObject dropPrefab = allItem.m_dropPrefab;
				if (!((Object)(object)dropPrefab == (Object)null) && !(((Object)dropPrefab).name != "BeltStrength"))
				{
					int num2 = BeltUpgrades.CarryForQuality(allItem.m_quality) - 150;
					if (num2 > num)
					{
						num = num2;
					}
				}
			}
			if (num > 0)
			{
				__result += num;
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(int) })]
	internal static class BeltTooltip_Patch
	{
		private static readonly Regex s_carryRegex = new Regex("\\+150\\b", RegexOptions.Compiled);

		private static void Postfix(ItemData __instance, ref string __result)
		{
			if (__instance == null || string.IsNullOrEmpty(__result))
			{
				return;
			}
			GameObject dropPrefab = __instance.m_dropPrefab;
			if (!((Object)(object)dropPrefab == (Object)null) && !(((Object)dropPrefab).name != "BeltStrength"))
			{
				int num = BeltUpgrades.CarryForQuality(__instance.m_quality);
				if (num != 150)
				{
					__result = s_carryRegex.Replace(__result, "+" + num);
				}
			}
		}
	}
	public static class BeltUpgrades
	{
		public struct SwapState
		{
			public bool applied;

			public Recipe recipe;

			public Requirement[] oldResources;

			public int oldMinLevel;
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_Patch
		{
			private static void Postfix(ObjectDB __instance)
			{
				Register(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")]
		private static class SetupRequirementList_Patch
		{
			private static readonly FieldInfo s_selectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe");

			private static readonly MethodInfo s_getRecipe = ((s_selectedRecipeField != null) ? AccessTools.Method(s_selectedRecipeField.FieldType, "get_Recipe", (Type[])null, (Type[])null) : null);

			[HarmonyPriority(800)]
			private static void Prefix(InventoryGui __instance, int quality, Player player, out SwapState __state)
			{
				Recipe recipe = null;
				if ((Object)(object)__instance != (Object)null && s_selectedRecipeField != null && s_getRecipe != null)
				{
					object value = s_selectedRecipeField.GetValue(__instance);
					if (value != null)
					{
						object? obj = s_getRecipe.Invoke(value, null);
						recipe = (Recipe)((obj is Recipe) ? obj : null);
					}
				}
				__state = TryApplyFiltered(recipe, quality, player);
			}

			[HarmonyPriority(0)]
			private static void Postfix(SwapState __state)
			{
				Restore(__state);
			}

			[HarmonyPriority(0)]
			private static void Finalizer(SwapState __state)
			{
				Restore(__state);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class DoCrafting_Patch
		{
			[HarmonyPriority(800)]
			private static void Prefix(out SwapState __state, ItemData ___m_craftUpgradeItem, Recipe ___m_craftRecipe)
			{
				int targetQuality = ((___m_craftUpgradeItem == null) ? 1 : (___m_craftUpgradeItem.m_quality + 1));
				__state = TryApply(___m_craftRecipe, targetQuality);
			}

			[HarmonyPriority(0)]
			private static void Postfix(SwapState __state)
			{
				Restore(__state);
			}

			[HarmonyPriority(0)]
			private static void Finalizer(SwapState __state)
			{
				Restore(__state);
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		private static class HaveRequirementItems_Patch
		{
			[HarmonyPriority(800)]
			private static void Prefix(Recipe piece, bool discover, int qualityLevel, out SwapState __state)
			{
				__state = default(SwapState);
				if (!discover)
				{
					__state = TryApply(piece, qualityLevel);
				}
			}

			[HarmonyPriority(0)]
			private static void Postfix(SwapState __state)
			{
				Restore(__state);
			}

			[HarmonyPriority(0)]
			private static void Finalizer(SwapState __state)
			{
				Restore(__state);
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirementItems")]
		private static class HaveRequirementItems_DiscoveryBlock_Patch
		{
			private static void Postfix(Player __instance, Recipe piece, bool discover, int qualityLevel, ref bool __result)
			{
				if (!__result)
				{
					return;
				}
				if (discover && qualityLevel <= 1 && (Object)(object)piece != (Object)null && (Object)(object)piece.m_item != (Object)null && ((Object)piece.m_item).name == "BeltStrength" && !EnableBaseCraft)
				{
					__result = false;
				}
				else if (!discover && !((Object)(object)piece == (Object)null) && !((Object)(object)piece.m_item == (Object)null) && !(((Object)piece.m_item).name != "BeltStrength"))
				{
					if (qualityLevel <= 1 && !EnableBaseCraft)
					{
						__result = false;
					}
					else if (qualityLevel > 1 && !HasDiscoveredAll(__instance, qualityLevel))
					{
						__result = false;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Requirement), "GetAmount")]
		private static class Requirement_GetAmount_Patch
		{
			private static void Postfix(Requirement __instance, int qualityLevel, ref int __result)
			{
				if (IsOurRequirement(__instance))
				{
					__result = __instance.m_amount;
				}
			}
		}

		[HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel")]
		private static class GetRequiredStationLevel_Patch
		{
			private static void Postfix(Recipe __instance, int quality, ref int __result)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_item == (Object)null) && !(((Object)__instance.m_item).name != "BeltStrength"))
				{
					__result = GetForgeForQuality(quality);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnTabUpgradePressed")]
		private static class OnTabUpgradePressed_Patch
		{
			private static void Prefix()
			{
				IsUpgradeTab = true;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnTabCraftPressed")]
		private static class OnTabCraftPressed_Patch
		{
			private static void Prefix()
			{
				IsUpgradeTab = false;
			}
		}

		[HarmonyPatch(typeof(Player), "GetAvailableRecipes")]
		private static class GetAvailableRecipes_HideBaseCraft_Patch
		{
			private static void Postfix(Player __instance, ref List<Recipe> available)
			{
				if ((Object)(object)__instance != (Object)null && PlayerHasBelt(__instance))
				{
					EnsureRecipeKnown(__instance);
				}
				if (!EnableBaseCraft && available != null && !IsUpgradeTab)
				{
					available.RemoveAll((Recipe rec) => (Object)(object)rec != (Object)null && (Object)(object)rec.m_item != (Object)null && ((Object)rec.m_item).name == "BeltStrength");
				}
			}
		}

		[HarmonyPatch(typeof(Player), "AddKnownItem")]
		private static class AddKnownItem_Patch
		{
			private static readonly MethodInfo s_addKnownRecipe = AccessTools.Method(typeof(Player), "AddKnownRecipe", (Type[])null, (Type[])null);

			private static void Postfix(Player __instance, ItemData item)
			{
				if (!((Object)(object)__instance == (Object)null) && item != null && !((Object)(object)item.m_dropPrefab == (Object)null) && !(((Object)item.m_dropPrefab).name != "BeltStrength"))
				{
					Recipe beltRecipe = BeltRecipe;
					if (!((Object)(object)beltRecipe == (Object)null) && !(s_addKnownRecipe == null))
					{
						s_addKnownRecipe.Invoke(__instance, new object[1] { beltRecipe });
					}
				}
			}
		}

		public const string BeltPrefabName = "BeltStrength";

		public const int MaxQuality = 7;

		public const int VanillaCarryBonus = 150;

		internal static ManualLogSource Log;

		private static ConfigEntry<string>[] s_recipes;

		private static ConfigEntry<int>[] s_carry;

		private static ConfigEntry<int>[] s_forge;

		private static ConfigEntry<bool> s_enableBaseCraft;

		private static ConfigEntry<bool> s_configLocked;

		internal static Recipe BeltRecipe;

		public static bool IsUpgradeTab;

		private static Dictionary<int, Requirement[]> s_requirements;

		private static HashSet<Requirement> s_ourRequirements;

		public static bool EnableBaseCraft
		{
			get
			{
				if (s_enableBaseCraft != null)
				{
					return s_enableBaseCraft.Value;
				}
				return false;
			}
		}

		public static void BindConfig(ConfigFile config, ConfigSync configSync)
		{
			s_recipes = new ConfigEntry<string>[8];
			s_carry = new ConfigEntry<int>[8];
			s_forge = new ConfigEntry<int>[8];
			string[] array = new string[8] { null, "Q1 Base belt (craft)", "Q2 Swamp upgrade", "Q3 Mountain upgrade", "Q4 Plains upgrade", "Q5 Mistlands upgrade", "Q6 Ashlands upgrade", "Q7 Deep North upgrade" };
			string[] array2 = new string[8] { null, "Iron:10,Coins:100,Guck:20,BjornHide:15,Chain:3", "Iron:30,Chain:5,TrophyWrithan:1", "Silver:30,Crystal:30,TrophySGolem:1", "BlackMetal:30,LoxPelt:15,TrophyGoblinBrute:1", "BlackMarble:50,ScaleHide:30,TrophyGjall:1", "FlametalNew:30,MoltenCore:2,TrophyMorgen:1", "Gold:30,AncientCoin:15,TrophyMole:1" };
			int[] array3 = new int[8] { 0, 150, 200, 250, 300, 350, 400, 450 };
			int[] array4 = new int[8] { 0, 1, 2, 3, 4, 5, 6, 7 };
			s_configLocked = configSync.BindLocking(config, "General", "Lock Configuration", defaultValue: true, "Whether the configuration is locked to the server's values. When locked, clients cannot override synced settings; server admins can always edit them.");
			s_enableBaseCraft = configSync.Bind(config, "General", "Enable Base Belt Crafting", defaultValue: false, "Whether the base Megingjord (Q1) can be crafted at the forge. Default OFF: buy the belt from Haldor, then upgrade it at the forge. When disabled, the base craft recipe is hidden.", SyncMode.AlwaysServerControlled);
			for (int i = 1; i <= 7; i++)
			{
				s_recipes[i] = configSync.Bind(config, "Recipes", array[i], array2[i], "Materials for " + array[i] + ". Format: \"PrefabName:amount,PrefabName:amount,...\".", SyncMode.AlwaysServerControlled);
				s_recipes[i].SettingChanged += delegate
				{
					Rebuild();
				};
				s_carry[i] = configSync.Bind(config, "Carry Weight", array[i], array3[i], $"Total carry bonus while a quality {i} belt is equipped. (Vanilla already grants {150}; only the difference is added.)", SyncMode.AlwaysServerControlled);
				s_forge[i] = configSync.Bind(config, "Forge Levels", array[i], array4[i], "Forge level required for " + array[i] + ".", SyncMode.AlwaysServerControlled);
				s_forge[i].SettingChanged += delegate
				{
					Rebuild();
				};
			}
		}

		public static int CarryForQuality(int quality)
		{
			if (quality < 1)
			{
				quality = 1;
			}
			if (quality > 7)
			{
				quality = 7;
			}
			return s_carry[quality].Value;
		}

		public static int GetForgeForQuality(int quality)
		{
			if (quality < 1)
			{
				quality = 1;
			}
			if (quality > 7)
			{
				quality = 7;
			}
			return s_forge[quality].Value;
		}

		internal static bool IsOurRequirement(Requirement req)
		{
			if (req != null && s_ourRequirements != null)
			{
				return s_ourRequirements.Contains(req);
			}
			return false;
		}

		internal static Requirement[] GetRequirements(int quality)
		{
			if (s_requirements != null && s_requirements.TryGetValue(quality, out var value))
			{
				return value;
			}
			return null;
		}

		public static bool HasDiscoveredAll(Player player, int quality)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			Requirement[] requirements = GetRequirements(quality);
			if (requirements == null)
			{
				return false;
			}
			Requirement[] array = requirements;
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i]?.m_resItem?.m_itemData?.m_shared?.m_name;
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				try
				{
					if (!player.IsKnownMaterial(text))
					{
						return false;
					}
				}
				catch
				{
					return false;
				}
			}
			return true;
		}

		public static SwapState TryApplyFiltered(Recipe recipe, int targetQuality, Player player)
		{
			SwapState result = default(SwapState);
			if ((Object)(object)recipe == (Object)null || (Object)(object)recipe != (Object)(object)BeltRecipe)
			{
				return result;
			}
			if (targetQuality < 1 || targetQuality > 7)
			{
				return result;
			}
			if (s_requirements == null || !s_requirements.TryGetValue(targetQuality, out var value))
			{
				return result;
			}
			Requirement[] resources = value;
			if ((Object)(object)player != (Object)null)
			{
				List<Requirement> list = new List<Requirement>();
				Requirement[] array = value;
				foreach (Requirement val in array)
				{
					string text = val?.m_resItem?.m_itemData?.m_shared?.m_name;
					bool flag = string.IsNullOrEmpty(text);
					if (!flag)
					{
						try
						{
							flag = player.IsKnownMaterial(text);
						}
						catch
						{
							flag = false;
						}
					}
					if (flag)
					{
						list.Add(val);
					}
				}
				resources = list.ToArray();
			}
			result.applied = true;
			result.recipe = recipe;
			result.oldResources = recipe.m_resources;
			result.oldMinLevel = recipe.m_minStationLevel;
			recipe.m_resources = resources;
			int value2 = s_forge[targetQuality].Value;
			recipe.m_minStationLevel = Math.Max(1, value2 - (targetQuality - 1));
			return result;
		}

		public static bool PlayerHasBelt(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			string text = null;
			if ((Object)(object)BeltRecipe != (Object)null && (Object)(object)BeltRecipe.m_item != (Object)null && BeltRecipe.m_item.m_itemData != null && BeltRecipe.m_item.m_itemData.m_shared != null)
			{
				text = BeltRecipe.m_item.m_itemData.m_shared.m_name;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null)
				{
					if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == "BeltStrength")
					{
						return true;
					}
					if (text != null && allItem.m_shared != null && allItem.m_shared.m_name == text)
					{
						return true;
					}
				}
			}
			foreach (ItemData equippedItem in inventory.GetEquippedItems())
			{
				if (equippedItem != null)
				{
					if ((Object)(object)equippedItem.m_dropPrefab != (Object)null && ((Object)equippedItem.m_dropPrefab).name == "BeltStrength")
					{
						return true;
					}
					if (text != null && equippedItem.m_shared != null && equippedItem.m_shared.m_name == text)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static void EnsureRecipeKnown(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)BeltRecipe == (Object)null)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Player), "AddKnownRecipe", (Type[])null, (Type[])null);
				if (!(methodInfo == null) && !player.IsRecipeKnown(((Object)BeltRecipe).name))
				{
					methodInfo.Invoke(player, new object[1] { BeltRecipe });
				}
			}
			catch
			{
			}
		}

		public static void Register(ObjectDB objectDB)
		{
			if ((Object)(object)BeltRecipe != (Object)null)
			{
				Rebuild();
				return;
			}
			GameObject itemPrefab = objectDB.GetItemPrefab("BeltStrength");
			if ((Object)(object)itemPrefab == (Object)null)
			{
				Log.LogInfo((object)"Vanilla belt prefab 'BeltStrength' not yet available (ObjectDB still loading) - will retry on next Awake.");
				return;
			}
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
			{
				Log.LogError((object)"Vanilla belt prefab has no ItemDrop/SharedData - Megingjord Extended disabled.");
				return;
			}
			component.m_itemData.m_shared.m_maxQuality = 7;
			CraftingStation val = FindForgeStation(objectDB);
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"Could not find the forge crafting station - Megingjord Extended disabled.");
				return;
			}
			RebuildTables();
			objectDB.m_recipes.RemoveAll((Recipe r) => (Object)(object)r != (Object)null && ((Object)r).name == "BeltStrength");
			Recipe val2 = ScriptableObject.CreateInstance<Recipe>();
			((Object)val2).name = "BeltStrength";
			val2.m_item = component;
			val2.m_craftingStation = val;
			val2.m_amount = 1;
			val2.m_enabled = true;
			ApplyTables(val2);
			objectDB.m_recipes.Add(val2);
			BeltRecipe = val2;
			Log.LogInfo((object)$"Registered upgradeable vanilla Megingjord: qualities 1-{7} at the forge.");
		}

		private static void Rebuild()
		{
			if (!((Object)(object)BeltRecipe == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null))
			{
				RebuildTables();
				ApplyTables(BeltRecipe);
				Log.LogInfo((object)"Megingjord Extended config reloaded.");
			}
		}

		private static void ApplyTables(Recipe recipe)
		{
			recipe.m_resources = s_requirements[1];
			recipe.m_minStationLevel = s_forge[1].Value;
		}

		private static void RebuildTables()
		{
			Dictionary<int, Requirement[]> dictionary = new Dictionary<int, Requirement[]>();
			HashSet<Requirement> hashSet = new HashSet<Requirement>();
			for (int i = 1; i <= 7; i++)
			{
				List<Requirement> list = ParseRequirements(s_recipes[i].Value, i);
				dictionary[i] = list.ToArray();
				foreach (Requirement item in list)
				{
					hashSet.Add(item);
				}
			}
			s_requirements = dictionary;
			s_ourRequirements = hashSet;
		}

		private static List<Requirement> ParseRequirements(string text, int quality)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			List<Requirement> list = new List<Requirement>();
			if (string.IsNullOrWhiteSpace(text))
			{
				return list;
			}
			string[] array = text.Split(',');
			foreach (string text2 in array)
			{
				string[] array2 = text2.Split(':');
				if (array2.Length != 2)
				{
					Log.LogWarning((object)$"Bad recipe entry '{text2}' for quality {quality} - expected \"PrefabName:amount\". Skipped.");
					continue;
				}
				string text3 = array2[0].Trim();
				if (!int.TryParse(array2[1].Trim(), out var result) || result <= 0)
				{
					Log.LogWarning((object)$"Bad amount in '{text2}' for quality {quality} - skipped.");
					continue;
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text3);
				ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null)
				{
					Log.LogWarning((object)$"Unknown item '{text3}' in quality {quality} recipe - skipped.");
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = val,
					m_amount = result
				});
			}
			return list;
		}

		private static CraftingStation FindForgeStation(ObjectDB objectDB)
		{
			foreach (Recipe recipe in objectDB.m_recipes)
			{
				CraftingStation val = (((Object)(object)recipe != (Object)null) ? recipe.m_craftingStation : null);
				if ((Object)(object)val != (Object)null && val.m_name == "$piece_forge")
				{
					return val;
				}
			}
			foreach (Recipe recipe2 in objectDB.m_recipes)
			{
				CraftingStation val2 = (((Object)(object)recipe2 != (Object)null) ? recipe2.m_craftingStation : null);
				if ((Object)(object)val2 != (Object)null && val2.m_name != null && val2.m_name.ToLowerInvariant().Contains("forge"))
				{
					return val2;
				}
			}
			return null;
		}

		public static SwapState TryApply(Recipe recipe, int targetQuality)
		{
			SwapState result = default(SwapState);
			if ((Object)(object)recipe == (Object)null || (Object)(object)recipe != (Object)(object)BeltRecipe)
			{
				return result;
			}
			if (targetQuality < 1 || targetQuality > 7)
			{
				return result;
			}
			if (s_requirements == null || !s_requirements.TryGetValue(targetQuality, out var value))
			{
				return result;
			}
			result.applied = true;
			result.recipe = recipe;
			result.oldResources = recipe.m_resources;
			result.oldMinLevel = recipe.m_minStationLevel;
			recipe.m_resources = value;
			int value2 = s_forge[targetQuality].Value;
			recipe.m_minStationLevel = Math.Max(1, value2 - (targetQuality - 1));
			return result;
		}

		public static void Restore(SwapState state)
		{
			if (state.applied && !((Object)(object)state.recipe == (Object)null))
			{
				state.recipe.m_resources = state.oldResources;
				state.recipe.m_minStationLevel = state.oldMinLevel;
			}
		}
	}
	[BepInPlugin("gafteds.upgradeablemegingjord", "Megingjord Extended", "2.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class UpgradeableMegingjordPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "gafteds.upgradeablemegingjord";

		public const string PluginName = "Megingjord Extended";

		public const string PluginVersion = "2.2.0";

		internal static UpgradeableMegingjordPlugin Instance;

		internal static ConfigSync ConfigSync;

		private void Awake()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			BeltUpgrades.Log = ((BaseUnityPlugin)this).Logger;
			ConfigSync = new ConfigSync("gafteds.upgradeablemegingjord", "Megingjord Extended", "2.2.0", "2.2.0", modRequired: false, RequirementMode.Fixed, allowClientConfigUpdatesWhenUnlocked: false, ((BaseUnityPlugin)this).Logger);
			BeltUpgrades.BindConfig(((BaseUnityPlugin)this).Config, ConfigSync);
			new Harmony("gafteds.upgradeablemegingjord").PatchAll(Assembly.GetExecutingAssembly());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Megingjord Extended v2.2.0 loaded.");
		}
	}
}