Decompiled source of Valheim Enchantment System v1.9.12

kg.ValheimEnchantmentSystem.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemDataManager;
using JetBrains.Annotations;
using Jewelcrafting;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using PieceManager;
using ServerSync;
using SkillManager;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;
using fastJSON;
using kg.ValheimEnchantmentSystem;
using kg.ValheimEnchantmentSystem.Configs;
using kg.ValheimEnchantmentSystem.Integrations;
using kg.ValheimEnchantmentSystem.Items_Structures;
using kg.ValheimEnchantmentSystem.Misc;
using kg.ValheimEnchantmentSystem.Platform;
using kg.ValheimEnchantmentSystem.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimEnchantmentSystem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimEnchantmentSystem")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: InternalsVisibleTo("ValheimEnchantmentSystem.RuleTests")]
[assembly: Guid("02E7D016-77BE-40E0-9D13-8656CD0A4FD3")]
[assembly: AssemblyFileVersion("1.9.12")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.9.12.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;
		}
	}
}
public static class AnimationSpeedManager
{
	public delegate double Handler(Character character, double speed);

	private static readonly Harmony Harmony = new Harmony("kg.ValheimEnchantmentSystem.AnimationSpeedManager");

	private static readonly MethodInfo TargetMethod = AccessTools.DeclaredMethod(typeof(CharacterAnimEvent), "CustomFixedUpdate", (Type[])null, (Type[])null);

	private static readonly Dictionary<int, List<Handler>> HandlersByPriority = new Dictionary<int, List<Handler>>();

	private static Handler[][] _handlers = Array.Empty<Handler[]>();

	private static bool _markerPatchInstalled;

	private static bool _wrapperInstalled;

	private static int _handlerIndex;

	private static bool _changed;

	[PublicAPI]
	public static void Add(Handler handler, int priority = 400)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Expected O, but got Unknown
		if (!_markerPatchInstalled)
		{
			Harmony.Patch((MethodBase)TargetMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AnimationSpeedManager), "MarkerPatch", (Type[])null, (Type[])null)), (HarmonyMethod)null);
			_markerPatchInstalled = true;
		}
		if (!HandlersByPriority.TryGetValue(priority, out List<Handler> value))
		{
			value = new List<Handler>();
			HandlersByPriority.Add(priority, value);
		}
		if (!_wrapperInstalled)
		{
			Harmony.Patch((MethodBase)TargetMethod, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AnimationSpeedManager), "Wrapper", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			_wrapperInstalled = true;
		}
		value.Add(handler);
		_handlers = (from pair in HandlersByPriority
			orderby pair.Key
			select pair.Value.ToArray()).ToArray();
	}

	private static void Wrapper(Character ___m_character, Animator ___m_animator)
	{
		double num = (double)___m_animator.speed * 10000000.0 % 100.0;
		if ((!(num > 10.0) || !(num < 30.0)) && !(___m_animator.speed <= 0.001f))
		{
			double num2 = ___m_animator.speed;
			double num3 = _handlers[_handlerIndex++].Aggregate(num2, (double current, Handler handler) => handler(___m_character, current));
			if (Math.Abs(num3 - num2) > double.Epsilon)
			{
				___m_animator.speed = (float)(num3 - num3 % 1E-05);
				_changed = true;
			}
		}
	}

	private static void MarkerPatch(Animator ___m_animator)
	{
		if (_changed)
		{
			float speed = ___m_animator.speed;
			double num = (double)speed * 10000000.0 % 100.0;
			if ((num < 10.0 || num > 30.0) ? true : false)
			{
				___m_animator.speed += 1.9E-06f;
			}
			_changed = false;
		}
		_handlerIndex = 0;
	}
}
namespace PieceManager
{
	[PublicAPI]
	public enum CraftingTable
	{
		None,
		[InternalName("piece_workbench")]
		Workbench,
		[InternalName("piece_cauldron")]
		Cauldron,
		[InternalName("forge")]
		Forge,
		[InternalName("piece_artisanstation")]
		ArtisanTable,
		[InternalName("piece_stonecutter")]
		StoneCutter,
		[InternalName("piece_magetable")]
		MageTable,
		[InternalName("blackforge")]
		BlackForge,
		[InternalName("piece_preptable")]
		FoodPreparationTable,
		[InternalName("piece_MeadCauldron")]
		MeadKetill,
		Custom
	}
	public class InternalName : Attribute
	{
		public readonly string internalName;

		public InternalName(string internalName)
		{
			this.internalName = internalName;
		}
	}
	[PublicAPI]
	public enum BuildPieceCategory
	{
		Misc = 0,
		Crafting = 1,
		BuildingWorkbench = 2,
		BuildingStonecutter = 3,
		Furniture = 4,
		All = 100,
		Custom = 99
	}
	public struct Requirement
	{
		public string itemName;

		public int amount;

		public bool recover;
	}
	[PublicAPI]
	public class RequiredResourcesList
	{
		public readonly List<Requirement> Requirements = new List<Requirement>();

		public void Add(string item, int amount, bool recover)
		{
			Requirements.Add(new Requirement
			{
				itemName = item,
				amount = amount,
				recover = recover
			});
		}
	}
	public struct CraftingStationConfig
	{
		public CraftingTable Table;

		public string? custom;
	}
	[PublicAPI]
	public class CraftingStationList
	{
		public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>();

