Decompiled source of Valheim Enchantment System v1.9.9

kg.ValheimEnchantmentSystem.dll

Decompiled a week 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: Guid("02E7D016-77BE-40E0-9D13-8656CD0A4FD3")]
[assembly: AssemblyFileVersion("1.9.8.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.9.8.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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)
	{
		Character ___m_character2 = ___m_character;
		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_character2, 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)
			{
				ObjectDB objectDb2 = objectDb;
				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 = objectDb2.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 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] { ':' });
					Requirement result = default(Requirement);
					result.itemName = array[0];
					result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2);
					bool result3 = default(bool);
					result.recover = array.Length <= 2 || !bool.TryParse(array[2], out result3) || result3;
					return result;
				}));
			}
		}

		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()
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			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 group = (string.IsNullOrWhiteSpace(text) ? localizedDisplayName : text);
					PieceConfig pieceConfig2 = (pieceConfigs[piece] = new PieceConfig());
					PieceConfig pieceConfig3 = pieceConfig2;
					pieceConfig3.craft = Config(group, "Crafting Costs", SerializedRequirements.Serialize(piece.RequiredItems.Requirements), new ConfigDescription("Item costs to craft " + localizedDisplayName + ".", (AcceptableValueBase)null, Array.Empty<object>()));
					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 class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public string? Category;
		}

		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 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)(ref val)).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 "Enchantment";
		}

		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()
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			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, new ConfigDescription("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.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Category = configCategory
					}
				}));
				skill.SkillGainFactor = skillGain.Value;
				skillGain.SettingChanged += delegate
				{
					skill.SkillGainFactor = skillGain.Value;
				};
				if (!IsEnchantmentSkill(skill))
				{
					ConfigEntry<float> skillEffect = config(configGroup, "Skill effect factor", skill.SkillEffectFactor, new ConfigDescription("The power of the skill, based on the default power.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 5f), new object[1]
					{
						new ConfigurationManagerAttributes
						{
							Category = configCategory
						}
					}));
					skill.SkillEffectFactor = skillEffect.Value;
					skillEffect.SettingChanged += delegate
					{
						skill.SkillEffectFactor = skillEffect.Value;
					};
				}
				ConfigEntry<int> skillLoss = config(configGroup, "Skill loss", skill.skillLoss, new ConfigDescription("How much experience to lose on death. " + GetSkillKeyDescription(key) + " Required EXP per level follows: ((current level + 1)^1.5) / 2 + 0.5.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Category = configCategory
					}
				}));
				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 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)
			{
				SkillType current = key;
				Skill skill = skills[current];
				if (string.Equals(skill.internalSkillName, name, StringComparison.CurrentCultureIgnoreCase))
				{
					Skill skill2 = __instance.GetSkill(current);
					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)(ref current)).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)
		{
			Localization localization2 = localization;
			lock (CacheLock)
			{
				Localization target;
				string key = Localizations.FirstOrDefault<KeyValuePair<string, WeakReference<Localization>>>((KeyValuePair<string, WeakReference<Localization>> pair) => pair.Value.TryGetTarget(out target) && target == localization2).Key;
				if (key != null)
				{
					Localizations.Remove(key);
				}
				Localizations[language] = new WeakReference<Localization>(localization2);
			}
		}

		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
		{
			string key2 = key;
			string placeholder2 = placeholder;
			Func<T, string> convertConfigValue2 = convertConfigValue;
			ConfigEntry<T> config2 = config;
			if (convertConfigValue2 == null)
			{
				convertConfigValue2 = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key2))
			{
				PlaceholderProcessors[key2] = new Dictionary<string, Func<string>>();
			}
			config2.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (Localization.instance != null && LoadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				if (Localization.instance != null)
				{
					PlaceholderProcessors[key2][placeholder2] = () => convertConfigValue2(config2.Value);
					UpdatePlaceholderText(Localization.instance, key2);
				}
			}
		}

		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)
		{
			string resourceFileName2 = resourceFileName;
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName2, 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
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass57_0
		{
			public Label target;

			public CodeInstruction targetedInstr;

			internal bool <CheckStackableInFindFreeStackMethods>b__1(CodeInstruction i)
			{
				return i.labels.Contains(target);
			}

			internal bool <CheckStackableInFindFreeStackMethods>b__2(CodeInstruction i)
			{
				Label? label = default(Label?);
				if (CodeInstructionExtensions.Branches(i, ref label))
				{
					return targetedInstr.labels.Contains(label.Value);
				}
				return false;
			}
		}

		[CompilerGenerated]
		private sealed class <CheckStackableInFindFreeStackMethods>d__57 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructionsEnumerable;

			public IEnumerable<CodeInstruction> <>3__instructionsEnumerable;

			private <>c__DisplayClass57_0 <>8__1;

			private CodeInstruction[] <instructions>5__2;

			private CodeInstruction <lastBranch>5__3;

			private CodeInstruction <loadingInstruction>5__4;

			private int <i>5__5;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CheckStackableInFindFreeStackMethods>d__57(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = null;
				<instructions>5__2 = null;
				<lastBranch>5__3 = null;
				<loadingInstruction>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_023c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0246: Expected O, but got Unknown
				//IL_0272: Unknown result type (might be due to invalid IL or missing references)
				//IL_027c: Expected O, but got Unknown
				//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ac: Expected O, but got Unknown
				int num;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<>8__1 = new <>c__DisplayClass57_0();
					<instructions>5__2 = instructionsEnumerable.ToArray();
					<>8__1.target = (Label)<instructions>5__2.First((CodeInstruction i) => i.opcode == OpCodes.Br || i.opcode == OpCodes.Br_S).operand;
					<>8__1.targetedInstr = <instructions>5__2.First((CodeInstruction i) => i.labels.Contains(<>8__1.target));
					Label? label = default(Label?);
					<lastBranch>5__3 = <instructions>5__2.Reverse().First((CodeInstruction i) => CodeInstructionExtensions.Branches(i, ref label) && <>8__1.targetedInstr.labels.Contains(label.Value));
					<loadingInstruction>5__4 = null;
					<i>5__5 = 0;
					break;
				}
				case 1:
					<>1__state = -1;
					if (<loadingInstruction>5__4 == null && <instructions>5__2[<i>5__5].opcode == OpCodes.Call && ((MethodInfo)<instructions>5__2[<i>5__5].operand).Name == "get_Current")
					{
						<loadingInstruction>5__4 = <instructions>5__2[<i>5__5 + 1].Clone();
						<loadingInstruction>5__4.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>5__4.opcode];
					}
					if (<instructions>5__2[<i>5__5] == <lastBranch>5__3)
					{
						<>2__current = <loadingInstruction>5__4;
						<>1__state = 2;
						return true;
					}
					goto IL_02bc;
				case 2:
					<>1__state = -1;
					<>2__current = new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "checkingForStackableItemData"));
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CheckItemDataIsStackableFindFree", (Type[])null, (Type[])null));
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>2__current = new CodeInstruction(OpCodes.Brfalse, (object)<>8__1.target);
					<>1__state = 5;
					return true;
				case 5:
					{
						<>1__state = -1;
						goto IL_02bc;
					}
					IL_02bc:
					num = <i>5__5 + 1;
					<i>5__5 = num;
					break;
				}
				if (<i>5__5 < <instructions>5__2.Length)
				{
					<>2__current = <instructions>5__2[<i>5__5];
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<CheckStackableInFindFreeStackMethods>d__57 <CheckStackableInFindFreeStackMethods>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<CheckStackableInFindFreeStackMethods>d__ = this;
				}
				else
				{
					<CheckStackableInFindFreeStackMethods>d__ = new <CheckStackableInFindFreeStackMethods>d__57(0);
				}
				<CheckStackableInFindFreeStackMethods>d__.instructionsEnumerable = <>3__instructionsEnumerable;
				return <CheckStackableInFindFreeStackMethods>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <ImportCustomDataOnUpgrade>d__71 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructionList;

			public IEnumerable<CodeInstruction> <>3__instructionList;

			private List<CodeInstruction>.Enumerator <>7__wrap1;

			private CodeInstruction <instruction>5__3;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ImportCustomDataOnUpgrade>d__71(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 2u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(List<CodeInstruction>.Enumerator);
				<instruction>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Expected O, but got Unknown
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cc: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						List<CodeInstruction> list = instructionList.ToList();
						<>7__wrap1 = list.GetEnumerator();
						<>1__state = -3;
						break;
					}
					case 1:
						<>1__state = -3;
						if (<instruction>5__3.opcode == OpCodes.Stfld && CodeInstructionExtensions.OperandIs(<instruction>5__3, (MemberInfo)AccessTools.DeclaredField(typeof(ItemData), "m_dropPrefab")))
						{
							<>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
							<>1__state = 2;
							return true;
						}
						goto IL_0118;
					case 2:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(ItemInfo), "CopyCustomDataFromUpgradedItem", (Type[])null, (Type[])null));
						<>1__state = 3;
						return true;
					case 3:
						{
							<>1__state = -3;
							goto IL_0118;
						}
						IL_0118:
						<instruction>5__3 = null;
						break;
					}
					if (<>7__wrap1.MoveNext())
					{
						<instruction>5__3 = <>7__wrap1.Current;
						<>2__current = <instruction>5__3;
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap1 = default(List<CodeInstruction>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<ImportCustomDataOnUpgrade>d__71 <ImportCustomDataOnUpgrade>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ImportCustomDataOnUpgrade>d__ = this;
				}
				else
				{
					<ImportCustomDataOnUpgrade>d__ = new <ImportCustomDataOnUpgrade>d__71(0);
				}
				<ImportCustomDataOnUpgrade>d__.instructionList = <>3__instructionList;
				return <ImportCustomDataOnUpgrade>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <TransferCustomItemDataOnUpgrade>d__68 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private MethodInfo <itemDeleter>5__2;

			private IEnumerator<CodeInstruction> <>7__wrap2;

			private CodeInstruction <instruction>5__4;

			CodeInstruction IEnumerator<CodeInstruction>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <TransferCustomItemDataOnUpgrade>d__68(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 2u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<itemDeleter>5__2 = null;
				<>7__wrap2 = null;
				<instruction>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Expected O, but got Unknown
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<itemDeleter>5__2 = AccessTools.DeclaredMethod(typeof(Inventory), "RemoveItem", new Type[1] { typeof(ItemData) }, (Type[])null);
						<>7__wrap2 = instructions.GetEnumerator();
						<>1__state = -3;
						goto IL_0136;
					case 1:
						<>1__state = -3;
						<>2__current = new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.DeclaredField(typeof(ItemInfo), "currentlyUpgradingItem"));
						<>1__state = 2;
						return true;
					case 2:
						<>1__state = -3;
						goto IL_0110;
					case 3:
						{
							<>1__state = -3;
							<instruction>5__4 = null;
							goto IL_0136;
						}
						IL_0136:
						if (<>7__wrap2.MoveNext())
						{
							<instruction>5__4 = <>7__wrap2.Current;
							if (<instruction>5__4.opcode == OpCodes.Callvirt && CodeInstructionExtensions.OperandIs(<instruction>5__4, (MemberInfo)<itemDeleter>5__2))
							{
								<>2__current = new CodeInstruction(OpCodes.Dup, (object)null);
								<>1__state = 1;
								return true;
							}
							goto IL_0110;
						}
						<>m__Finally1();
						<>7__wrap2 = null;
						return false;
						IL_0110:
						<>2__current = <instruction>5__4;
						<>1__state = 3;
						return true;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap2 != null)
				{
					<>7__wrap2.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<TransferCustomItemDataOnUpgrade>d__68 <TransferCustomItemDataOnUpgrade>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<TransferCustomItemDataOnUpgrade>d__ = this;
				}
				else
				{
					<TransferCustomItemDataOnUpgrade>d__ = new <TransferCustomItemDataOnUpgrade>d__68(0);
				}
				<TransferCustomItemDataOnUpgrade>d__.instructions = <>3__instructions;
				return <TransferCustomItemDataOnUpgrade>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
			}
		}

		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)
		{
			Type type2 = type;
			if (!knownTypes.Contains(typeKey))
			{
				knownTypes.Add(typeKey);
				Type type3 = type2;
				while ((object)type3 != null)
				{
					AddInterfaces(type3);
					type3 = type3.BaseType;
				}
			}
			void AddInterfaces(Type baseType)
			{
				if (!typeInheritorsCache.TryGetValue(baseType, out HashSet<Type> value))
				{
					HashSet<Type> hashSet2 = (typeInheritorsCache[baseType] = new HashSet<Type>());
					value = hashSet2;
				}
				value.Add(type2);
				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;
		}

		[IteratorStateMachine(typeof(<CheckStackableInFindFreeStackMethods>d__57))]
		private static IEnumerable<CodeInstruction> CheckStackableInFindFreeStackMethods(IEnumerable<CodeInstruction> instructionsEnumerable)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckStackableInFindFreeStackMethods>d__57(-2)
			{
				<>3__instructionsEnumerable = instructionsEnumerable
			};
		}

		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--)