		public void Set(CraftingTable table)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = table
			});
		}

		public void Set(string customTable)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = CraftingTable.Custom,
				custom = customTable
			});
		}
	}
	[PublicAPI]
	public class BuildingPieceCategory
	{
		public BuildPieceCategory Category;

		public string custom = "";

		public void Set(BuildPieceCategory category)
		{
			Category = category;
		}

		public void Set(string customCategory)
		{
			Category = BuildPieceCategory.Custom;
			custom = customCategory;
		}
	}
	[PublicAPI]
	public class PieceTool
	{
		public readonly HashSet<string> Tools = new HashSet<string>();

		public void Add(string tool)
		{
			Tools.Add(tool);
		}
	}
	[PublicAPI]
	public class BuildPiece
	{
		private sealed class PieceConfig
		{
			public ConfigEntry<string>? craft;
		}

		private static class SerializedRequirements
		{
			public static string Serialize(IEnumerable<Requirement> requirements)
			{
				return string.Join(",", requirements.Select((Requirement requirement) => $"{requirement.itemName}:{requirement.amount}:{requirement.recover}"));
			}

			public static Requirement[] ToPieceReqs(ObjectDB objectDb, IEnumerable<Requirement> requirements)
			{
				return (from requirement in requirements.Where((Requirement requirement) => !string.IsNullOrWhiteSpace(requirement.itemName)).Select((Func<Requirement, Requirement>)delegate(Requirement requirement)
					{
						//IL_0057: Unknown result type (might be due to invalid IL or missing references)
						//IL_005c: Unknown result type (might be due to invalid IL or missing references)
						//IL_0063: Unknown result type (might be due to invalid IL or missing references)
						//IL_006f: Unknown result type (might be due to invalid IL or missing references)
						//IL_007c: Expected O, but got Unknown
						GameObject itemPrefab = objectDb.GetItemPrefab(requirement.itemName);
						ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
						if (!((Object)(object)val == (Object)null))
						{
							return new Requirement
							{
								m_resItem = val,
								m_amount = requirement.amount,
								m_recover = requirement.recover
							};
						}
						Debug.LogWarning((object)(Plugin.Info.Metadata.GUID + ": required build piece item '" + requirement.itemName + "' does not exist."));
						return (Requirement)null;
					})
					where requirement != null
					select requirement).ToArray();
			}

			public static Requirement[] ToPieceReqs(ObjectDB objectDb, string serialized)
			{
				return ToPieceReqs(objectDb, serialized.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(delegate(string entry)
				{
					string[] array = entry.Split(new char[1] { ':' });
					int result;
					bool result2 = default(bool);
					return new Requirement
					{
						itemName = array[0],
						amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
						recover = (array.Length <= 2 || !bool.TryParse(array[2], out result2) || result2)
					};
				}));
			}
		}

		private static readonly Harmony Harmony;

		internal static readonly List<BuildPiece> registeredPieces;

		private static readonly Dictionary<BuildPiece, PieceConfig> pieceConfigs;

		private static bool configBindingsInitialized;

		[Description("Disables generation of configs for registered pieces.")]
		public static bool ConfigurationEnabled;

		public readonly GameObject Prefab;

		public readonly RequiredResourcesList RequiredItems = new RequiredResourcesList();

		public readonly BuildingPieceCategory Category = new BuildingPieceCategory();

		public readonly PieceTool Tool = new PieceTool();

		public CraftingStationList Crafting = new CraftingStationList();

		public ConfigEntryBase? RecipeIsActive;

		private static BaseUnityPlugin? _plugin;

		private static BaseUnityPlugin Plugin
		{
			get
			{
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				object obj = _plugin;
				if (obj == null)
				{
					BaseUnityPlugin val = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)Assembly.GetExecutingAssembly().DefinedTypes.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
					_plugin = val;
					obj = (object)val;
				}
				return (BaseUnityPlugin)obj;
			}
		}

		static BuildPiece()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			Harmony = new Harmony("kg.ValheimEnchantmentSystem.ThinPieceManager");
			registeredPieces = new List<BuildPiece>();
			pieceConfigs = new Dictionary<BuildPiece, PieceConfig>();
			ConfigurationEnabled = true;
			Harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(BuildPiece), "Patch_FejdStartup", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(BuildPiece), "Patch_ObjectDBInit", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ObjectDB), "CopyOtherDB", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(BuildPiece), "Patch_ObjectDBInit", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZNetScene), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(BuildPiece), "Patch_ZNetSceneAwake", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public BuildPiece(AssetBundle bundle, string prefabName)
		{
			Prefab = bundle.LoadAsset<GameObject>(prefabName) ?? throw new InvalidOperationException("Could not load piece prefab '" + prefabName + "' from asset bundle.");
			((Object)Prefab).name = prefabName;
			ApplyStaticDefaults(this);
			registeredPieces.Add(this);
		}

		private static void Patch_FejdStartup()
		{
			EnsureConfigBindings();
		}

		internal static void Patch_ObjectDBInit(ObjectDB __instance)
		{
			EnsureConfigBindings();
			if ((Object)(object)__instance.GetItemPrefab("Hammer") == (Object)null)
			{
				return;
			}
			foreach (BuildPiece registeredPiece in registeredPieces)
			{
				ApplyRuntimeConfiguration(registeredPiece, __instance, ZNetScene.instance);
			}
		}

		internal static void Patch_ZNetSceneAwake(ZNetScene __instance)
		{
			foreach (BuildPiece registeredPiece in registeredPieces)
			{
				if (!__instance.m_prefabs.Contains(registeredPiece.Prefab))
				{
					__instance.m_prefabs.Add(registeredPiece.Prefab);
				}
				int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)registeredPiece.Prefab).name);
				if (!__instance.m_namedPrefabs.ContainsKey(stableHashCode))
				{
					__instance.m_namedPrefabs.Add(stableHashCode, registeredPiece.Prefab);
				}
			}
		}

		internal static void EnsureConfigBindings()
		{
			if (configBindingsInitialized)
			{
				return;
			}
			foreach (BuildPiece piece in registeredPieces)
			{
				ApplyStaticDefaults(piece);
				if (ConfigurationEnabled)
				{
					string token = piece.Prefab.GetComponent<Piece>()?.m_name ?? ((Object)piece.Prefab).name;
					string localizedDisplayName = GetLocalizedDisplayName(token, ((Object)piece.Prefab).name);
					string text = SharedLocalizationCache.LocalizeForConfig(token);
					string text2 = (string.IsNullOrWhiteSpace(text) ? localizedDisplayName : text);
					PieceConfig pieceConfig = (pieceConfigs[piece] = new PieceConfig());
					PieceConfig pieceConfig3 = pieceConfig;
					pieceConfig3.craft = Config(text2, "Crafting Costs", SerializedRequirements.Serialize(piece.RequiredItems.Requirements), ConfigurationManagerDisplay.Description("Item costs to craft " + localizedDisplayName + ".", "1 - General", 900, text2 + " - Crafting Costs"));
					pieceConfig3.craft.SettingChanged += delegate
					{
						ReapplyRuntimeConfiguration(piece);
					};
				}
			}
			configBindingsInitialized = true;
		}

		private static void ReapplyRuntimeConfiguration(BuildPiece piece)
		{
			if (!((Object)(object)ObjectDB.instance == (Object)null))
			{
				ApplyRuntimeConfiguration(piece, ObjectDB.instance, ZNetScene.instance);
			}
		}

		private static void ApplyStaticDefaults(BuildPiece piece)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Piece component = piece.Prefab.GetComponent<Piece>();
			if (!((Object)(object)component == (Object)null))
			{
				component.m_category = (PieceCategory)((piece.Category.Category == BuildPieceCategory.Custom) ? BuildPieceCategory.Crafting : piece.Category.Category);
			}
		}

		private static void ApplyRuntimeConfiguration(BuildPiece piece, ObjectDB objectDb, ZNetScene? scene)
		{
			Piece component = piece.Prefab.GetComponent<Piece>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			if (pieceConfigs.TryGetValue(piece, out PieceConfig value))
			{
				ConfigEntry<string> craft = value.craft;
				if (craft != null)
				{
					component.m_resources = SerializedRequirements.ToPieceReqs(objectDb, craft.Value);
					goto IL_005a;
				}
			}
			component.m_resources = SerializedRequirements.ToPieceReqs(objectDb, piece.RequiredItems.Requirements);
			goto IL_005a;
			IL_005a:
			ApplyCraftingStation(piece, component, scene);
			ApplyToolRegistration(piece, objectDb);
			ConfigEntryBase recipeIsActive = piece.RecipeIsActive;
			if (recipeIsActive != null)
			{
				component.m_enabled = Convert.ToInt32(recipeIsActive.BoxedValue) != 0;
			}
		}

		private static void ApplyCraftingStation(BuildPiece piece, Piece pieceComponent, ZNetScene? scene)
		{
			if (piece.Crafting.Stations.Count == 0 || (Object)(object)scene == (Object)null)
			{
				pieceComponent.m_craftingStation = null;
				return;
			}
			CraftingStationConfig craftingStationConfig = piece.Crafting.Stations.First();
			switch (craftingStationConfig.Table)
			{
			case CraftingTable.None:
				pieceComponent.m_craftingStation = null;
				break;
			case CraftingTable.Custom:
			{
				GameObject prefab2 = scene.GetPrefab(craftingStationConfig.custom);
				pieceComponent.m_craftingStation = ((prefab2 != null) ? prefab2.GetComponent<CraftingStation>() : null);
				break;
			}
			default:
			{
				GameObject prefab = scene.GetPrefab(GetInternalName(craftingStationConfig.Table));
				pieceComponent.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
				break;
			}
			}
		}

		private static void ApplyToolRegistration(BuildPiece piece, ObjectDB objectDb)
		{
			foreach (GameObject item in objectDb.m_items)
			{
				(item.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces)?.m_pieces.Remove(piece.Prefab);
			}
			IEnumerable<string> enumerable = piece.Tool.Tools.DefaultIfEmpty("Hammer");
			foreach (string item2 in enumerable)
			{
				GameObject itemPrefab = objectDb.GetItemPrefab(item2);
				if (Object.op_Implicit((Object)(object)itemPrefab))
				{
					PieceTable val = itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces;
					if ((Object)(object)val != (Object)null && !val.m_pieces.Contains(piece.Prefab))
					{
						val.m_pieces.Add(piece.Prefab);
					}
				}
			}
		}

		private static string GetLocalizedDisplayName(string? token, string fallback)
		{
			if (string.IsNullOrWhiteSpace(token) || Localization.instance == null)
			{
				return fallback;
			}
			string text = Localization.instance.Localize(token).Trim();
			if (!string.IsNullOrWhiteSpace(text) && !string.Equals(text, token, StringComparison.Ordinal))
			{
				return text;
			}
			return fallback;
		}

		private static string GetInternalName(CraftingTable value)
		{
			return ((InternalName)typeof(CraftingTable).GetMember(value.ToString())[0].GetCustomAttributes(typeof(InternalName), inherit: false).First()).internalName;
		}

		private static ConfigEntry<T> Config<T>(string group, string name, T value, ConfigDescription description)
		{
			return ValheimEnchantmentSystem.config(group, name, value, description);
		}
	}
}
namespace SkillManager
{
	[PublicAPI]
	public class Skill
	{
		private readonly struct SavedSkillState
		{
			public readonly float Level;

			public readonly float Accumulator;

			public SavedSkillState(float level, float accumulator)
			{
				Level = level;
				Accumulator = accumulator;
			}
		}

		public static class LocalizationCache
		{
			internal static void LocalizationPostfix(Localization __instance, string language)
			{
				SharedLocalizationCache.Track(__instance, language);
			}

			public static Localization ForLanguage(string? language = null)
			{
				return SharedLocalizationCache.ForLanguage(language);
			}

			public static string LocalizeForConfig(string token, string preferredLanguage = "English")
			{
				return SharedLocalizationCache.LocalizeForConfig(token, preferredLanguage);
			}
		}

		[PublicAPI]
		public class LocalizeKey
		{
			private static readonly List<LocalizeKey> keys = new List<LocalizeKey>();

			public readonly string Key;

			public readonly Dictionary<string, string> Localizations = new Dictionary<string, string>();

			public LocalizeKey(string key)
			{
				Key = key.Replace("$", "");
				keys.Add(this);
			}

			public void Alias(string alias)
			{
				Localizations.Clear();
				if (!alias.Contains("$"))
				{
					alias = "$" + alias;
				}
				Localizations["alias"] = alias;
				if (Localization.m_instance != null)
				{
					Localization.instance.AddWord(Key, Localization.instance.Localize(alias));
				}
			}

			public LocalizeKey English(string key)
			{
				return addForLang("English", key);
			}

			public LocalizeKey Swedish(string key)
			{
				return addForLang("Swedish", key);
			}

			public LocalizeKey French(string key)
			{
				return addForLang("French", key);
			}

			public LocalizeKey Italian(string key)
			{
				return addForLang("Italian", key);
			}

			public LocalizeKey German(string key)
			{
				return addForLang("German", key);
			}

			public LocalizeKey Spanish(string key)
			{
				return addForLang("Spanish", key);
			}

			public LocalizeKey Russian(string key)
			{
				return addForLang("Russian", key);
			}

			public LocalizeKey Romanian(string key)
			{
				return addForLang("Romanian", key);
			}

			public LocalizeKey Bulgarian(string key)
			{
				return addForLang("Bulgarian", key);
			}

			public LocalizeKey Macedonian(string key)
			{
				return addForLang("Macedonian", key);
			}

			public LocalizeKey Finnish(string key)
			{
				return addForLang("Finnish", key);
			}

			public LocalizeKey Danish(string key)
			{
				return addForLang("Danish", key);
			}

			public LocalizeKey Norwegian(string key)
			{
				return addForLang("Norwegian", key);
			}

			public LocalizeKey Icelandic(string key)
			{
				return addForLang("Icelandic", key);
			}

			public LocalizeKey Turkish(string key)
			{
				return addForLang("Turkish", key);
			}

			public LocalizeKey Lithuanian(string key)
			{
				return addForLang("Lithuanian", key);
			}

			public LocalizeKey Czech(string key)
			{
				return addForLang("Czech", key);
			}

			public LocalizeKey Hungarian(string key)
			{
				return addForLang("Hungarian", key);
			}

			public LocalizeKey Slovak(string key)
			{
				return addForLang("Slovak", key);
			}

			public LocalizeKey Polish(string key)
			{
				return addForLang("Polish", key);
			}

			public LocalizeKey Dutch(string key)
			{
				return addForLang("Dutch", key);
			}

			public LocalizeKey Portuguese_European(string key)
			{
				return addForLang("Portuguese_European", key);
			}

			public LocalizeKey Portuguese_Brazilian(string key)
			{
				return addForLang("Portuguese_Brazilian", key);
			}

			public LocalizeKey Chinese(string key)
			{
				return addForLang("Chinese", key);
			}

			public LocalizeKey Japanese(string key)
			{
				return addForLang("Japanese", key);
			}

			public LocalizeKey Korean(string key)
			{
				return addForLang("Korean", key);
			}

			public LocalizeKey Hindi(string key)
			{
				return addForLang("Hindi", key);
			}

			public LocalizeKey Thai(string key)
			{
				return addForLang("Thai", key);
			}

			public LocalizeKey Abenaki(string key)
			{
				return addForLang("Abenaki", key);
			}

			public LocalizeKey Croatian(string key)
			{
				return addForLang("Croatian", key);
			}

			public LocalizeKey Georgian(string key)
			{
				return addForLang("Georgian", key);
			}

			public LocalizeKey Greek(string key)
			{
				return addForLang("Greek", key);
			}

			public LocalizeKey Serbian(string key)
			{
				return addForLang("Serbian", key);
			}

			public LocalizeKey Ukrainian(string key)
			{
				return addForLang("Ukrainian", key);
			}

			private LocalizeKey addForLang(string lang, string value)
			{
				Localizations[lang] = value;
				if (Localization.m_instance != null)
				{
					if (Localization.instance.GetSelectedLanguage() == lang)
					{
						Localization.instance.AddWord(Key, value);
					}
					else if (lang == "English" && !Localization.instance.m_translations.ContainsKey(Key))
					{
						Localization.instance.AddWord(Key, value);
					}
				}
				return this;
			}

			[HarmonyPriority(300)]
			internal static void AddLocalizedKeys(Localization __instance, string language)
			{
				foreach (LocalizeKey key in keys)
				{
					string value2;
					if (key.Localizations.TryGetValue(language, out string value) || key.Localizations.TryGetValue("English", out value))
					{
						__instance.AddWord(key.Key, value);
					}
					else if (key.Localizations.TryGetValue("alias", out value2))
					{
						__instance.AddWord(key.Key, Localization.instance.Localize(value2));
					}
				}
			}
		}

		private static readonly Dictionary<SkillType, Skill> skills;

		internal static readonly Dictionary<string, Skill> skillByName;

		private readonly string skillName;

		private readonly string internalSkillName;

		private readonly SkillDef skillDef;

		public readonly LocalizeKey Name;

		public readonly LocalizeKey Description;

		private float skillEffectFactor = 1f;

		private int skillLoss = 5;

		public bool Configurable;

		private static bool configBindingsInitialized;

		private const string RequiredExperienceFormulaDescription = "Required EXP per level follows: ((current level + 1)^1.5) / 2 + 0.5.";

		private static bool InitializedTerminal;

		private static BaseUnityPlugin? _plugin;

		public float SkillGainFactor
		{
			get
			{
				return skillDef.m_increseStep;
			}
			set
			{
				skillDef.m_increseStep = value;
				this.SkillGainFactorChanged?.Invoke(value);
			}
		}

		public float SkillEffectFactor
		{
			get
			{
				return skillEffectFactor;
			}
			set
			{
				skillEffectFactor = value;
				this.SkillEffectFactorChanged?.Invoke(value);
			}
		}

		public int SkillLoss
		{
			get
			{
				return skillLoss;
			}
			set
			{
				skillLoss = value;
				this.SkillLossChanged?.Invoke(value);
			}
		}

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				object obj = _plugin;
				if (obj == null)
				{
					BaseUnityPlugin val = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)Assembly.GetExecutingAssembly().DefinedTypes.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
					_plugin = val;
					obj = (object)val;
				}
				return (BaseUnityPlugin)obj;
			}
		}

		public event Action<float>? SkillGainFactorChanged;

		public event Action<float>? SkillEffectFactorChanged;

		public event Action<float>? SkillLossChanged;

		public Skill(string englishName, string icon)
			: this(englishName, loadSprite(icon, 64, 64))
		{
		}

		public unsafe Skill(string englishName, Sprite icon)
		{
			//IL_0019: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			SkillType val = fromName(englishName);
			string text = new Regex("[^a-zA-Z]").Replace(englishName, "_");
			skills[val] = this;
			skillByName[englishName] = this;
			skillDef = new SkillDef
			{
				m_description = "$skilldesc_" + text,
				m_icon = icon,
				m_increseStep = 1f,
				m_skill = val
			};
			internalSkillName = text;
			skillName = englishName;
			Name = new LocalizeKey("skill_" + ((object)(*(SkillType*)(&val))/*cast due to .constrained prefix*/).ToString()).English(englishName);
			Description = new LocalizeKey("skilldesc_" + text);
		}

		public static SkillType fromName(string englishName)
		{
			return (SkillType)Math.Abs(StringExtensionMethods.GetStableHashCode(englishName));
		}

		static Skill()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_016a: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Expected O, but got Unknown
			//IL_02b0: Expected O, but got Unknown
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Expected O, but got Unknown
			//IL_0306: Expected O, but got Unknown
			skills = new Dictionary<SkillType, Skill>();
			skillByName = new Dictionary<string, Skill>();
			InitializedTerminal = false;
			Harmony val = new Harmony("org.bepinex.helpers.skillmanager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_FejdStartup", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ZNet), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_ZNet_Awake", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_Awake", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "GetSkillDef", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_GetSkillDef", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "Load", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_Load_Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_Load_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "IsSkillValid", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_IsSkillValid", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "CheatRaiseSkill", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_CheatRaiseskill", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "CheatResetSkill", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_CheatResetSkill", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(LocalizeKey), "AddLocalizedKeys", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Terminal), "InitTerminal", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Terminal_InitTerminal_Prefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Terminal_InitTerminal", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Skills), "OnDeath", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_OnDeath_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Skill), "Patch_Skills_OnDeath_Finalizer", (Type[])null, (Type[])null)), (HarmonyMethod)null);
		}

		private static bool IsEnchantmentSkill(Skill skill)
		{
			return string.Equals(skill.internalSkillName, "kg_Enchantment", StringComparison.Ordinal);
		}

		private static string GetConfigGroup(Skill skill)
		{
			if (!IsEnchantmentSkill(skill))
			{
				return skill.internalSkillName;
			}
			return "Enchantment";
		}

		private static string GetConfigCategory(Skill skill, string localizedName)
		{
			if (!IsEnchantmentSkill(skill))
			{
				return localizedName;
			}
			return "3 - Skill";
		}

		private static string GetSkillKeyDescription(string skillKey)
		{
			return "Skill key: " + skillKey + ".";
		}

		private static string GetLocalizedDisplayName(string token, string fallback)
		{
			if (Localization.instance == null)
			{
				return fallback;
			}
			string text = Localization.instance.Localize(token).Trim();
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return fallback;
		}

		private static void Patch_FejdStartup()
		{
			EnsureConfigBindings();
		}

		private static void Patch_ZNet_Awake()
		{
			EnsureConfigBindings();
		}

		private static void Patch_Skills_Awake(Skills __instance)
		{
			EnsureSkillDefinitions(__instance);
		}

		private static void EnsureSkillDefinitions(Skills? skillComponent)
		{
			if ((Object)(object)skillComponent == (Object)null)
			{
				return;
			}
			foreach (Skill customSkill in skills.Values)
			{
				if (!skillComponent.m_skills.Any((SkillDef skillDef) => skillDef?.m_skill == (SkillType?)customSkill.skillDef.m_skill))
				{
					skillComponent.m_skills.Add(customSkill.skillDef);
				}
			}
		}

		private static Dictionary<SkillType, SavedSkillState>? CaptureCustomSkillStates(ZPackage? pkg)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (pkg == null || skills.Count == 0)
			{
				return null;
			}
			try
			{
				ZPackage val = new ZPackage(pkg.GetArray());
				val.SetPos(pkg.GetPos());
				int num = val.ReadInt();
				int num2 = val.ReadInt();
				Dictionary<SkillType, SavedSkillState> dictionary = null;
				for (int i = 0; i < num2; i++)
				{
					SkillType key = (SkillType)val.ReadInt();
					float level = val.ReadSingle();
					float accumulator = ((num >= 2) ? val.ReadSingle() : 0f);
					if (skills.ContainsKey(key))
					{
						if (dictionary == null)
						{
							dictionary = new Dictionary<SkillType, SavedSkillState>();
						}
						dictionary[key] = new SavedSkillState(level, accumulator);
					}
				}
				return dictionary;
			}
			catch
			{
				return null;
			}
		}

		private static void RestoreCustomSkillStates(Skills? skillComponent, Dictionary<SkillType, SavedSkillState>? capturedStates)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)skillComponent == (Object)null || capturedStates == null || capturedStates.Count == 0)
			{
				return;
			}
			EnsureSkillDefinitions(skillComponent);
			foreach (KeyValuePair<SkillType, SavedSkillState> capturedState in capturedStates)
			{
				Skill skill = skillComponent.GetSkill(capturedState.Key);
				skill.m_level = capturedState.Value.Level;
				skill.m_accumulator = capturedState.Value.Accumulator;
			}
		}

		private static void Patch_Skills_Load_Prefix(Skills __instance, ZPackage pkg, out Dictionary<SkillType, SavedSkillState>? __state)
		{
			EnsureSkillDefinitions(__instance);
			__state = CaptureCustomSkillStates(pkg);
		}

		private static void Patch_Skills_Load_Postfix(Skills __instance, Dictionary<SkillType, SavedSkillState>? __state)
		{
			RestoreCustomSkillStates(__instance, __state);
		}

		private static void EnsureConfigBindings()
		{
			if (configBindingsInitialized)
			{
				return;
			}
			foreach (Skill skill in skills.Values)
			{
				if (!skill.Configurable)
				{
					continue;
				}
				string key = skill.Name.Key;
				string fallback = new Regex("['[\"\\]]").Replace(LocalizationCache.LocalizeForConfig(key), "").Trim();
				string localizedDisplayName = GetLocalizedDisplayName(key, fallback);
				string configGroup = GetConfigGroup(skill);
				string configCategory = GetConfigCategory(skill, localizedDisplayName);
				ConfigEntry<float> skillGain = config(configGroup, "Skill gain factor", skill.SkillGainFactor, ConfigurationManagerDisplay.Description("The rate at which you gain experience for the skill. " + GetSkillKeyDescription(key) + " Required EXP per level follows: ((current level + 1)^1.5) / 2 + 0.5.", configCategory, IsEnchantmentSkill(skill) ? new int?(1000) : ((int?)null), IsEnchantmentSkill(skill) ? "Skill Gain Factor" : null, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.01f, 5f)));
				skill.SkillGainFactor = skillGain.Value;
				skillGain.SettingChanged += delegate
				{
					skill.SkillGainFactor = skillGain.Value;
				};
				if (!IsEnchantmentSkill(skill))
				{
					ConfigEntry<float> skillEffect = config(configGroup, "Skill effect factor", skill.SkillEffectFactor, ConfigurationManagerDisplay.Description("The power of the skill, based on the default power.", configCategory, null, null, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.01f, 5f)));
					skill.SkillEffectFactor = skillEffect.Value;
					skillEffect.SettingChanged += delegate
					{
						skill.SkillEffectFactor = skillEffect.Value;
					};
				}
				ConfigEntry<int> skillLoss = config(configGroup, "Skill loss", skill.skillLoss, ConfigurationManagerDisplay.Description("How much experience to lose on death. " + GetSkillKeyDescription(key) + " Required EXP per level follows: ((current level + 1)^1.5) / 2 + 0.5.", configCategory, IsEnchantmentSkill(skill) ? new int?(990) : ((int?)null), IsEnchantmentSkill(skill) ? "Skill Loss" : null, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(0, 100)));
				skill.skillLoss = skillLoss.Value;
				skillLoss.SettingChanged += delegate
				{
					skill.skillLoss = skillLoss.Value;
				};
			}
			configBindingsInitialized = true;
		}

		private static void Patch_Skills_GetSkillDef(ref SkillDef? __result, List<SkillDef> ___m_skills, SkillType type)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (__result == null)
			{
				SkillDef val = GetSkillDef(type);
				if (val != null)
				{
					___m_skills.Add(val);
					__result = val;
				}
			}
		}

		private unsafe static bool Patch_Skills_CheatRaiseskill(Skills __instance, string name, float value, Player ___m_player)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			foreach (SkillType key in skills.Keys)
			{
				Skill skill = skills[key];
				if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase))
				{
					Skill skill2 = __instance.GetSkill(key);
					skill2.m_level += value;
					skill2.m_level = Mathf.Clamp(skill2.m_level, 0f, 100f);
					((Character)___m_player).Message((MessageType)1, "Skill increased " + Localization.instance.Localize("$skill_" + ((object)(*(SkillType*)(&key))/*cast due to .constrained prefix*/).ToString()) + ": " + (int)skill2.m_level, 0, skill2.m_info.m_icon);
					Console.instance.Print("Skill " + skill.internalSkillName + " = " + skill2.m_level);
					return false;
				}
			}
			return true;
		}

		private static bool Patch_Skills_CheatResetSkill(Skills __instance, string name)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			foreach (SkillType key in skills.Keys)
			{
				Skill skill = skills[key];
				if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase))
				{
					__instance.ResetSkill(key);
					Console.instance.Print("Skill " + skill.internalSkillName + " reset");
					return false;
				}
			}
			return true;
		}

		private static void Patch_Skills_OnDeath_Prefix(Skills __instance, ref Dictionary<SkillType, Skill>? __state)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null)
			{
				__state = new Dictionary<SkillType, Skill>();
			}
			foreach (KeyValuePair<SkillType, Skill> skill in skills)
			{
				if (__instance.m_skillData.TryGetValue(skill.Key, out var value))
				{
					__state[skill.Key] = value;
					if (skill.Value.skillLoss > 0)
					{
						Skill obj = value;
						obj.m_level -= value.m_level * (float)skill.Value.SkillLoss / 100f;
						value.m_accumulator = 0f;
					}
					__instance.m_skillData.Remove(skill.Key);
				}
			}
		}

		private static void Patch_Skills_OnDeath_Finalizer(Skills __instance, ref Dictionary<SkillType, Skill>? __state)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null)
			{
				return;
			}
			foreach (KeyValuePair<SkillType, Skill> item in __state)
			{
				__instance.m_skillData[item.Key] = item.Value;
			}
			__state = null;
		}

		private static void Patch_Terminal_InitTerminal_Prefix()
		{
			InitializedTerminal = Terminal.m_terminalInitialized;
		}

		private static void Patch_Terminal_InitTerminal()
		{
			if (!InitializedTerminal)
			{
				AddSkill(Terminal.commands["raiseskill"]);
				AddSkill(Terminal.commands["resetskill"]);
			}
			static void AddSkill(ConsoleCommand command)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				ConsoleOptionsFetcher fetcher = command.m_tabOptionsFetcher;
				command.m_tabOptionsFetcher = (ConsoleOptionsFetcher)delegate
				{
					List<string> list = fetcher.Invoke();
					list.AddRange(skills.Values.Select((Skill skill) => skill.internalSkillName));
					return list;
				};
			}
		}

		private static SkillDef? GetSkillDef(SkillType skillType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!skills.ContainsKey(skillType))
			{
				return null;
			}
			Skill skill = skills[skillType];
			return skill.skillDef;
		}

		private static void Patch_Skills_IsSkillValid(SkillType type, ref bool __result)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!__result && skills.ContainsKey(type))
			{
				__result = true;
			}
		}

		private static byte[] ReadEmbeddedFileBytes(string name)
		{
			using MemoryStream memoryStream = new MemoryStream();
			Assembly.GetExecutingAssembly().GetManifestResourceStream(Assembly.GetExecutingAssembly().GetName().Name + "." + name).CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static Texture2D loadTexture(string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Texture2D val = new Texture2D(0, 0);
			ImageConversion.LoadImage(val, ReadEmbeddedFileBytes("icons." + name));
			return val;
		}

		private static Sprite loadSprite(string name, int width, int height)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			return Sprite.Create(loadTexture(name), new Rect(0f, 0f, (float)width, (float)height), Vector2.zero);
		}

		private static ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description)
		{
			return ValheimEnchantmentSystem.config(group, name, value, description);
		}

		private static ConfigEntry<T> config<T>(string group, string name, T value, string description)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}
	}
	public static class SkillManagerVersion
	{
		public const string Version = "1.7.0";
	}
	[PublicAPI]
	public static class SkillExtensions
	{
		public static float GetSkillFactor(this Character character, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return character.GetSkillFactor(Skill.fromName(name)) * Skill.skillByName[name].SkillEffectFactor;
		}

		public static float GetSkillFactor(this Skills skills, string name)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return skills.GetSkillFactor(Skill.fromName(name)) * Skill.skillByName[name].SkillEffectFactor;
		}

		public static void RaiseSkill(this Character character, string name, float value = 1f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			character.RaiseSkill(Skill.fromName(name), value);
		}

		public static void RaiseSkill(this Skills skill, string name, float value = 1f)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			skill.RaiseSkill(Skill.fromName(name), value);
		}

		public static void LowerSkill(this Character character, string name, float factor = 1f)
		{
			character.GetSkills().LowerSkill(name, factor);
		}

		public static void LowerSkill(this Skills skills, string name, float factor)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (factor > 0f && skills.m_skillData.TryGetValue(Skill.fromName(name), out var value))
			{
				Skill obj = value;
				obj.m_level -= value.m_level * factor;
				value.m_accumulator = 0f;
			}
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	public static class SharedLocalizationCache
	{
		private static readonly Dictionary<string, WeakReference<Localization>> Localizations = new Dictionary<string, WeakReference<Localization>>();

		private static readonly object CacheLock = new object();

		public static void Track(Localization localization, string language)
		{
			lock (CacheLock)
			{
				Localization target;
				string key = Localizations.FirstOrDefault<KeyValuePair<string, WeakReference<Localization>>>((KeyValuePair<string, WeakReference<Localization>> pair) => pair.Value.TryGetTarget(out target) && target == localization).Key;
				if (key != null)
				{
					Localizations.Remove(key);
				}
				Localizations[language] = new WeakReference<Localization>(localization);
			}
		}

		public static Localization ForLanguage(string? language = null)
		{
			bool flag = language != null;
			string text = language ?? PlayerPrefs.GetString("language", "English");
			lock (CacheLock)
			{
				if (Localizations.TryGetValue(text, out WeakReference<Localization> value) && value.TryGetTarget(out var target))
				{
					return target;
				}
			}
			if (Localization.m_instance != null)
			{
				Localization instance = Localization.instance;
				string selectedLanguage = instance.GetSelectedLanguage();
				Track(instance, selectedLanguage);
				if (!flag || string.Equals(selectedLanguage, text, StringComparison.OrdinalIgnoreCase))
				{
					return instance;
				}
				throw new InvalidOperationException("Requested localization '" + text + "' is not cached. Active language is '" + selectedLanguage + "'.");
			}
			throw new InvalidOperationException("No localization instance is available for language '" + text + "'.");
		}

		public static string LocalizeForConfig(string token, string preferredLanguage = "English")
		{
			if (string.IsNullOrWhiteSpace(token))
			{
				return string.Empty;
			}
			string text = (token.StartsWith("$", StringComparison.Ordinal) ? token : ("$" + token));
			string key = text.TrimStart(new char[1] { '$' });
			if (Localizer.TryGetConfigText(preferredLanguage, key, out string text2))
			{
				return text2;
			}
			try
			{
				string text3 = ForLanguage(preferredLanguage).Localize(text).Trim();
				if (!string.IsNullOrWhiteSpace(text3) && !string.Equals(text3, text, StringComparison.Ordinal))
				{
					return text3;
				}
			}
			catch
			{
			}
			string text4 = text.TrimStart(new char[1] { '$' }).Replace('_', ' ').Trim();
			if (text4.Length != 0)
			{
				return text4;
			}
			return text;
		}
	}
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> LoadedTexts;

		private static readonly object LoadedTextsLock;

		private static readonly ConditionalWeakTable<Localization, string> LocalizationLanguage;

		private static readonly List<WeakReference<Localization>> LocalizationObjects;

		private static readonly List<string> FileExtensions;

		private static BaseUnityPlugin? _plugin;

		private static readonly object ExternalLocalizationFilesLock;

		private static Dictionary<string, string>? _externalLocalizationFiles;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		public static event Action? OnLocalizationComplete;

		private static string? TryParseLanguageFromExternalFile(string filePath)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
			string text = plugin.Info.Metadata.GUID + ".";
			if (!fileNameWithoutExtension.StartsWith(text, StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			string text2 = fileNameWithoutExtension.Substring(text.Length);
			if (!string.IsNullOrWhiteSpace(text2))
			{
				return text2;
			}
			return null;
		}

		private static bool HasSupportedExtension(string filePath)
		{
			return FileExtensions.Contains<string>(Path.GetExtension(filePath), StringComparer.OrdinalIgnoreCase);
		}

		private static Dictionary<string, string> BuildExternalLocalizationFiles()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string directoryName = Path.GetDirectoryName(Paths.PluginPath);
			foreach (string item in Directory.GetFiles(directoryName, plugin.Info.Metadata.GUID + ".*", SearchOption.AllDirectories).Where(HasSupportedExtension))
			{
				string text = TryParseLanguageFromExternalFile(item);
				if (text != null)
				{
					if (dictionary.ContainsKey(text))
					{
						Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.GUID + ". The duplicate file found at " + item + " will be skipped."));
					}
					else
					{
						dictionary[text] = item;
					}
				}
			}
			return dictionary;
		}

		private static Dictionary<string, string> GetExternalLocalizationFiles()
		{
			lock (ExternalLocalizationFilesLock)
			{
				if (_externalLocalizationFiles == null)
				{
					_externalLocalizationFiles = BuildExternalLocalizationFiles();
				}
				return _externalLocalizationFiles;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			if (!LocalizationLanguage.TryGetValue(localization, out string value) || !LoadedTexts.TryGetValue(value, out Dictionary<string, string> value2) || !value2.TryGetValue(key, out var value3))
			{
				return;
			}
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value4))
			{
				value3 = value4.Aggregate(value3, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, value3);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (Localization.instance != null && LoadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				if (Localization.instance != null)
				{
					PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
					UpdatePlaceholderText(Localization.instance, key);
				}
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in LocalizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					string orCreateValue = LocalizationLanguage.GetOrCreateValue(target);
					if (!LoadedTexts.TryGetValue(orCreateValue, out Dictionary<string, string> value))
					{
						value = new Dictionary<string, string>();
						LoadedTexts[orCreateValue] = value;
					}
					if (!target.m_translations.ContainsKey(key))
					{
						value[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				LocalizationObjects.Remove(item);
			}
		}

		public static bool TryGetConfigText(string language, string key, out string text)
		{
			text = string.Empty;
			if (string.IsNullOrWhiteSpace(language) || string.IsNullOrWhiteSpace(key))
			{
				return false;
			}
			Dictionary<string, string> dictionary = EnsureConfigTextsLoaded(language);
			if (dictionary == null || !dictionary.TryGetValue(key, out var value) || string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			text = value.Trim();
			return text.Length > 0;
		}

		public static void Load()
		{
			_ = plugin;
		}

		public static void LoadLocalizationLater(Localization __instance)
		{
			LoadLocalization(Localization.instance, __instance.GetSelectedLanguage());
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!LocalizationLanguage.Remove(__instance))
			{
				LocalizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			LocalizationLanguage.Add(__instance, language);
			SharedLocalizationCache.Track(__instance, language);
			Dictionary<string, string> externalLocalizationFiles = GetExternalLocalizationFiles();
			byte[] array = LoadTranslationFromAssembly("English");
			if (array == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array));
			if (dictionary == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text = null;
			if (language != "English")
			{
				if (externalLocalizationFiles.TryGetValue(language, out var value))
				{
					text = File.ReadAllText(value);
				}
				else
				{
					byte[] array2 = LoadTranslationFromAssembly(language);
					if (array2 != null)
					{
						text = Encoding.UTF8.GetString(array2);
					}
				}
			}
			if (text == null && externalLocalizationFiles.TryGetValue("English", out var value2))
			{
				text = File.ReadAllText(value2);
			}
			if (text != null)
			{
				foreach (KeyValuePair<string, string> item in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text) ?? new Dictionary<string, string>())
				{
					dictionary[item.Key] = item.Value;
				}
			}
			LoadedTexts[language] = dictionary;
			foreach (KeyValuePair<string, string> item2 in dictionary)
			{
				UpdatePlaceholderText(__instance, item2.Key);
			}
		}

		static Localizer()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			LoadedTexts = new Dictionary<string, Dictionary<string, string>>();
			LoadedTextsLock = new object();
			LocalizationLanguage = new ConditionalWeakTable<Localization, string>();
			LocalizationObjects = new List<WeakReference<Localization>>();
			FileExtensions = new List<string>(2) { ".json", ".yml" };
			ExternalLocalizationFilesLock = new object();
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			Assembly assembly = typeof(Localizer).Assembly;
			foreach (string fileExtension in FileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension, assembly);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		private static Dictionary<string, string>? EnsureConfigTextsLoaded(string language)
		{
			lock (LoadedTextsLock)
			{
				if (LoadedTexts.TryGetValue(language, out Dictionary<string, string> value))
				{
					return value;
				}
				Dictionary<string, string> externalLocalizationFiles = GetExternalLocalizationFiles();
				string text = null;
				if (externalLocalizationFiles.TryGetValue(language, out var value2))
				{
					text = File.ReadAllText(value2);
				}
				else
				{
					byte[] array = LoadTranslationFromAssembly(language);
					if (array != null)
					{
						text = Encoding.UTF8.GetString(array);
					}
				}
				if (text == null)
				{
					return null;
				}
				Dictionary<string, string> dictionary = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text);
				if (dictionary == null)
				{
					return null;
				}
				LoadedTexts[language] = dictionary;
				return dictionary;
			}
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.2";
	}
}
namespace ItemDataManager
{
	[PublicAPI]
	public abstract class ItemData
	{
		internal static WeakReference<ItemInfo> constructingInfo = null;

		internal WeakReference<ItemInfo>? info;

		private static readonly FieldInfo parameterInfoClassImpl = AccessTools.DeclaredField(typeof(ParameterInfo), "ClassImpl");

		private static Dictionary<Type, Dictionary<string, FieldInfo>> serializedFields = new Dictionary<Type, Dictionary<string, FieldInfo>>();

		public string CustomDataKey { get; internal set; }

		protected virtual bool AllowStackingIdenticalValues { get; set; }

		public string Value
		{
			get
			{
				if (!Item.m_customData.TryGetValue(CustomDataKey, out var value))
				{
					return "";
				}
				return value;
			}
			set
			{
				Item.m_customData[CustomDataKey] = value;
			}
		}

		public string Key { get; internal set; }

		public bool IsCloned => Info.isCloned.Contains(CustomDataKey);

		public bool IsAlive
		{
			get
			{
				ItemInfo target;
				return (info ?? constructingInfo).TryGetTarget(out target);
			}
		}

		public ItemData Item => Info.ItemData;

		public ItemInfo Info
		{
			get
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				if (!(info ?? constructingInfo).TryGetTarget(out ItemInfo target))
				{
					return new ItemInfo(new ItemData());
				}
				return target;
			}
		}

		public virtual void FirstLoad()
		{
		}

		public virtual void Load()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			Dictionary<string, FieldInfo> dictionary = fetchSerializedFields();
			if (dictionary == null || dictionary.Count <= 0 || Value == "")
			{
				return;
			}
			List<object> list = new List<object>();
			string[] array = Value.Split(new char[1] { '|' });
			foreach (string text in array)
			{
				string[] array2 = text.Split(new char[1] { ':' });
				if (array2.Length == 2 && dictionary.TryGetValue(array2[0], out var value))
				{
					ZPackage val = new ZPackage(array2[1]);
					ParameterInfo parameterInfo = (ParameterInfo)FormatterServices.GetUninitializedObject(typeof(ParameterInfo));
					parameterInfoClassImpl.SetValue(parameterInfo, value.FieldType);
					list.Clear();
					ZRpc.Deserialize(new ParameterInfo[2] { null, parameterInfo }, val, ref list);
					if (list.Count > 0)
					{
						value.SetValue(this, list[0]);
					}
				}
			}
		}

		public virtual void Save()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			Dictionary<string, FieldInfo> dictionary = fetchSerializedFields();
			if (dictionary == null || dictionary.Count <= 0)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (FieldInfo value in dictionary.Values)
			{
				ZPackage val = new ZPackage();
				ZRpc.Serialize(new object[1] { value.GetValue(this) }, ref val);
				stringBuilder.Append(value.Name);
				stringBuilder.Append(':');
				stringBuilder.Append(val.GetBase64());
				stringBuilder.Append('|');
			}
			int length = stringBuilder.Length - 1;
			stringBuilder.Length = length;
			Value = stringBuilder.ToString();
		}

		public virtual void Unload()
		{
		}

		public virtual void Upgraded()
		{
		}

		public virtual string? TryStack(ItemData? data)
		{
			if (!AllowStackingIdenticalValues || !(data?.Value == Value))
			{
				return null;
			}
			return Value;
		}

		private Dictionary<string, FieldInfo> fetchSerializedFields()
		{
			Type type = GetType();
			if (serializedFields.TryGetValue(type, out Dictionary<string, FieldInfo> value))
			{
				return value;
			}
			return serializedFields[type] = (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where f.GetCustomAttributes(typeof(SerializeField), inherit: true).Length != 0
				select f).ToDictionary((FieldInfo f) => f.Name, (FieldInfo f) => f);
		}
	}
	public sealed class StringItemData : ItemData
	{
	}
	[PublicAPI]
	public class ItemInfo : IEnumerable<ItemData>, IEnumerable
	{
		public static HashSet<Type> ForceLoadTypes;

		internal static string? _modGuid;

		private static Dictionary<Type, HashSet<Type>> typeInheritorsCache;

		private static HashSet<string> knownTypes;

		private Dictionary<string, ItemData> data = new Dictionary<string, ItemData>();

		private WeakReference<ItemInfo>? selfReference;

		internal HashSet<string> isCloned = new HashSet<string>();

		private static ItemData? awakeningItem;

		private static Assembly primaryAssembly;

		private static Dictionary<Assembly, string> assemblyNameCache;

		private static Dictionary<Type, string> classKeyCache;

		private HashSet<string> fetchedClassKeys = new HashSet<string>();

		private static MethodInfo removeMethod;

		private static ItemData? checkingForStackableItemData;

		private static Dictionary<string, string>? newValuesOnStackable;

		private static ItemData? currentlyUpgradingItem;

		internal static string modGuid => _modGuid ?? (_modGuid = ((Func<string>)delegate
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			IEnumerable<TypeInfo> source;
			try
			{
				source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
			}
			catch (ReflectionTypeLoadException ex)
			{
				source = from t in ex.Types
					where t != null
					select t.GetTypeInfo();
			}
			BaseUnityPlugin val = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
			return val.Info.Metadata.GUID;
		})());

		public string Mod => modGuid;

		public ItemData ItemData { get; private set; }

		public string? this[string key]
		{
			get
			{
				return Get<StringItemData>(key)?.Value;
			}
			set
			{
				GetOrCreate<StringItemData>(key).Value = value ?? "";
			}
		}

		internal static void addTypeToInheritorsCache(Type type, string typeKey)
		{
			if (!knownTypes.Contains(typeKey))
			{
				knownTypes.Add(typeKey);
				Type type2 = type;
				while ((object)type2 != null)
				{
					AddInterfaces(type2);
					type2 = type2.BaseType;
				}
			}
			void AddInterfaces(Type baseType)
			{
				if (!typeInheritorsCache.TryGetValue(baseType, out HashSet<Type> value))
				{
					HashSet<Type> hashSet = (typeInheritorsCache[baseType] = new HashSet<Type>());
					value = hashSet;
				}
				value.Add(type);
				Type[] interfaces = baseType.GetInterfaces();
				foreach (Type baseType2 in interfaces)
				{
					AddInterfaces(baseType2);
				}
			}
		}

		private static string cachedAssemblyName(Assembly assembly)
		{
			if (assemblyNameCache.TryGetValue(assembly, out string value))
			{
				return value;
			}
			return assemblyNameCache[assembly] = assembly.GetName().Name;
		}

		internal static string classKey(Type type, string key)
		{
			if (!classKeyCache.TryGetValue(type, out string value))
			{
				value = type.FullName + ((type.Assembly != primaryAssembly) ? ("," + cachedAssemblyName(type.Assembly)) : "");
				addTypeToInheritorsCache(type, value);
			}
			if (key == "")
			{
				return value;
			}
			return value + "#" + key;
		}

		internal static string dataKey(string key)
		{
			return modGuid + "#" + key;
		}

		internal ItemInfo(ItemData itemData)
		{
			ItemData = itemData;
			string text = dataKey("");
			List<string> list = ItemData.m_customData.Keys.ToList();
			foreach (string item in list)
			{
				if (!item.StartsWith(text))
				{
					continue;
				}
				string text2 = item.Substring(text.Length);
				string[] array = text2.Split(new char[1] { '#' }, 2);
				if (!knownTypes.Contains(array[0]))
				{
					Type type = Type.GetType(array[0]);
					if ((object)type != null && typeof(ItemData).IsAssignableFrom(type))
					{
						addTypeToInheritorsCache(type, array[0]);
					}
				}
			}
		}

		public T GetOrCreate<T>(string key = "") where T : ItemData, new()
		{
			return Add<T>(key) ?? Get<T>(key);
		}

		public T? Add<T>(string key = "") where T : ItemData, new()
		{
			string text = classKey(typeof(T), key);
			if (fetchedClassKeys.Contains(text) && data.ContainsKey(text))
			{
				return null;
			}
			string text2 = dataKey(text);
			if (ItemData.m_customData.ContainsKey(text2) || (awakeningItem != ItemData && data.ContainsKey(text)))
			{
				return null;
			}
			ItemData.m_customData[text2] = "";
			ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<ItemInfo>(this));
			T val = new T
			{
				info = selfReference,
				Key = key,
				CustomDataKey = text2
			};
			data[text] = val;
			val.Value = "";
			val.FirstLoad();
			return val;
		}

		public T? Get<T>(string key = "") where T : class
		{
			if (!typeInheritorsCache.TryGetValue(typeof(T), out HashSet<Type> value))
			{
				if (!typeof(ItemData).IsAssignableFrom(typeof(T)) || typeof(T) == typeof(ItemData))
				{
					throw new Exception("Trying to get value from ItemDataManager for class not inheriting from ItemData");
				}
				return null;
			}
			foreach (Type item in value)
			{
				string text = classKey(item, key);
				if (data.TryGetValue(text, out ItemData value2))
				{
					return (T)(object)value2;
				}
				if (!fetchedClassKeys.Contains(text) && awakeningItem != ItemData)
				{
					string text2 = dataKey(text);
					fetchedClassKeys.Add(text);
					if (ItemData.m_customData.ContainsKey(text2))
					{
						return (T)(object)constructDataObj(text2, text);
					}
				}
			}
			return null;
		}

		public Dictionary<string, T> GetAll<T>() where T : ItemData
		{
			LoadAll();
			return data.Values.Where((ItemData o) => o is T).ToDictionary((ItemData o) => o.Key, (ItemData o) => (T)o);
		}

		public bool Remove(string key = "")
		{
			return Remove<StringItemData>(key);
		}

		public bool Remove<T>(string key = "") where T : ItemData
		{
			string key2 = classKey(typeof(T), key);
			string key3 = dataKey(key2);
			if (ItemData.m_customData.Remove(key3))
			{
				if (data.TryGetValue(key2, out ItemData value))
				{
					value.Unload();
					data.Remove(key2);
				}
				return true;
			}
			return false;
		}

		public bool Remove<T>(T itemData) where T : ItemData
		{
			if (typeof(T) == itemData.GetType())
			{
				return Remove<T>(itemData.Key);
			}
			return (bool)removeMethod.MakeGenericMethod(itemData.GetType()).Invoke(this, new object[1] { itemData.Key });
		}

		private ItemData? constructDataObj(string fullkey, string key)
		{
			string[] array = key.Split(new char[1] { '#' }, 2);
			Type type = Type.GetType(array[0]);
			if ((object)type == null || !typeof(ItemData).IsAssignableFrom(type))
			{
				return null;
			}
			ItemDataManager.ItemData.constructingInfo = selfReference ?? (selfReference = new WeakReference<ItemInfo>(this));
			ItemData itemData = (ItemData)Activator.CreateInstance(type);
			data[key] = itemData;
			itemData.info = selfReference;
			itemData.Key = ((array.Length > 1) ? array[1] : "");
			itemData.CustomDataKey = fullkey;
			itemData.Load();
			return itemData;
		}

		public void Save()
		{
			foreach (ItemData value in data.Values)
			{
				value.Save();
			}
		}

		public void LoadAll()
		{
			if (awakeningItem == ItemData)
			{
				return;
			}
			string text = dataKey("");
			List<string> list = ItemData.m_customData.Keys.ToList();
			foreach (string item in list)
			{
				if (item.StartsWith(text))
				{
					string key = item.Substring(text.Length);
					if (!data.ContainsKey(key))
					{
						constructDataObj(item, key);
					}
				}
			}
		}

		public IEnumerator<ItemData> GetEnumerator()
		{
			LoadAll();
			return data.Values.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		private static void SavePrefix(ItemData __instance)
		{
			SaveItem(__instance);
		}

		private static void SaveInventoryPrefix(Inventory __instance)
		{
			foreach (ItemData item in __instance.m_inventory)
			{
				SaveItem(item);
			}
		}

		private static void SaveItem(ItemData item)
		{
			if (ItemExtensions.itemInfo.TryGetValue(item, out ItemInfo value))
			{
				value.Save();
			}
		}

		public Dictionary<string, string>? IsStackableWithOtherInfo(ItemInfo? info)
		{
			LoadAll();
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			if (info != null)
			{
				info.LoadAll();
				HashSet<string> hashSet = new HashSet<string>(info.data.Keys.Intersect(data.Keys));
				foreach (string item in hashSet)
				{
					string text = data[item].TryStack(info.data[item]);
					if (text == null)
					{
						return null;
					}
					dictionary[item] = text;
				}
				foreach (KeyValuePair<string, ItemData> datum in info.data)
				{
					if (!dictionary.ContainsKey(datum.Key))
					{
						string text2 = info.data[datum.Key].TryStack(null);
						if (text2 == null)
						{
							return null;
						}
						dictionary[datum.Key] = text2;
					}
				}
			}
			foreach (KeyValuePair<string, ItemData> datum2 in data)
			{
				if (!dictionary.ContainsKey(datum2.Key))
				{
					string text3 = data[datum2.Key].TryStack(null);
					if (text3 == null)
					{
						return null;
					}
					dictionary[datum2.Key] = text3;
				}
			}
			return dictionary.ToDictionary((KeyValuePair<string, string> kv) => dataKey(kv.Key), (KeyValuePair<string, string> kv) => kv.Value);
		}

		private static void RegisterForceLoadedTypesAddItem(ItemData? __result)
		{
			awakeningItem = null;
			if (__result != null)
			{
				RegisterForceLoadedTypes(__result);
			}
		}

		private static void RegisterForceLoadedTypes(ItemData itemData)
		{
			foreach (Type forceLoadType in ForceLoadTypes)
			{
				string key = classKey(forceLoadType, "");
				string text = dataKey(key);
				if (itemData.m_customData.ContainsKey(text))
				{
					itemData.Data().constructDataObj(text, key);
				}
			}
		}

		private static void ItemDropAwake(ItemDrop __instance)
		{
			GameObject dropPrefab = __instance.m_itemData.m_dropPrefab;
			if (dropPrefab != null && ItemExtensions.itemInfo.TryGetValue(dropPrefab.GetComponent<ItemDrop>().m_itemData, out ItemInfo value))
			{
				__instance.m_itemData.Data().isCloned = new HashSet<string>(value.data.Values.Select((ItemData i) => i.CustomDataKey));
			}
		}

		private static void ItemDropAwakeDelayed(ItemDrop __instance)
		{
			if (!ZNetView.m_forceDisableInit)
			{
				RegisterForceLoadedTypes(__instance.m_itemData);
			}
		}

		private static void ItemDataClonePrefix(ItemData __instance, ItemData __result)
		{
			SaveItem(__instance);
		}

		private static void ItemDataClonePostfix(ItemData __instance, ItemData __result)
		{
			if (ItemExtensions.itemInfo.TryGetValue(__instance, out ItemInfo value))
			{
				__result.Data().isCloned = new HashSet<string>(value.data.Values.Select((ItemData i) => i.CustomDataKey));
			}
		}

		private static void ItemDataClonePostfixDelayed(ItemData __result)
		{
			RegisterForceLoadedTypes(__result);
		}

		private static void RegisterForceLoadedTypesOnPlayerLoaded(Player __instance)
		{
			foreach (Food food in __instance.m_foods)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(food.m_name);
				if (itemPrefab.GetComponent<ItemDrop>().m_itemData == food.m_item)
				{
					food.m_item = food.m_item.Clone();
					food.m_item.m_dropPrefab = itemPrefab;
				}
				RegisterForceLoadedTypes(food.m_item);
			}
		}

		private static void SaveCheckingForStackableItemData(ItemData item)
		{
			checkingForStackableItemData = item;
		}

		private static void ResetCheckingForStackableItemData()
		{
			checkingForStackableItemData = null;
		}

		private static IEnumerable<CodeInstruction> CheckStackableInFindFreeStackMethods(IEnumerable<CodeInstruction> instructionsEnumerable)
		{
			CodeInstruction[] instructions = instructionsEnumerable.ToArray();
			Label target = (Label)instructions.First((CodeInstruction val) => val.opcode == OpCodes.Br || val.opcode == OpCodes.Br_S).operand;
			CodeInstruction targetedInstr = instructions.First((CodeInstruction val) => val.labels.Contains(target));
			Label? label = default(Label?);
			CodeInstruction lastBranch = instructions.Reverse().First((CodeInstruction val) => CodeInstructionExtensions.Branches(val, ref label) && targetedInstr.labels.Contains(label.Value));
			CodeInstruction loadingInstruction = null;
			int i = 0;
			while (i < instructions.Length)
			{
				yield return instructions[i];
				if (loadingInstruction == null && instructions[i].opcode == OpCodes.Call && ((MethodInfo)instructions[i].operand).Name == "get_Current")
				{
					loadingInstruction = instructions[i + 1].Clone();
					loadingInstruction.opcode = new Dictionary<OpCode, OpCode>
					{
						{
							OpCodes.Stloc_0,
							OpCodes.Ldloc_0
						},
						{
							OpCodes.Stloc_1,
							OpCodes.Ldloc_1
						},
						{
							OpCodes.Stloc_2,
							OpCodes.Ldloc_2
						},
						{
							OpCodes.Stloc_3,
							OpCodes.Ldloc_3
						},
						{
							OpCodes.Stloc_S,
							OpCodes.Ldloc_S
						}
					}[loadingInstruction.opcode];
				}
				if (instructions[i] == lastBranch)
				{
					yield return loadingInstruction;
					yield return new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "checkingForStackableItemData"));
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataIsStackableFindFree", (Type[])null, (Type[])null));
					yield return new CodeInstruction(OpCodes.Brfalse, (object)target);
				}
				int num = i + 1;
				i = num;
			}
		}

		private static bool CheckItemDataIsStackableFindFree(ItemData item, ItemData? target)
		{
			if (target == null)
			{
				return true;
			}
			Dictionary<string, string> dictionary = IsStackable(item, target);
			if (dictionary != null)
			{
				newValuesOnStackable = dictionary;
				return true;
			}
			return false;
		}

		private static void ResetNewValuesOnStackable()
		{
			newValuesOnStackable = null;
		}

		private static void ApplyNewValuesOnStackable(ItemData? __result)
		{
			if (__result == null || newValuesOnStackable == null)
			{
				return;
			}
			foreach (KeyValuePair<string, string> item in newValuesOnStackable)
			{
				__result.m_customData[item.Key] = item.Value;
			}
		}

		private static Dictionary<string, string>? IsStackable(ItemData a, ItemData b)
		{
			ItemInfo itemInfo = a.Data();
			if (itemInfo != null)
			{
				return itemInfo.IsStackableWithOtherInfo(b.Data());
			}
			ItemInfo itemInfo2 = b.Data();
			if (itemInfo2 != null)
			{
				return itemInfo2.IsStackableWithOtherInfo(null);
			}
			return new Dictionary<string, string>();
		}

		private static bool CheckItemDataStackableAddItem(Inventory __instance, ItemData item, int x, int y, ref Dictionary<string, string>? __state, ref bool __result)
		{
			ItemData itemAt = __instance.GetItemAt(x, y);
			if (itemAt != null)
			{
				Dictionary<string, string> dictionary = IsStackable(item, itemAt);
				if (dictionary == null)
				{
					__result = false;
					return false;
				}
				__state = dictionary;
			}
			return true;
		}

		private static void ApplyCustomItemDataStackableAddItem(Inventory __instance, int x, int y, Dictionary<string, string>? __state, bool __result)
		{
			if (!__result || __state == null)
			{
				return;
			}
			foreach (KeyValuePair<string, string> item in __state)
			{
				__instance.GetItemAt(x, y).m_customData[item.Key] = item.Value;
			}
		}

		private static void ApplyCustomItemDataStackableAutoStack(ItemDrop item, Dictionary<string, string> customData)
		{
			item.m_itemData.m_customData = customData;
		}

		private static Dictionary<string, string>? IsStackableItemDrop(ItemDrop drop, ItemData item)
		{
			return IsStackable(drop.m_itemData, item);
		}

		private static IEnumerable<CodeInstruction> HandleAutostackableItems(IEnumerable<CodeInstruction> instructionList, ILGenerator ilg)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			List<CodeInstruction> list = instructionList.ToList();
			FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ItemData), "m_stack");
			FieldInfo fieldInfo2 = AccessTools.DeclaredField(typeof(ItemDrop), "m_itemData");
			Label? label = default(Label?);
			for (int i = 0; i < list.Count; i++)
			{
				if (!CodeInstructionExtensions.StoresField(list[i], fieldInfo))
				{
					continue;
				}
				for (int num = i; num > 0; num--)
				{
					if (CodeInstructionExtensions.Branches(list[num], ref label))
					{
						for (int num2 = num; num2 > 0; num2--)
						{
							if (CodeInstructionExtensions.LoadsField(list[num2], fieldInfo2, false))
							{
								LocalBuilder localBuilder = ilg.DeclareLocal(typeof(Dictionary<string, string>));
								LocalBuilder localBuilder2 = ilg.DeclareLocal(typeof(ItemData));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyCustomItemDataStackableAutoStack", (Type[])null, (Type[])null)));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder.LocalIndex));
								list.Insert(i + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Brfalse, (object)label));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Dup, (object)localBuilder.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "IsStackableItemDrop", (Type[])null, (Type[])null)));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2.LocalIndex));
								list.Insert(num + 1, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
								list.Insert(num2 + 1, new CodeInstruction(OpCodes.Stloc, (object)localBuilder2.LocalIndex));
								list.Insert(num2 + 1, new CodeInstruction(OpCodes.Dup, (object)null));
								return list;
							}
						}
					}
				}
			}
			throw new Exception("Found no stack store in a branch");
		}

		private static IEnumerable<CodeInstruction> TransferCustomItemDataOnUpgrade(IEnumerable<CodeInstruction> instructions, ILGenerator ilg)
		{
			MethodInfo itemDeleter = AccessTools.DeclaredMethod(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)itemDeleter))
				{
					yield return new CodeInstruction(OpCodes.Dup, (object)null);
					yield return new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "currentlyUpgradingItem"));
				}
				yield return instruction;
			}
		}

		private static void ResetCurrentlyUpgradingItem()
		{
			currentlyUpgradingItem = null;
		}

		private static void CopyCustomDataFromUpgradedItem(ItemDrop item)
		{
			if (currentlyUpgradingItem != null)
			{
				item.m_itemData.m_customData = currentlyUpgradingItem.m_customData;
				ItemInfo itemInfo = currentlyUpgradingItem.Data();
				ItemExtensions.itemInfo.Remove(currentlyUpgradingItem);
				ItemExtensions.itemInfo.Add(item.m_itemData, itemInfo);
				item.m_itemData.m_quality = currentlyUpgradingItem.m_quality + 1;
				item.m_itemData.m_variant = currentlyUpgradingItem.m_variant;
				itemInfo.ItemData = item.m_itemData;
				itemInfo.LoadAll();
				foreach (ItemData value in itemInfo.data.Values)
				{
					value.Upgraded();
				}
				currentlyUpgradingItem = null;
				awakeningItem = null;
				return;
			}
			GameObject dropPrefab = item.m_itemData.m_dropPrefab;
			if (dropPrefab == null || item.m_itemData.m_customData.Count != 0)
			{
				return;
			}
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			ZDO val = ((Object.op_Implicit((Object)(object)component) && component.IsValid()) ? component.GetZDO() : null);
			if (val != null && val.GetInt(ZDOVars.s_dataCount, -1) != -1)
			{
				return;
			}
			item.m_itemData.m_customData = new Dictionary<string, string>(dropPrefab.GetComponent<ItemDrop>().m_itemData.m_customData);
			if (val == null)
			{
				return;
			}
			int num = 0;
			val.Set(ZDOVars.s_dataCount, item.m_itemData.m_customData.Count, false);
			foreach (KeyValuePair<string, string> customDatum in item.m_itemData.m_customData)
			{
				val.Set($"data_{num}", customDatum.Key);
				val.Set($"data__{num++}", customDatum.Value);
			}
		}

		private static IEnumerable<CodeInstruction> ImportCustomDataOnUpgrade(IEnumerable<CodeInstruction> instructionList)
		{
			List<CodeInstruction> list = instructionList.ToList();
			foreach (CodeInstruction instruction in list)
			{
				yield return instruction;
				if (instruction.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)AccessTools.DeclaredField(typeof(ItemData), "m_dropPrefab")))
				{
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CopyCustomDataFromUpgradedItem", (Type[])null, (Type[])null));
				}
			}
		}

		private static void TrackAwakeningItem(ItemDrop __instance)
		{
			if (ZNetView.m_forceDisableInit)
			{
				awakeningItem = __instance.m_itemData;
			}
		}

		static ItemInfo()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_01d0: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_023f: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Expected O, but got Unknown
			//IL_02a1: Expected O, but got Unknown
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Expected O, but got Unknown
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Expected O, but got Unknown
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Expected O, but got Unknown
			//IL_0351: Expected O, but got Unknown
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Expected O, but got Unknown
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Expected O, but got Unknown
			//IL_03e3: Expected O, but got Unknown
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Expected O, but got Unknown
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Expected O, but got Unknown
			//IL_0552: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Expected O, but got Unknown
			//IL_058d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bf: Expected O, but got Unknown
			//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Expected O, but got Unknown
			//IL_05f3: Expected O, but got Unknown
			//IL_0632: Unknown result type (might be due to invalid IL or missing references)
			//IL_063f: Expected O, but got Unknown
			//IL_066d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0698: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a5: Expected O, but got Unknown
			//IL_06a5: Expected O, but got Unknown
			//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f1: Expected O, but got Unknown
			ForceLoadTypes = new HashSet<Type>();
			typeInheritorsCache = new Dictionary<Type, HashSet<Type>>();
			knownTypes = new HashSet<string>();
			awakeningItem = null;
			primaryAssembly = Assembly.GetExecutingAssembly();
			assemblyNameCache = new Dictionary<Assembly, string>();
			classKeyCache = new Dictionary<Type, string>();
			removeMethod = typeof(ItemInfo).GetMethods().Single((MethodInfo m) => m.Name == "Remove" && m.IsGenericMethod && m.GetParameters()[0].ParameterType == typeof(string));
			Harmony val = new Harmony("org.bepinex.helpers.ItemDataManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "Save", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveInventoryPrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			foreach (MethodInfo item in from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "SaveToZDO"
				select m)
			{
				val.Patch((MethodBase)item, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SavePrefix", (Type[])null, (Type[])null), 800, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[4]
			{
				typeof(ItemData),
				typeof(int),
				typeof(int),
				typeof(int)
			}, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataStackableAddItem", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyCustomItemDataStackableAddItem", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "CanAddItem", new Type[2]
			{
				typeof(ItemData),
				typeof(int)
			}, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "AddItem", new Type[1] { typeof(ItemData) }, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "SaveCheckingForStackableItemData", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ItemInfo), "ResetCheckingForStackableItemData", (Type[])null), (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Inventory), "FindFreeStackSpace", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Inventory), "FindFreeStackItem", (Type[])null, (Type[])null);
			HarmonyMethod val2 = new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckStackableInFindFreeStackMethods", (Type[])null, (Type[])null));
			val.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ResetNewValuesOnStackable", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ApplyNewValuesOnStackable", (Type[])null, (Type[])null)), val2, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemDrop), "AutoStackItems", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "HandleAutostackableItems", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(InventoryGui), "DoCrafting", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "TransferCustomItemDataOnUpgrade", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "ResetCurrentlyUpgradingItem", (Type[])null, (Type[])null)), (HarmonyMethod)null);
			foreach (MethodInfo item2 in from m in typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "LoadFromZDO"
				select m)
			{
				val.Patch((MethodBase)item2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypes", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Player), "Load", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(ItemInfo), "RegisterForceLoadedTypesOnPlayerLoaded", (Type[])null, (Type[])null), 700, (string[])null, (string[])null, (bool?)null), (HarmonyMethod)