Decompiled source of MoreJewelry Updated v1.0.13

plugins/MoreJewelry.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
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 BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemManager;
using JetBrains.Annotations;
using Jewelcrafting;
using LocalizationManager;
using Managers;
using Microsoft.CodeAnalysis;
using MockManager;
using MoreJewelry.Data;
using ServerSync;
using SoftReferenceableAssets;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
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;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("MoreJewelry")]
[assembly: AssemblyDescription("https://thunderstore.io/c/valheim/p/probablykory/MoreJewelry/")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("probablykory")]
[assembly: AssemblyProduct("MoreJewelry")]
[assembly: AssemblyCopyright("Copyright probablykory © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("964752f0-09df-446a-9c20-88bf895c6178")]
[assembly: AssemblyFileVersion("1.0.13")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_postprocessing")]
[assembly: IgnoresAccessChecksTo("assembly_sunshafts")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: IgnoresAccessChecksTo("SoftReferenceableAssets")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.13.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MockManager
{
	public class AssetManager
	{
		private static class Patches
		{
			[HarmonyPatch(typeof(AssetBundleLoader), "OnInitCompleted")]
			[HarmonyPostfix]
			private static void AssetBundleLoader_Load(AssetBundleLoader __instance)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				foreach (KeyValuePair<AssetID, AssetRef> asset in Instance.assets)
				{
					AddAssetToBundleLoader(__instance, asset.Key, asset.Value);
				}
			}
		}

		private struct AssetRef
		{
			public BepInPlugin sourceMod;

			public Object asset;

			public AssetID originalID;

			public AssetRef(BepInPlugin sourceMod, Object asset, Object original)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				this.sourceMod = sourceMod;
				this.asset = asset;
				originalID = (AssetID)((Object.op_Implicit(original) && Instance.IsReady()) ? Instance.GetAssetID(((object)original).GetType(), original.name) : default(AssetID));
			}
		}

		private static AssetManager instance;

		private Dictionary<AssetID, AssetRef> assets = new Dictionary<AssetID, AssetRef>();

		private Dictionary<Type, Dictionary<string, AssetID>> mapNameToAssetID;

		public static AssetManager Instance => instance ?? (instance = new AssetManager());

		internal Dictionary<Type, Dictionary<string, AssetID>> MapNameToAssetID => mapNameToAssetID ?? (mapNameToAssetID = CreateNameToAssetID());

		private AssetManager()
		{
		}

		public void Init()
		{
			Main.Mod.Harmony.PatchAll(typeof(Patches));
			Logger.LogDebugOnly("AssetManager initialized.");
		}

		public bool IsReady()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (Runtime.s_assetLoader != null)
			{
				return ((AssetBundleLoader)Runtime.s_assetLoader).Initialized;
			}
			return false;
		}

		public AssetID AddAsset(Object asset, Object original)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			AssetID val = GenerateAssetID(asset);
			if (assets.ContainsKey(val))
			{
				return val;
			}
			AssetRef assetRef = new AssetRef(BepInExUtils.GetSourceModMetadata(), asset, original);
			assets.Add(val, assetRef);
			if (AssetBundleLoader.Instance != null)
			{
				AddAssetToBundleLoader(AssetBundleLoader.Instance, val, assetRef);
			}
			return val;
		}

		public AssetID AddAsset(Object asset)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return AddAsset(asset, null);
		}

		private static void AddAssetToBundleLoader(AssetBundleLoader assetBundleLoader, AssetID assetID, AssetRef assetRef)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit(assetRef.asset))
			{
				Logger.LogWarning($"Asset == null for AssetID {assetID}, skipping");
				return;
			}
			string text = "JVL_BundleWrapper_" + assetRef.asset.name;
			string text2 = assetRef.sourceMod.GUID + "/Prefabs/" + assetRef.asset.name;
			if (assetBundleLoader.m_bundleNameToLoaderIndex.ContainsKey(text))
			{
				return;
			}
			AssetLocation val = default(AssetLocation);
			((AssetLocation)(ref val))..ctor(text, text2);
			BundleLoader val2 = default(BundleLoader);
			((BundleLoader)(ref val2))..ctor(text, "");
			((BundleLoader)(ref val2)).HoldReference();
			assetBundleLoader.m_bundleNameToLoaderIndex.Add(text, assetBundleLoader.m_bundleLoaders.Length);
			assetBundleLoader.m_bundleLoaders = CollectionExtensions.AddItem<BundleLoader>((IEnumerable<BundleLoader>)assetBundleLoader.m_bundleLoaders, val2).ToArray();
			int originalBundleLoaderIndex = ((IEnumerable<AssetLoader>)assetBundleLoader.m_assetLoaders).FirstOrDefault((Func<AssetLoader, bool>)((AssetLoader l) => l.m_assetID == assetRef.originalID)).m_bundleLoaderIndex;
			if (((AssetID)(ref assetRef.originalID)).IsValid && originalBundleLoaderIndex > 0)
			{
				BundleLoader val3 = assetBundleLoader.m_bundleLoaders[originalBundleLoaderIndex];
				val2.m_bundleLoaderIndicesOfThisAndDependencies = (from i in CollectionExtensions.AddItem<int>(val3.m_bundleLoaderIndicesOfThisAndDependencies.Where((int i) => i != originalBundleLoaderIndex), assetBundleLoader.m_bundleNameToLoaderIndex[text])
					orderby i
					select i).ToArray();
			}
			else
			{
				((BundleLoader)(ref val2)).SetDependencies(Array.Empty<string>());
			}
			assetBundleLoader.m_bundleLoaders[assetBundleLoader.m_bundleNameToLoaderIndex[text]] = val2;
			AssetLoader val4 = default(AssetLoader);
			((AssetLoader)(ref val4))..ctor(assetID, val);
			val4.m_asset = assetRef.asset;
			((AssetLoader)(ref val4)).HoldReference();
			assetBundleLoader.m_assetIDToLoaderIndex.Add(assetID, assetBundleLoader.m_assetLoaders.Length);
			assetBundleLoader.m_assetLoaders = CollectionExtensions.AddItem<AssetLoader>((IEnumerable<AssetLoader>)assetBundleLoader.m_assetLoaders, val4).ToArray();
			Instance.MapNameToAssetID[((object)assetRef.asset).GetType()][assetRef.asset.name] = assetID;
			Logger.LogDebug($"Added prefab '{assetRef.asset.name}' with ID {assetID} to AssetBundleLoader");
		}

		public AssetID GenerateAssetID(Object asset)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			uint stableHashCode = (uint)StringExtensionMethods.GetStableHashCode(asset.name);
			return new AssetID(stableHashCode, stableHashCode, stableHashCode, stableHashCode);
		}

		public GameObject ClonePrefab(GameObject asset, string newName, Transform parent)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(asset, parent);
			((Object)val).name = newName;
			AddAsset((Object)(object)val, (Object)(object)asset);
			return val;
		}

		public AssetID GetAssetID(Type type, string name)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!IsReady())
			{
				throw new InvalidOperationException("The vanilla asset system is not initialized yet");
			}
			if (MapNameToAssetID.TryGetValue(type, out Dictionary<string, AssetID> value) && value.TryGetValue(name, out var value2))
			{
				return value2;
			}
			if (MapNameToAssetID.TryGetValue(typeof(Object), out value) && value.TryGetValue(name, out value2))
			{
				return value2;
			}
			return default(AssetID);
		}

		public AssetID GetAssetID<T>(string name) where T : Object
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return GetAssetID(typeof(T), name);
		}

		public SoftReference<Object> GetSoftReference(Type type, string name)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_001d: 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)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			AssetID assetID = GetAssetID(type, name);
			if (!((AssetID)(ref assetID)).IsValid)
			{
				return default(SoftReference<Object>);
			}
			return new SoftReference<Object>(assetID);
		}

		public SoftReference<T> GetSoftReference<T>(string name) where T : Object
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0013: 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)
			AssetID assetID = GetAssetID<T>(name);
			if (!((AssetID)(ref assetID)).IsValid)
			{
				return default(SoftReference<T>);
			}
			return new SoftReference<T>(assetID);
		}

		private static Dictionary<Type, Dictionary<string, AssetID>> CreateNameToAssetID()
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (!Instance.IsReady())
			{
				throw new InvalidOperationException("The vanilla asset system is not initialized yet");
			}
			Dictionary<Type, Dictionary<string, AssetID>> dictionary = new Dictionary<Type, Dictionary<string, AssetID>>();
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			foreach (KeyValuePair<string, AssetID> item in Runtime.GetAllAssetPathsInBundleMappedToAssetID().ToList())
			{
				string text = item.Key.Split(new char[1] { '/' }).Last();
				string text2 = text.Split(new char[1] { '.' }).Last();
				string key = text.RemoveSuffix("." + text2);
				if (!(item.Key == "Assets/UI/prefabs/radials/elements/Hammer.prefab"))
				{
					Type type = Instance.TypeFromExtension(text2);
					if (type == null && text2 == "asset" && text.StartsWith("Recipe_"))
					{
						type = typeof(Recipe);
					}
					if (type == null)
					{
						type = typeof(Object);
					}
					if (!dictionary.ContainsKey(type))
					{
						dictionary.Add(type, new Dictionary<string, AssetID>());
					}
					if (!dictionary[type].ContainsKey(key) || !SkipAmbiguousPath(dictionary2[key], item.Key, text2))
					{
						dictionary[type][key] = item.Value;
						dictionary2[key] = item.Key;
					}
				}
			}
			return dictionary;
		}

		private static bool SkipAmbiguousPath(string oldPath, string newPath, string extension)
		{
			if (extension == "prefab")
			{
				if (oldPath.StartsWith("Assets/world/Locations"))
				{
					return false;
				}
				if (newPath.StartsWith("Assets/world/Locations"))
				{
					return true;
				}
				if (oldPath.StartsWith("Assets/world/Props/DeepNorth"))
				{
					return false;
				}
				Logger.LogWarning("Ambiguous asset name for path. old: " + oldPath + ", new: " + newPath + ", using old path");
			}
			return true;
		}

		private Type TypeFromExtension(string extension)
		{
			switch (extension.ToLower())
			{
			case "prefab":
				return typeof(GameObject);
			case "mat":
				return typeof(Material);
			case "obj":
			case "fbx":
				return typeof(Mesh);
			case "png":
			case "jpg":
			case "tga":
			case "tif":
				return typeof(Texture2D);
			case "wav":
			case "mp3":
				return typeof(AudioClip);
			case "controller":
				return typeof(RuntimeAnimatorController);
			case "physicmaterial":
			case "physicsmaterial":
				return typeof(PhysicsMaterial);
			case "shader":
				return typeof(Shader);
			case "anim":
				return typeof(AnimationClip);
			case "mixer":
				return typeof(AudioMixer);
			case "txt":
				return typeof(TextAsset);
			case "ttf":
			case "otf":
				return typeof(TMP_FontAsset);
			case "rendertexture":
				return typeof(RenderTexture);
			case "lighting":
				return typeof(LightingSettings);
			default:
				return null;
			}
		}
	}
	internal static class BepInExUtils
	{
		private static BaseUnityPlugin[] Plugins;

		private static Dictionary<PluginInfo, string> PluginInfoTypeNameCache { get; } = new Dictionary<PluginInfo, string>();

		private static Dictionary<Assembly, PluginInfo> AssemblyToPluginInfoCache { get; } = new Dictionary<Assembly, PluginInfo>();

		private static Dictionary<Type, PluginInfo> TypeToPluginInfoCache { get; } = new Dictionary<Type, PluginInfo>();

		private static BaseUnityPlugin[] CacheDependentPlugins()
		{
			List<BaseUnityPlugin> list = new List<BaseUnityPlugin>();
			foreach (BaseUnityPlugin loadedPlugin in GetLoadedPlugins())
			{
				if (loadedPlugin.Info == null)
				{
					Logger.LogWarning("Plugin without Info found: " + ((object)loadedPlugin).GetType().Assembly.FullName);
					continue;
				}
				if (loadedPlugin.Info.Metadata == null)
				{
					Logger.LogWarning("Plugin without Metadata found: " + ((object)loadedPlugin).GetType().Assembly.FullName);
					continue;
				}
				if (loadedPlugin.Info.Metadata.GUID == Main.Mod.GUID)
				{
					list.Add(loadedPlugin);
					continue;
				}
				foreach (BepInDependency item in ((object)loadedPlugin).GetType().GetCustomAttributes(typeof(BepInDependency), inherit: false).Cast<BepInDependency>())
				{
					if (item.DependencyGUID == Main.Mod.GUID)
					{
						list.Add(loadedPlugin);
					}
				}
			}
			return list.ToArray();
		}

		public static Dictionary<string, BaseUnityPlugin> GetDependentPlugins(bool includeSelf = false)
		{
			if (Plugins == null)
			{
				if (!ReflectionHelper.GetPrivateField<bool>(typeof(Chainloader), "_loaded"))
				{
					return new Dictionary<string, BaseUnityPlugin>();
				}
				Plugins = CacheDependentPlugins();
			}
			return Plugins.Where((BaseUnityPlugin plugin) => includeSelf || plugin.Info.Metadata.GUID != Main.Mod.GUID).ToDictionary((BaseUnityPlugin plugin) => plugin.Info.Metadata.GUID);
		}

		public static Dictionary<string, BaseUnityPlugin> GetPlugins(bool includeSelf = false)
		{
			return (from plugin in GetLoadedPlugins()
				where includeSelf || plugin.Info.Metadata.GUID != Main.Mod.GUID
				select plugin).ToDictionary((BaseUnityPlugin plugin) => plugin.Info.Metadata.GUID);
		}

		public static PluginInfo GetPluginInfoFromType(Type type)
		{
			if (TypeToPluginInfoCache.TryGetValue(type, out PluginInfo value))
			{
				return value;
			}
			foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
			{
				if (ReflectionHelper.GetPrivateProperty<string>(value2, "TypeName").Equals(type.FullName))
				{
					TypeToPluginInfoCache[type] = value2;
					return value2;
				}
			}
			return null;
		}

		private static string GetPluginInfoTypeName(PluginInfo info)
		{
			if (PluginInfoTypeNameCache.TryGetValue(info, out string value))
			{
				return value;
			}
			value = ReflectionHelper.GetPrivateProperty<string>(info, "TypeName");
			PluginInfoTypeNameCache.Add(info, value);
			return value;
		}

		public static PluginInfo GetPluginInfoFromAssembly(Assembly assembly)
		{
			if (AssemblyToPluginInfoCache.TryGetValue(assembly, out PluginInfo value))
			{
				return value;
			}
			foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
			{
				if (assembly.GetType(GetPluginInfoTypeName(value2)) != null)
				{
					AssemblyToPluginInfoCache[assembly] = value2;
					return value2;
				}
			}
			AssemblyToPluginInfoCache[assembly] = null;
			return null;
		}

		public static PluginInfo GetPluginInfoFromPath(FileInfo fileInfo)
		{
			return Chainloader.PluginInfos.Values.Where((PluginInfo pi) => pi.Location != null).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo pi) => fileInfo.DirectoryName != null && fileInfo.DirectoryName.Contains(new FileInfo(pi.Location).DirectoryName) && new FileInfo(pi.Location).DirectoryName != Paths.PluginPath));
		}

		public static BepInPlugin GetSourceModMetadata()
		{
			Type callingType = ReflectionHelper.GetCallingType();
			PluginInfo pluginInfoFromType = GetPluginInfoFromType(callingType);
			BepInPlugin val = ((pluginInfoFromType != null) ? pluginInfoFromType.Metadata : null);
			if (val == null)
			{
				PluginInfo pluginInfoFromAssembly = GetPluginInfoFromAssembly(callingType.Assembly);
				val = ((pluginInfoFromAssembly != null) ? pluginInfoFromAssembly.Metadata : null) ?? Main.Mod.Info.Metadata;
			}
			return val;
		}

		private static IEnumerable<BaseUnityPlugin> GetLoadedPlugins()
		{
			return from x in Chainloader.PluginInfos
				where x.Value != null && (Object)(object)x.Value.Instance != (Object)null
				select x.Value.Instance;
		}
	}
	public static class Cache
	{
		private static readonly Dictionary<Type, Dictionary<string, Object>> dictionaryCache = new Dictionary<Type, Dictionary<string, Object>>();

		public static Object GetPrefab(Type type, string name)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (AssetManager.Instance.IsReady())
			{
				SoftReference<Object> softReference = AssetManager.Instance.GetSoftReference(type, name);
				if (softReference.IsValid)
				{
					softReference.Load();
					if (Object.op_Implicit(softReference.Asset))
					{
						if (softReference.Asset != (Object)null && ((object)softReference.Asset).GetType() == type)
						{
							return softReference.Asset;
						}
						Object asset = softReference.Asset;
						GameObject val = (GameObject)(object)((asset is GameObject) ? asset : null);
						if (val != null && TryFindAssetInSelfOrChildComponents(val, type, out Object asset2))
						{
							return asset2;
						}
					}
				}
			}
			if (GetCachedMap(type).TryGetValue(name, out Object value))
			{
				return value;
			}
			return null;
		}

		public static T GetPrefab<T>(string name) where T : Object
		{
			return (T)(object)GetPrefab(typeof(T), name);
		}

		public static Dictionary<string, Object> GetPrefabs(Type type)
		{
			return GetCachedMap(type);
		}

		private static Transform GetParent(Object obj)
		{
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val == null)
			{
				return null;
			}
			return val.transform.parent;
		}

		private static Object FindBestAsset(IDictionary<string, Object> map, Object newObject, string name)
		{
			if (!map.TryGetValue(name, out Object value))
			{
				return newObject;
			}
			if (name == "_NetScene")
			{
				GameObject val = (GameObject)(object)((value is GameObject) ? value : null);
				if (val != null)
				{
					GameObject val2 = (GameObject)(object)((newObject is GameObject) ? newObject : null);
					if (val2 != null && !val.activeInHierarchy && val2.activeInHierarchy)
					{
						return (Object)(object)val2;
					}
				}
			}
			Material val3 = (Material)(object)((value is Material) ? value : null);
			if (val3 != null)
			{
				Material val4 = (Material)(object)((newObject is Material) ? newObject : null);
				if (val4 != null && FindBestMaterial(val3, val4, out Object material))
				{
					return material;
				}
			}
			bool flag = Object.op_Implicit((Object)(object)GetParent(value));
			bool flag2 = Object.op_Implicit((Object)(object)GetParent(newObject));
			if (!flag && flag2)
			{
				return value;
			}
			if (flag)
			{
				return newObject;
			}
			return newObject;
		}

		private static bool FindBestMaterial(Material cachedMaterial, Material newMaterial, out Object material)
		{
			string name = ((Object)cachedMaterial.shader).name;
			string name2 = ((Object)newMaterial.shader).name;
			if (name == "Hidden/InternalErrorShader" && name2 != "Hidden/InternalErrorShader")
			{
				material = (Object)(object)newMaterial;
				return true;
			}
			if (name != "Hidden/InternalErrorShader" && name2 == "Hidden/InternalErrorShader")
			{
				material = (Object)(object)cachedMaterial;
				return true;
			}
			material = null;
			return false;
		}

		private static Dictionary<string, Object> GetCachedMap(Type type)
		{
			if (dictionaryCache.TryGetValue(type, out Dictionary<string, Object> value))
			{
				return value;
			}
			return InitCache(type);
		}

		private static Dictionary<string, Object> InitCache(Type type)
		{
			Dictionary<string, Object> dictionary = new Dictionary<string, Object>();
			Object[] array = Resources.FindObjectsOfTypeAll(type);
			foreach (Object val in array)
			{
				string name = val.name;
				dictionary[name] = FindBestAsset(dictionary, val, name);
			}
			dictionaryCache[type] = dictionary;
			return dictionary;
		}

		public static void Clear()
		{
			dictionaryCache.Clear();
		}

		public static void Clear<T>() where T : Object
		{
			dictionaryCache.Remove(typeof(T));
		}

		private static bool TryFindAssetOfComponent(Component unityObject, Type objectType, out Object asset)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Type type = ((object)unityObject).GetType();
			ClassMember classMember = ClassMember.GetClassMember(type);
			foreach (MemberBase member in classMember.Members)
			{
				if (member.MemberType == objectType && member.HasGetMethod)
				{
					asset = (Object)member.GetValue(unityObject);
					if (asset != (Object)null)
					{
						return Object.op_Implicit(asset);
					}
				}
			}
			asset = null;
			return false;
		}

		internal static bool TryFindAssetInSelfOrChildComponents(GameObject unityObject, Type objectType, out Object asset)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)unityObject))
			{
				asset = null;
				return false;
			}
			Component[] components = unityObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is Transform) && TryFindAssetOfComponent(val, objectType, out asset))
				{
					return Object.op_Implicit(asset);
				}
			}
			foreach (Transform item in unityObject.transform)
			{
				Transform val2 = item;
				if (TryFindAssetInSelfOrChildComponents(((Component)val2).gameObject, objectType, out asset))
				{
					return Object.op_Implicit(asset);
				}
			}
			asset = null;
			return false;
		}
	}
	internal class ClassMember
	{
		private static readonly Dictionary<Type, ClassMember> CachedClassMembers = new Dictionary<Type, ClassMember>();

		public List<MemberBase> Members { get; private set; } = new List<MemberBase>();

		public Type Type { get; private set; }

		private ClassMember(Type type, IEnumerable<FieldInfo> fieldInfos, IEnumerable<PropertyInfo> propertyInfos)
		{
			Type = type;
			foreach (FieldInfo fieldInfo in fieldInfos)
			{
				AddMember(new FieldMember(fieldInfo));
			}
			foreach (PropertyInfo propertyInfo in propertyInfos)
			{
				AddMember(new PropertyMember(propertyInfo));
			}
		}

		private void AddMember(MemberBase member)
		{
			if (member.IsClass && !(member.MemberType == typeof(string)) && (!(member.EnumeratedType != null) || (member.IsEnumeratedClass && !(member.EnumeratedType == typeof(string)))) && !member.HasCustomAttribute<NonSerializedAttribute>())
			{
				Members.Add(member);
			}
		}

		private static T[] GetMembersFromType<T>(Type type, Func<Type, T[]> getMembers)
		{
			T[] array = getMembers(type);
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				T[] second = getMembers(baseType);
				array = array.Union(second).ToArray();
				baseType = baseType.BaseType;
			}
			return array;
		}

		public static ClassMember GetClassMember(Type type)
		{
			if (CachedClassMembers.TryGetValue(type, out ClassMember value))
			{
				return value;
			}
			FieldInfo[] membersFromType = GetMembersFromType(type, (Type t) => t.GetFields(~BindingFlags.Static));
			PropertyInfo[] membersFromType2 = GetMembersFromType(type, (Type t) => t.GetProperties(~BindingFlags.Static));
			value = new ClassMember(type, membersFromType, membersFromType2);
			CachedClassMembers[type] = value;
			return value;
		}
	}
	public static class ExposedGameObjectExtension
	{
		public static GameObject OrNull(this GameObject @this)
		{
			if (!Object.op_Implicit((Object)(object)@this))
			{
				return null;
			}
			return @this;
		}

		public static T OrNull<T>(this T @this) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)@this))
			{
				return default(T);
			}
			return @this;
		}

		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T result = default(T);
			if (!gameObject.TryGetComponent<T>(ref result))
			{
				return gameObject.AddComponent<T>();
			}
			return result;
		}

		public static Component AddComponentCopy<T>(this GameObject gameObject, T duplicate) where T : Component
		{
			Component val = gameObject.AddComponent(((object)duplicate).GetType());
			PropertyInfo[] properties = ((object)duplicate).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				switch (propertyInfo.Name)
				{
				case "mesh":
					if (duplicate is MeshFilter)
					{
						continue;
					}
					break;
				case "material":
				case "materials":
					if (duplicate is Renderer)
					{
						continue;
					}
					break;
				case "bounds":
					if (duplicate is Renderer)
					{
						continue;
					}
					break;
				case "name":
				case "rayTracingMode":
				case "tag":
					continue;
				}
				if (propertyInfo.CanWrite && propertyInfo.GetMethod != null)
				{
					propertyInfo.SetValue(val, propertyInfo.GetValue(duplicate));
				}
			}
			FieldInfo[] fields = ((object)duplicate).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!(fieldInfo.Name == "rayTracingMode"))
				{
					fieldInfo.SetValue(val, fieldInfo.GetValue(duplicate));
				}
			}
			return val;
		}

		public static bool HasAnyComponent(this GameObject gameObject, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponent(type)))
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasAnyComponent(this GameObject gameObject, params string[] componentNames)
		{
			foreach (string text in componentNames)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponent(text)))
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasAllComponents(this GameObject gameObject, params string[] componentNames)
		{
			foreach (string text in componentNames)
			{
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(text)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasAllComponents(this GameObject gameObject, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(type)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasAnyComponentInChildren(this GameObject gameObject, bool includeInactive = false, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren(type, includeInactive)))
				{
					return true;
				}
			}
			return false;
		}

		public static Transform FindDeepChild(this GameObject gameObject, string childName, IterativeSearchType searchType = (IterativeSearchType)1)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return gameObject.transform.FindDeepChild(childName, searchType);
		}

		public static Transform FindDeepChild(this GameObject gameObject, IEnumerable<string> childNames, IterativeSearchType searchType = (IterativeSearchType)1)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Transform val = gameObject.transform;
			foreach (string childName in childNames)
			{
				val = val.FindDeepChild(childName, searchType);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return null;
				}
			}
			return val;
		}
	}
	public static class PrefabExtension
	{
		public static void FixReferences(this object objectToFix)
		{
			MockManager.FixReferences(objectToFix, 0);
		}

		public static void FixReferences(this GameObject gameObject)
		{
			gameObject.FixReferences(recursive: false);
		}

		public static void FixReferences(this ICollection<GameObject> gameObjects, bool recursive = false)
		{
			foreach (GameObject gameObject in gameObjects)
			{
				gameObject.FixReferences(recursive);
			}
		}

		public static void FixReferences(this GameObject gameObject, bool recursive)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			Component[] components = gameObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is Transform))
				{
					MockManager.FixReferences(val, 0);
				}
			}
			if (!recursive)
			{
				return;
			}
			List<Tuple<Transform, GameObject>> list = new List<Tuple<Transform, GameObject>>();
			foreach (Transform item in gameObject.transform)
			{
				Transform val2 = item;
				GameObject realPrefabFromMock = MockManager.GetRealPrefabFromMock<GameObject>((Object)(object)((Component)val2).gameObject);
				if (Object.op_Implicit((Object)(object)realPrefabFromMock))
				{
					list.Add(new Tuple<Transform, GameObject>(val2, realPrefabFromMock));
				}
				else
				{
					((Component)val2).gameObject.FixReferences(recursive: true);
				}
			}
			foreach (Tuple<Transform, GameObject> item2 in list)
			{
				MockManager.ReplaceMockGameObject(item2.Item1, item2.Item2, gameObject);
			}
		}

		public static void CloneFields(this GameObject gameObject, GameObject objectToClone)
		{
			Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>();
			Component[] componentsInChildren = objectToClone.GetComponentsInChildren<Component>();
			Component[] array = componentsInChildren;
			foreach (Component val in array)
			{
				FieldInfo[] fields = ((object)val).GetType().GetFields((BindingFlags)(-1));
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
					{
						dictionary.Add(fieldInfo, fieldInfo.GetValue(val));
					}
				}
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(((object)val).GetType())))
				{
					gameObject.AddComponent(((object)val).GetType());
				}
			}
			Component[] componentsInChildren2 = gameObject.GetComponentsInChildren<Component>();
			Component[] array2 = componentsInChildren2;
			foreach (Component val2 in array2)
			{
				FieldInfo[] fields2 = ((object)val2).GetType().GetFields((BindingFlags)(-1));
				foreach (FieldInfo fieldInfo2 in fields2)
				{
					if (dictionary.TryGetValue(fieldInfo2, out var value))
					{
						fieldInfo2.SetValue(val2, value);
					}
				}
			}
		}
	}
	public static class TransformExtensions
	{
		public static Transform FindDeepChild(this Transform transform, string childName, IterativeSearchType searchType = (IterativeSearchType)1)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Utils.FindChild(transform, childName, searchType);
		}
	}
	public static class StringExtensions
	{
		public static bool ContainsAny(this string str, params string[] substrings)
		{
			foreach (string value in substrings)
			{
				if (str.Contains(value))
				{
					return true;
				}
			}
			return false;
		}

		public static bool EndsWithAny(this string str, params string[] suffixes)
		{
			foreach (string value in suffixes)
			{
				if (str.EndsWith(value))
				{
					return true;
				}
			}
			return false;
		}

		public static bool StartsWithAny(this string str, params string[] prefixes)
		{
			foreach (string value in prefixes)
			{
				if (str.StartsWith(value))
				{
					return true;
				}
			}
			return false;
		}

		public static string RemoveSuffix(this string s, string suffix)
		{
			if (s.EndsWith(suffix))
			{
				return s.Substring(0, s.Length - suffix.Length);
			}
			return s;
		}

		public static string RemovePrefix(this string s, string prefix)
		{
			if (s.StartsWith(prefix))
			{
				return s.Substring(prefix.Length, s.Length - prefix.Length);
			}
			return s;
		}

		public static string CapitalizeFirstLetter(this string s)
		{
			if (s.Length == 0)
			{
				return s;
			}
			if (s.Length == 1)
			{
				return $"{char.ToUpper(s[0])}";
			}
			return char.ToUpper(s[0]) + s.Substring(1);
		}
	}
	internal class FieldMember : MemberBase
	{
		private readonly FieldInfo fieldInfo;

		public FieldMember(FieldInfo fieldInfo)
		{
			this.fieldInfo = fieldInfo;
			base.MemberType = fieldInfo.FieldType;
			base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object));
			base.IsClass = base.MemberType.IsClass;
			base.HasGetMethod = true;
			base.HasSetMethod = true;
			base.EnumeratedType = base.MemberType.GetEnumeratedType();
			base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false;
			base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false;
		}

		public override object GetValue(object obj)
		{
			try
			{
				return fieldInfo.GetValue(obj);
			}
			catch
			{
				return null;
			}
		}

		public override void SetValue(object obj, object value)
		{
			fieldInfo.SetValue(obj, value);
		}

		public override bool HasCustomAttribute<T>()
		{
			return fieldInfo.GetCustomAttribute<T>() != null;
		}
	}
	internal abstract class MemberBase
	{
		public bool HasGetMethod { get; protected set; }

		public bool HasSetMethod { get; protected set; }

		public Type MemberType { get; protected set; }

		public Type EnumeratedType { get; protected set; }

		public bool IsUnityObject { get; protected set; }

		public bool IsClass { get; protected set; }

		public bool IsEnumerableOfUnityObjects { get; protected set; }

		public bool IsEnumeratedClass { get; protected set; }

		public abstract object GetValue(object obj);

		public abstract void SetValue(object obj, object value);

		public abstract bool HasCustomAttribute<T>() where T : Attribute;
	}
	public class MockManager
	{
		private static class Patches
		{
			[HarmonyPatch(typeof(ZoneSystem), "Start")]
			[HarmonyPostfix]
			private static void ZoneSystem_Start(ZoneSystem __instance)
			{
				FixQueuedMaterials();
			}
		}

		private static MockManager _instance;

		[Obsolete("Legacy ValheimLib mock prefix. Use JVLMockPrefix \"JVLmock_\" instead.")]
		public const string MockPrefix = "VLmock_";

		public const string JVLMockPrefix = "JVLmock_";

		public const string JVLMockSeparator = "__";

		internal GameObject MockPrefabContainer;

		private Dictionary<string, GameObject> mockedPrefabs = new Dictionary<string, GameObject>();

		private static HashSet<Material> fixedMaterials = new HashSet<Material>();

		private static HashSet<Material> queuedToFixMaterials = new HashSet<Material>();

		private static bool allVanillaObjectsAvailable;

		public static MockManager Instance => _instance ?? (_instance = new MockManager());

		private static MethodInfo Object_IsPersistent { get; } = AccessTools.Method(typeof(Object), "IsPersistent", (Type[])null, (Type[])null);

		public static bool IsHeadless => (int)SystemInfo.graphicsDeviceType == 4;

		private MockManager()
		{
		}

		public void Init()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			MockPrefabContainer = new GameObject("MockPrefabs");
			MockPrefabContainer.transform.parent = Main.GetRootObject().transform;
			MockPrefabContainer.SetActive(false);
			Main.Mod.Harmony.PatchAll(typeof(Patches));
			Logger.LogDebugOnly("MockManager initialized.");
			AssetManager.Instance.Init();
		}

		public GameObject CreateMockedGameObject(string prefabName)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			string text = "JVLmock_" + prefabName;
			if (mockedPrefabs.TryGetValue(text, out GameObject value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			GameObject val = new GameObject(text);
			val.transform.parent = MockPrefabContainer.transform;
			val.SetActive(false);
			mockedPrefabs[text] = val;
			return val;
		}

		public T CreateMockedPrefab<T>(string prefabName) where T : Component
		{
			GameObject val = CreateMockedGameObject(prefabName);
			string name = ((Object)val).name;
			T orAddComponent = val.GetOrAddComponent<T>();
			if (!Object.op_Implicit((Object)(object)orAddComponent))
			{
				Logger.LogWarning($"Could not create mock for prefab {prefabName} of type {typeof(T)}");
				return default(T);
			}
			((Object)(object)orAddComponent).name = name;
			return orAddComponent;
		}

		public static T GetRealPrefabFromMock<T>(Object unityObject) where T : Object
		{
			return (T)(object)GetRealPrefabFromMock(unityObject, typeof(T));
		}

		public static Object GetRealPrefabFromMock(Object unityObject, Type mockObjectType)
		{
			if (!Object.op_Implicit(unityObject))
			{
				return null;
			}
			if (IsHeadless && mockObjectType == typeof(Texture))
			{
				return null;
			}
			if (!IsMockName(GetCleanedName(mockObjectType, unityObject.name), out string assetName, out List<string> childNames))
			{
				return null;
			}
			if (childNames.Count == 0 && TryGetAsset(mockObjectType, assetName, out Object asset))
			{
				return asset;
			}
			GameObject val = Cache.GetPrefab<GameObject>(assetName);
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new MockResolveException("GameObject with name '" + assetName + "' was not found.", assetName, mockObjectType);
			}
			if (childNames.Count > 0)
			{
				Transform val2 = val.FindDeepChild(childNames, (IterativeSearchType)1);
				if (!Object.op_Implicit((Object)(object)val2) || ((Object)val2).name != childNames.Last())
				{
					throw new MockResolveException("Child '" + childNames.Last() + "' not found with the specified path.", assetName, childNames, mockObjectType);
				}
				val = ((Component)val2).gameObject;
			}
			if (TryFindAssetInSelfOrChildComponents(val, mockObjectType, out asset))
			{
				return asset;
			}
			if (childNames.Count > 0)
			{
				string text = Utils.GetPath(val.transform).TrimStart(new char[1] { '/' });
				throw new MockResolveException(mockObjectType.Name + " not found at child '" + text + "'.", assetName, childNames, mockObjectType);
			}
			throw new MockResolveException(mockObjectType.Name + " not found at prefab '" + assetName + "'.", assetName, mockObjectType);
		}

		private static bool TryGetAsset(Type mockObjectType, string assetName, out Object asset)
		{
			asset = Cache.GetPrefab(mockObjectType, assetName);
			return Object.op_Implicit(asset);
		}

		internal static void FixReferences(object objectToFix, int depth)
		{
			if (depth == 5 || objectToFix == null)
			{
				return;
			}
			Type type = objectToFix.GetType();
			ClassMember classMember = ClassMember.GetClassMember(type);
			foreach (MemberBase member in classMember.Members)
			{
				FixMemberReferences(member, objectToFix, depth + 1);
			}
		}

		internal static void ReplaceMockGameObject(Transform child, GameObject realPrefab, GameObject parent)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (IsPersistent(parent))
			{
				Logger.LogWarning("Cannot replace mock child " + ((Object)child).name + " in persistent prefab " + ((Object)parent).name + ". Clone the prefab before replacing mocks, i.e. with PrefabManager.Instance.CreateClonedPrefab or ZoneManager.Instance.CreateLocationContainer for locations");
			}
			else
			{
				GameObject val = Object.Instantiate<GameObject>(realPrefab, parent.transform);
				((Object)val).name = ((Object)realPrefab).name;
				val.SetActive(((Component)child).gameObject.activeSelf);
				val.transform.position = ((Component)child).gameObject.transform.position;
				val.transform.rotation = ((Component)child).gameObject.transform.rotation;
				val.transform.localScale = ((Component)child).gameObject.transform.localScale;
				int siblingIndex = child.GetSiblingIndex();
				Object.DestroyImmediate((Object)(object)((Component)child).gameObject);
				val.transform.SetSiblingIndex(siblingIndex);
			}
		}

		private static bool IsPersistent(GameObject parent)
		{
			return (bool)Object_IsPersistent.Invoke(null, new object[1] { parent });
		}

		private static bool IsMockName(string name, out string assetName, out List<string> childNames)
		{
			if (name.StartsWith("JVLmock_", StringComparison.Ordinal))
			{
				string text = name.Substring("JVLmock_".Length);
				string[] array = text.Split(new string[1] { "__" }, StringSplitOptions.RemoveEmptyEntries);
				assetName = array[0];
				childNames = array.Skip(1).ToList();
				return true;
			}
			if (name.StartsWith("VLmock_", StringComparison.Ordinal))
			{
				assetName = name.Substring("VLmock_".Length);
				childNames = new List<string>();
				return true;
			}
			assetName = name;
			childNames = new List<string>();
			return false;
		}

		private static string GetCleanedName(Type objectType, string name)
		{
			if (objectType == typeof(Material))
			{
				return name.RemoveSuffix(" (Instance)");
			}
			if (objectType == typeof(Mesh))
			{
				return name.RemoveSuffix(" Instance");
			}
			return name;
		}

		private static void FixMemberReferences(MemberBase member, object objectToFix, int depth)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			if (member.MemberType == typeof(DropTable))
			{
				FixDropTable(member, objectToFix);
			}
			else if (member.IsUnityObject && member.HasGetMethod && member.HasSetMethod)
			{
				Object val = (Object)member.GetValue(objectToFix);
				Object realPrefabFromMock = GetRealPrefabFromMock(val, member.MemberType);
				if (Object.op_Implicit(realPrefabFromMock))
				{
					member.SetValue(objectToFix, realPrefabFromMock);
					return;
				}
				Material val2 = (Material)(object)((val is Material) ? val : null);
				if (val2 != null)
				{
					TryFixMaterial(val2);
				}
			}
			else if (member.IsEnumeratedClass && member.IsEnumerableOfUnityObjects && member.HasSetMethod)
			{
				bool isArray = member.MemberType.IsArray;
				bool flag = member.MemberType.IsGenericType && member.MemberType.GetGenericTypeDefinition() == typeof(List<>);
				bool flag2 = member.MemberType.IsGenericType && member.MemberType.GetGenericTypeDefinition() == typeof(HashSet<>);
				if (!(isArray || flag || flag2))
				{
					Logger.LogWarning($"Not fixing potential mock references for field {member.MemberType.Name} : {member.MemberType} is not supported.");
					return;
				}
				IEnumerable<Object> enumerable = (IEnumerable<Object>)member.GetValue(objectToFix);
				if (enumerable == null)
				{
					return;
				}
				List<Object> list = new List<Object>();
				bool flag3 = false;
				foreach (Object item in enumerable)
				{
					Object realPrefabFromMock2 = GetRealPrefabFromMock(item, member.EnumeratedType);
					list.Add(Object.op_Implicit(realPrefabFromMock2) ? realPrefabFromMock2 : item);
					flag3 = flag3 || Object.op_Implicit(realPrefabFromMock2);
					if (!Object.op_Implicit(realPrefabFromMock2))
					{
						Material val3 = (Material)(object)((item is Material) ? item : null);
						if (val3 != null)
						{
							TryFixMaterial(val3);
						}
					}
				}
				if (list.Count > 0 && flag3)
				{
					MethodInfo enumerableCast = ReflectionHelper.Cache.EnumerableCast;
					MethodInfo methodInfo = enumerableCast.MakeGenericMethod(member.EnumeratedType);
					object obj = methodInfo.Invoke(null, new object[1] { list });
					if (isArray)
					{
						MethodInfo enumerableToArray = ReflectionHelper.Cache.EnumerableToArray;
						MethodInfo methodInfo2 = enumerableToArray.MakeGenericMethod(member.EnumeratedType);
						object value = methodInfo2.Invoke(null, new object[1] { obj });
						member.SetValue(objectToFix, value);
					}
					else if (flag)
					{
						MethodInfo enumerableToList = ReflectionHelper.Cache.EnumerableToList;
						MethodInfo methodInfo3 = enumerableToList.MakeGenericMethod(member.EnumeratedType);
						object value2 = methodInfo3.Invoke(null, new object[1] { obj });
						member.SetValue(objectToFix, value2);
					}
					else if (flag2)
					{
						Type type = typeof(HashSet<>).MakeGenericType(member.EnumeratedType);
						object value3 = Activator.CreateInstance(type, obj);
						member.SetValue(objectToFix, value3);
					}
				}
			}
			else
			{
				if (member.IsEnumeratedClass)
				{
					if (member.MemberType.IsGenericType && member.MemberType.GetGenericTypeDefinition() == typeof(Dictionary<, >))
					{
						Logger.LogWarning("Not fixing potential mock references for field " + member.MemberType.Name + " : Dictionary is not supported.");
						return;
					}
					IEnumerable<object> enumerable2 = (IEnumerable<object>)member.GetValue(objectToFix);
					if (enumerable2 == null)
					{
						return;
					}
					{
						foreach (object item2 in enumerable2)
						{
							FixReferences(item2, depth);
						}
						return;
					}
				}
				if (member.IsClass && member.HasGetMethod)
				{
					FixReferences(member.GetValue(objectToFix), depth);
				}
			}
		}

		private static void FixDropTable(MemberBase member, object objectToFix)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			List<DropData> drops = ((DropTable)member.GetValue(objectToFix)).m_drops;
			for (int i = 0; i < drops.Count; i++)
			{
				DropData val = drops[i];
				GameObject realPrefabFromMock = MockManager.GetRealPrefabFromMock<GameObject>((Object)(object)val.m_item);
				if (Object.op_Implicit((Object)(object)realPrefabFromMock))
				{
					val.m_item = realPrefabFromMock;
				}
				drops[i] = val;
			}
		}

		private static void TryFixMaterial(Material material)
		{
			if (!IsHeadless && Object.op_Implicit((Object)(object)material) && !fixedMaterials.Contains(material) && !queuedToFixMaterials.Contains(material))
			{
				FixMaterial(material);
			}
		}

		private static void FixQueuedMaterials()
		{
			Cache.Clear<Texture>();
			allVanillaObjectsAvailable = true;
			foreach (Material item in new HashSet<Material>(queuedToFixMaterials))
			{
				queuedToFixMaterials.Remove(item);
				FixMaterial(item);
			}
		}

		private static void FixMaterial(Material material)
		{
			if (Object.op_Implicit((Object)(object)material) && !fixedMaterials.Contains(material))
			{
				bool flag = FixTextures(material);
				bool flag2 = true;
				if (!IsHeadless)
				{
					flag2 = FixShader(material);
				}
				if (flag && flag2)
				{
					fixedMaterials.Add(material);
				}
				else
				{
					queuedToFixMaterials.Add(material);
				}
			}
		}

		private static bool FixTextures(Material material)
		{
			bool result = true;
			int[] texturePropertyNameIDs = material.GetTexturePropertyNameIDs();
			foreach (int num in texturePropertyNameIDs)
			{
				Texture texture = material.GetTexture(num);
				if (!Object.op_Implicit((Object)(object)texture))
				{
					continue;
				}
				Texture realPrefabFromMock;
				try
				{
					realPrefabFromMock = MockManager.GetRealPrefabFromMock<Texture>((Object)(object)texture);
				}
				catch (MockResolveException ex)
				{
					if (allVanillaObjectsAvailable)
					{
						Logger.LogWarning(ex.Message);
					}
					result = false;
					continue;
				}
				if (Object.op_Implicit((Object)(object)realPrefabFromMock))
				{
					material.SetTexture(num, realPrefabFromMock);
				}
			}
			return result;
		}

		private static bool FixShader(Material material)
		{
			Shader shader = material.shader;
			if (!Object.op_Implicit((Object)(object)shader) || !IsMockName(((Object)shader).name, out string assetName, out List<string> _))
			{
				return true;
			}
			Shader prefab = Cache.GetPrefab<Shader>(assetName);
			if (Object.op_Implicit((Object)(object)prefab))
			{
				material.shader = prefab;
				return true;
			}
			if (allVanillaObjectsAvailable)
			{
				Logger.LogWarning("Could not find shader " + ((Object)shader).name);
			}
			return false;
		}

		private static bool TryFindAssetOfComponent(Component unityObject, Type objectType, out Object asset)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			Type type = ((object)unityObject).GetType();
			ClassMember classMember = ClassMember.GetClassMember(type);
			foreach (MemberBase member in classMember.Members)
			{
				if (member.MemberType == objectType && member.HasGetMethod)
				{
					asset = (Object)member.GetValue(unityObject);
					if (asset != (Object)null)
					{
						return Object.op_Implicit(asset);
					}
				}
			}
			asset = null;
			return false;
		}

		private static bool TryFindAssetInSelfOrChildComponents(GameObject unityObject, Type objectType, out Object asset)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			if ((Object)(object)unityObject == (Object)null)
			{
				asset = null;
				return false;
			}
			if (objectType.IsSubclassOf(typeof(Component)))
			{
				Component component = unityObject.GetComponent(objectType);
				if (Object.op_Implicit((Object)(object)component))
				{
					asset = (Object)(object)component;
					return true;
				}
			}
			Component[] components = unityObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is Transform) && TryFindAssetOfComponent(val, objectType, out asset))
				{
					return Object.op_Implicit(asset);
				}
			}
			foreach (Transform item in unityObject.transform)
			{
				Transform val2 = item;
				if (TryFindAssetInSelfOrChildComponents(((Component)val2).gameObject, objectType, out asset))
				{
					return Object.op_Implicit(asset);
				}
			}
			asset = null;
			return false;
		}
	}
	public class MockResolveException : Exception
	{
		public string FailedMockName { get; private set; }

		public string FailedMockPath { get; private set; }

		public Type MockType { get; private set; }

		[Obsolete("Use MockResolveException(string, string, Type) instead.")]
		public MockResolveException(string message, string failedMockName)
			: base(message)
		{
			FailedMockName = failedMockName;
		}

		public MockResolveException(string message, string failedMockName, Type mockType)
			: base(ConstructMessage(message, failedMockName, string.Empty, mockType))
		{
			FailedMockName = failedMockName;
			MockType = mockType;
		}

		public MockResolveException(string message, string failedMockName, IEnumerable<string> failedMockPath, Type mockType)
			: base(ConstructMessage(message, failedMockName, string.Join<string>("->", failedMockPath), mockType))
		{
			FailedMockName = failedMockName;
			FailedMockPath = string.Join<string>("->", failedMockPath);
			MockType = mockType;
		}

		private static string ConstructMessage(string message, string failedMockName, string failedMockPath, Type mockType)
		{
			if (string.IsNullOrEmpty(failedMockPath))
			{
				return "Mock " + mockType.Name + " '" + failedMockName + "' could not be resolved. " + message;
			}
			return "Mock " + mockType.Name + " at '" + failedMockName + "' with child path '" + failedMockPath + "' could not be resolved. " + message;
		}
	}
	internal class PropertyMember : MemberBase
	{
		private readonly PropertyInfo propertyInfo;

		public PropertyMember(PropertyInfo propertyInfo)
		{
			this.propertyInfo = propertyInfo;
			base.MemberType = propertyInfo.PropertyType;
			base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object));
			base.IsClass = base.MemberType.IsClass;
			base.HasGetMethod = propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.GetMethod != null;
			base.HasSetMethod = propertyInfo.SetMethod != null;
			base.EnumeratedType = base.MemberType.GetEnumeratedType();
			base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false;
			base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false;
		}

		public override object GetValue(object obj)
		{
			try
			{
				return propertyInfo.GetValue(obj);
			}
			catch
			{
				return null;
			}
		}

		public override void SetValue(object obj, object value)
		{
			propertyInfo.SetValue(obj, value);
		}

		public override bool HasCustomAttribute<T>()
		{
			return propertyInfo.GetCustomAttribute<T>() != null;
		}
	}
	public static class ReflectionHelper
	{
		public static class Cache
		{
			private static MethodInfo _enumerableToArray;

			private static MethodInfo _enumerableToList;

			private static MethodInfo _enumerableCast;

			public static MethodInfo EnumerableToArray
			{
				get
				{
					if (_enumerableToArray == null)
					{
						_enumerableToArray = typeof(Enumerable).GetMethod("ToArray", (BindingFlags)(-1));
					}
					return _enumerableToArray;
				}
			}

			public static MethodInfo EnumerableToList
			{
				get
				{
					if (_enumerableToList == null)
					{
						_enumerableToList = typeof(Enumerable).GetMethod("ToList", (BindingFlags)(-1));
					}
					return _enumerableToList;
				}
			}

			public static MethodInfo EnumerableCast
			{
				get
				{
					if (_enumerableCast == null)
					{
						_enumerableCast = typeof(Enumerable).GetMethod("Cast", (BindingFlags)(-1));
					}
					return _enumerableCast;
				}
			}
		}

		public const BindingFlags AllBindingFlags = (BindingFlags)(-1);

		public static bool IsSameOrSubclass(this Type type, Type @base)
		{
			if (!type.IsSubclassOf(@base))
			{
				return type == @base;
			}
			return true;
		}

		public static bool HasImplementedRawGeneric(this Type type, Type generic)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			if (generic == null)
			{
				throw new ArgumentNullException("generic");
			}
			if (type.GetInterfaces().Any(IsTheRawGenericType))
			{
				return true;
			}
			while (type != null && type != typeof(object))
			{
				if (IsTheRawGenericType(type))
				{
					return true;
				}
				type = type.BaseType;
			}
			return false;
			bool IsTheRawGenericType(Type test)
			{
				return generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test);
			}
		}

		public static bool IsEnumerable(this Type type)
		{
			if (typeof(IEnumerable).IsAssignableFrom(type))
			{
				return type != typeof(string);
			}
			return false;
		}

		public static Type GetEnumeratedType(this Type type)
		{
			object obj = type?.GetElementType();
			if (obj == null)
			{
				if (!typeof(IEnumerable).IsAssignableFrom(type))
				{
					return null;
				}
				obj = type.GetGenericArguments().FirstOrDefault();
			}
			return (Type)obj;
		}

		public static Type GetCallingType()
		{
			return (new StackTrace().GetFrames() ?? Array.Empty<StackFrame>()).First((StackFrame x) => x.GetMethod().ReflectedType?.Assembly != typeof(Logger).Assembly).GetMethod().ReflectedType;
		}

		public static Assembly GetCallingAssembly()
		{
			return (new StackTrace().GetFrames() ?? Array.Empty<StackFrame>()).First((StackFrame x) => x.GetMethod().ReflectedType?.Assembly != typeof(Logger).Assembly).GetMethod().ReflectedType?.Assembly;
		}

		public static object InvokePrivate(object instance, string name, object[] args = null)
		{
			MethodInfo method = instance.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.NonPublic);
			if (method == null)
			{
				Type[] types = ((args == null) ? Type.EmptyTypes : args.Select((object arg) => arg.GetType()).ToArray());
				method = instance.GetType().GetMethod(name, types);
			}
			if (method == null)
			{
				Logger.LogError("Method " + name + " does not exist on type: " + instance.GetType());
				return null;
			}
			return method.Invoke(instance, args);
		}

		public static T GetPrivateProperty<T>(object instance, string name)
		{
			PropertyInfo property = instance.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic);
			if (property == null)
			{
				Logger.LogError("Property " + name + " does not exist on type: " + instance.GetType());
				return default(T);
			}
			return (T)property.GetValue(instance);
		}

		public static T GetPrivateField<T>(object instance, string name)
		{
			FieldInfo field = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				Logger.LogError("Variable " + name + " does not exist on type: " + instance.GetType());
				return default(T);
			}
			return (T)field.GetValue(instance);
		}

		public static T GetPrivateField<T>(Type type, string name)
		{
			FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.NonPublic);
			if (field == null)
			{
				Logger.LogError("Variable " + name + " does not exist on type: " + type);
				return default(T);
			}
			return (T)field.GetValue(null);
		}

		public static void SetPrivateField(object instance, string name, object value)
		{
			FieldInfo field = instance.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				Logger.LogError("Variable " + name + " does not exist on type: " + instance.GetType());
			}
			else
			{
				field.SetValue(instance, value);
			}
		}
	}
}
namespace LocalizationManager
{
	[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 ConditionalWeakTable<Localization, string> localizationLanguage;

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

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		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 && !t.IsAbstract && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

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

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

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

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' });
				string text = ((array.Length <= 1) ? array[0] : array[1]);
				if (dictionary.ContainsKey(text))
				{
					Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
				}
				else
				{
					dictionary[text] = item;
				}
			}
			byte[] array2 = LoadTranslationFromAssembly("English");
			if (array2 == 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> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for Mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.ContainsKey(language))
				{
					text2 = File.ReadAllText(dictionary[language]);
				}
				else
				{
					byte[] array3 = LoadTranslationFromAssembly(language);
					if (array3 != null)
					{
						text2 = Encoding.UTF8.GetString(array3);
					}
				}
			}
			if (text2 == null && dictionary.ContainsKey("English"))
			{
				text2 = File.ReadAllText(dictionary["English"]);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string> { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

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

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
}
namespace ItemManager
{
	[PublicAPI]
	public enum CraftingTable
	{
		Disabled,
		Inventory,
		[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,
		Custom
	}
	[PublicAPI]
	public enum ConversionPiece
	{
		Disabled,
		[InternalName("smelter")]
		Smelter,
		[InternalName("charcoal_kiln")]
		CharcoalKiln,
		[InternalName("blastfurnace")]
		BlastFurnace,
		[InternalName("windmill")]
		Windmill,
		[InternalName("piece_spinningwheel")]
		SpinningWheel,
		[InternalName("eitrrefinery")]
		EitrRefinery,
		Custom
	}
	public class InternalName : Attribute
	{
		public readonly string internalName;

		public InternalName(string internalName)
		{
			this.internalName = internalName;
		}
	}
	[PublicAPI]
	public class RequiredResourceList
	{
		public readonly List<Requirement> Requirements = new List<Requirement>();

		public bool Free;

		public void Add(string itemName, int amount, int quality = 0)
		{
			Requirements.Add(new Requirement
			{
				itemName = itemName,
				amount = amount,
				quality = quality
			});
		}

		public void Add(string itemName, ConfigEntry<int> amountConfig, int quality = 0)
		{
			Requirements.Add(new Requirement
			{
				itemName = itemName,
				amountConfig = amountConfig,
				quality = quality
			});
		}
	}
	[PublicAPI]
	public class CraftingStationList
	{
		public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>();

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

		public void Add(string customTable, int level)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = CraftingTable.Custom,
				level = level,
				custom = customTable
			});
		}
	}
	[PublicAPI]
	public class ItemRecipe
	{
		public readonly RequiredResourceList RequiredItems = new RequiredResourceList();

		public readonly RequiredResourceList RequiredUpgradeItems = new RequiredResourceList();

		public readonly CraftingStationList Crafting = new CraftingStationList();

		public int CraftAmount = 1;

		public bool RequireOnlyOneIngredient;

		public float QualityResultAmountMultiplier = 1f;

		public ConfigEntryBase? RecipeIsActive;
	}
	[PublicAPI]
	public class Trade
	{
		public Trader Trader;

		public uint Price;

		public uint Stack = 1u;

		public string? RequiredGlobalKey;
	}
	[PublicAPI]
	[Flags]
	public enum Trader
	{
		None = 0,
		Haldor = 1,
		Hildir = 2
	}
	public struct Requirement
	{
		public string itemName;

		public int amount;

		public ConfigEntry<int>? amountConfig;

		[Description("Set to a non-zero value to apply the requirement only for a specific quality")]
		public int quality;
	}
	public struct CraftingStationConfig
	{
		public CraftingTable Table;

		public int level;

		public string? custom;
	}
	[Flags]
	public enum Configurability
	{
		Disabled = 0,
		Recipe = 1,
		Stats = 2,
		Drop = 4,
		Trader = 8,
		Full = 0xF
	}
	[PublicAPI]
	public class DropTargets
	{
		public readonly List<DropTarget> Drops = new List<DropTarget>();

		public void Add(string creatureName, float chance, int min = 1, int? max = null, bool levelMultiplier = true)
		{
			Drops.Add(new DropTarget
			{
				creature = creatureName,
				chance = chance,
				min = min,
				max = (max ?? min),
				levelMultiplier = levelMultiplier
			});
		}
	}
	public struct DropTarget
	{
		public string creature;

		public int min;

		public int max;

		public float chance;

		public bool levelMultiplier;
	}
	public enum Toggle
	{
		On = 1,
		Off = 0
	}
	[PublicAPI]
	public class Item
	{
		private class ItemConfig
		{
			public ConfigEntry<string>? craft;

			public ConfigEntry<string>? upgrade;

			public ConfigEntry<CraftingTable> table;

			public ConfigEntry<int> tableLevel;

			public ConfigEntry<string> customTable;

			public ConfigEntry<int>? maximumTableLevel;

			public ConfigEntry<Toggle> requireOneIngredient;

			public ConfigEntry<float> qualityResultAmountMultiplier;
		}

		private class TraderConfig
		{
			public ConfigEntry<Trader> trader;

			public ConfigEntry<uint> price;

			public ConfigEntry<uint> stack;

			public ConfigEntry<string> requiredGlobalKey;
		}

		private class RequirementQuality
		{
			public int quality;
		}

		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order;

			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			public string? Category;

			[UsedImplicitly]
			public Action<ConfigEntryBase>? CustomDrawer;

			public Func<bool>? browsability;
		}

		[PublicAPI]
		public enum DamageModifier
		{
			Normal,
			Resistant,
			Weak,
			Immune,
			Ignore,
			VeryResistant,
			VeryWeak,
			None
		}

		private delegate void setDmgFunc(ref DamageTypes dmg, float value);

		private class SerializedRequirements
		{
			public readonly List<Requirement> Reqs;

			public SerializedRequirements(List<Requirement> reqs)
			{
				Reqs = reqs;
			}

			public SerializedRequirements(string reqs)
				: this(reqs.Split(new char[1] { ',' }).Select(delegate(string r)
				{
					string[] array = r.Split(new char[1] { ':' });
					int result;
					int result2;
					return new Requirement
					{
						itemName = array[0],
						amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
						quality = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0)
					};
				}).ToList())
			{
			}

			public override string ToString()
			{
				return string.Join(",", Reqs.Select((Requirement r) => $"{r.itemName}:{r.amount}" + ((r.quality > 0) ? $":{r.quality}" : "")));
			}

			public static ItemDrop? fetchByName(ObjectDB objectDB, string name)
			{
				GameObject itemPrefab = objectDB.GetItemPrefab(name);
				ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("The required item '" + name + "' does not exist."));
				}
				return val;
			}

			public static Requirement[] toPieceReqs(ObjectDB objectDB, SerializedRequirements craft, SerializedRequirements upgrade)
			{
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0178: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0185: Unknown result type (might be due to invalid IL or missing references)
				//IL_018c: Unknown result type (might be due to invalid IL or missing references)
				//IL_018f: Expected O, but got Unknown
				//IL_0194: Expected O, but got Unknown
				//IL_011c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0125: Expected O, but got Unknown
				Dictionary<string, Requirement> dictionary = craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func<Requirement, string>)((Requirement r) => r.itemName), (Func<Requirement, Requirement>)delegate(Requirement r)
				{
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_003e: Expected O, but got Unknown
					ItemDrop val6 = ResItem(r);
					return (val6 != null) ? new Requirement
					{
						m_amount = (r.amountConfig?.Value ?? r.amount),
						m_resItem = val6,
						m_amountPerLevel = 0
					} : ((Requirement)null);
				});
				List<Requirement> list = dictionary.Values.Where((Requirement v) => v != null).ToList();
				foreach (Requirement item in upgrade.Reqs.Where((Requirement r) => r.itemName != ""))
				{
					if (item.quality > 0)
					{
						ItemDrop val = ResItem(item);
						if (val != null)
						{
							Requirement val2 = new Requirement
							{
								m_resItem = val,
								m_amountPerLevel = (item.amountConfig?.Value ?? item.amount),
								m_amount = 0
							};
							list.Add(val2);
							requirementQuality.Add(val2, new RequirementQuality
							{
								quality = item.quality
							});
						}
						continue;
					}
					if (!dictionary.TryGetValue(item.itemName, out var value) || value == null)
					{
						ItemDrop val3 = ResItem(item);
						if (val3 != null)
						{
							string itemName = item.itemName;
							Requirement val4 = new Requirement
							{
								m_resItem = val3,
								m_amount = 0
							};
							Requirement val5 = val4;
							dictionary[itemName] = val4;
							value = val5;
							list.Add(value);
						}
					}
					if (value != null)
					{
						value.m_amountPerLevel = item.amountConfig?.Value ?? item.amount;
					}
				}
				return list.ToArray();
				ItemDrop? ResItem(Requirement r)
				{
					return fetchByName(objectDB, r.itemName);
				}
			}
		}

		private class SerializedDrop
		{
			public readonly List<DropTarget> Drops;

			public SerializedDrop(List<DropTarget> drops)
			{
				Drops = drops;
			}

			public SerializedDrop(string drops)
			{
				Drops = ((drops == "") ? ((IEnumerable<string>)Array.Empty<string>()) : ((IEnumerable<string>)drops.Split(new char[1] { ',' }))).Select(delegate(string r)
				{
					string[] array = r.Split(new char[1] { ':' });
					if (array.Length <= 2 || !int.TryParse(array[2], out var result))
					{
						result = 1;
					}
					if (array.Length <= 3 || !int.TryParse(array[3], out var result2))
					{
						result2 = result;
					}
					bool levelMultiplier = array.Length <= 4 || array[4] != "0";
					float result3;
					return new DropTarget
					{
						creature = array[0],
						chance = ((array.Length > 1 && float.TryParse(array[1], out result3)) ? result3 : 1f),
						min = result,
						max = result2,
						levelMultiplier = levelMultiplier
					};
				}).ToList();
			}

			public override string ToString()
			{
				return string.Join(",", Drops.Select((DropTarget r) => $"{r.creature}:{r.chance.ToString(CultureInfo.InvariantCulture)}:{r.min}:" + ((r.min == r.max) ? "" : $"{r.max}") + (r.levelMultiplier ? "" : ":0")));
			}

			private static Character? fetchByName(ZNetScene netScene, string name)
			{
				GameObject prefab = netScene.GetPrefab(name);
				Character val = ((prefab != null) ? prefab.GetComponent<Character>() : null);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("The drop target character '" + name + "' does not exist."));
				}
				return val;
			}

			public Dictionary<Character, Drop> toCharacterDrops(ZNetScene netScene, GameObject item)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: 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_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Expected O, but got Unknown
				Dictionary<Character, Drop> dictionary = new Dictionary<Character, Drop>();
				foreach (DropTarget drop in Drops)
				{
					Character val = fetchByName(netScene, drop.creature);
					if (val != null)
					{
						dictionary[val] = new Drop
						{
							m_prefab = item,
							m_amountMin = drop.min,
							m_amountMax = drop.max,
							m_chance = drop.chance,
							m_levelMultiplier = drop.levelMultiplier
						};
					}
				}
				return dictionary;
			}
		}

		public enum RecipesEnabled
		{
			False,
			True,
			Mixed
		}

		private static readonly List<Item> registeredItems = new List<Item>();

		private static readonly Dictionary<ItemDrop, Item> itemDropMap = new Dictionary<ItemDrop, Item>();

		private static Dictionary<Item, Dictionary<string, List<Recipe>>> activeRecipes = new Dictionary<Item, Dictionary<string, List<Recipe>>>();

		private static Dictionary<Recipe, ConfigEntryBase?> hiddenCraftRecipes = new Dictionary<Recipe, ConfigEntryBase>();

		private static Dictionary<Recipe, ConfigEntryBase?> hiddenUpgradeRecipes = new Dictionary<Recipe, ConfigEntryBase>();

		private static Dictionary<Item, Dictionary<string, ItemConfig>> itemCraftConfigs = new Dictionary<Item, Dictionary<string, ItemConfig>>();

		private static Dictionary<Item, ConfigEntry<string>> itemDropConfigs = new Dictionary<Item, ConfigEntry<string>>();

		private Dictionary<CharacterDrop, Drop> characterDrops = new Dictionary<CharacterDrop, Drop>();

		private readonly Dictionary<ConfigEntryBase, Action> statsConfigs = new Dictionary<ConfigEntryBase, Action>();

		private static readonly ConditionalWeakTable<Requirement, RequirementQuality> requirementQuality = new ConditionalWeakTable<Requirement, RequirementQuality>();

		public static Configurability DefaultConfigurability = Configurability.Full;

		public Configurability? Configurable;

		private Configurability configurationVisible = Configurability.Full;

		private TraderConfig? traderConfig;

		public readonly GameObject Prefab;

		[Description("Specifies the maximum required crafting station level to upgrade and repair the item.\nDefault is calculated from crafting station level and maximum quality.")]
		public int MaximumRequiredStationLevel = int.MaxValue;

		[Description("Assigns the item as a drop item to a creature.\nUses a creature name, a drop chance and a minimum and maximum amount.")]
		public readonly DropTargets DropsFrom = new DropTargets();

		[Description("Configures whether the item can be bought at the trader.\nDon't forget to set cost to something above 0 or the item will be sold for free.")]
		public readonly Trade Trade = new Trade();

		internal List<Conversion> Conversions = new List<Conversion>();

		internal List<ItemConversion> conversions = new List<ItemConversion>();

		public Dictionary<string, ItemRecipe> Recipes = new Dictionary<string, ItemRecipe>();

		private LocalizeKey? _name;

		private LocalizeKey? _description;

		private static object? configManager;

		private static Localization? _english;

		private static BaseUnityPlugin? _plugin;

		private static bool hasConfigSync = true;

		private static object? _configSync;

		private Configurability configurability => Configurable ?? DefaultConfigurability;

		[Description("Specifies the resources needed to craft the item.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the item should need.")]
		public RequiredResourceList RequiredItems => this[""].RequiredItems;

		[Description("Specifies the resources needed to upgrade the item.\nUse .Add to add resources with their internal ID and an amount. This amount will be multipled by the item quality level.\nUse one .Add for each resource type the upgrade should need.")]
		public RequiredResourceList RequiredUpgradeItems => this[""].RequiredUpgradeItems;

		[Description("Specifies the crafting station needed to craft the item.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.\nUse one .Add for each crafting station.")]
		public CraftingStationList Crafting => this[""].Crafting;

		[Description("Specifies a config entry which toggles whether a recipe is active.")]
		public ConfigEntryBase? RecipeIsActive
		{
			get
			{
				return this[""].RecipeIsActive;
			}
			set
			{
				this[""].RecipeIsActive = value;
			}
		}

		[Description("Specifies the number of items that should be given to the player with a single craft of the item.\nDefaults to 1.")]
		public int CraftAmount
		{
			get
			{
				return this[""].CraftAmount;
			}
			set
			{
				this[""].CraftAmount = value;
			}
		}

		public bool RequireOnlyOneIngredient
		{
			get
			{
				return this[""].RequireOnlyOneIngredient;
			}
			set
			{
				this[""].RequireOnlyOneIngredient = value;
			}
		}

		public float QualityResultAmountMultiplier
		{
			get
			{
				return this[""].QualityResultAmountMultiplier;
			}
			set
			{
				this[""].QualityResultAmountMultiplier = value;
			}
		}

		public ItemRecipe this[string name]
		{
			get
			{
				if (Recipes.TryGetValue(name, out ItemRecipe value))
				{
					return value;
				}
				return Recipes[name] = new ItemRecipe();
			}
		}

		public LocalizeKey Name
		{
			get
			{
				LocalizeKey name = _name;
				if (name != null)
				{
					return name;
				}
				SharedData shared = Prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
				if (shared.m_name.StartsWith("$"))
				{
					_name = new LocalizeKey(shared.m_name);
				}
				else
				{
					string text = "$item_" + ((Object)Prefab).name.Replace(" ", "_");
					_name = new LocalizeKey(text).English(shared.m_name);
					shared.m_name = text;
				}
				return _name;
			}
		}

		public LocalizeKey Description
		{
			get
			{
				LocalizeKey description = _description;
				if (description != null)
				{
					return description;
				}
				SharedData shared = Prefab.GetComponent<ItemDrop>().m_itemData.m_shared;
				if (shared.m_description.StartsWith("$"))
				{
					_description = new LocalizeKey(shared.m_description);
				}
				else
				{
					string text = "$itemdesc_" + ((Object)Prefab).name.Replace(" ", "_");
					_description = new LocalizeKey(text).English(shared.m_description);
					shared.m_description = text;
				}
				return _description;
			}
		}

		private static Localization english => _english ?? (_english = LocalizationCache.ForLanguage("English"));

		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 && !t.IsAbstract && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		private static object? configSync
		{
			get
			{
				if (_configSync == null && hasConfigSync)
				{
					Type type = Assembly.GetExecutingAssembly().GetType("ServerSync.ConfigSync");
					if ((object)type != null)
					{
						_configSync = Activator.CreateInstance(type, plugin.Info.Metadata.GUID + " ItemManager");
						type.GetField("CurrentVersion").SetValue(_configSync, plugin.Info.Metadata.Version.ToString());
						type.GetProperty("IsLocked").SetValue(_configSync, true);
					}
					else
					{
						hasConfigSync = false;
					}
				}
				return _configSync;
			}
		}

		public static List<Item> RegisteredItems => registeredItems;

		public ItemData ItemData => Prefab.GetComponent<ItemDrop>().m_itemData;

		public SharedData ItemSharedData => ItemData.m_shared;

		public Item(string assetBundleFileName, string prefabName, string folderName = "assets")
			: this(PrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName)
		{
		}

		public Item(AssetBundle bundle, string prefabName)
			: this(PrefabManager.RegisterPrefab(bundle, prefabName, addToObjectDb: true), skipRegistering: true)
		{
		}

		public Item(GameObject prefab, bool skipRegistering = false)
		{
			if (!skipRegistering)
			{
				PrefabManager.RegisterPrefab(prefab, addToObjectDb: true);
			}
			Prefab = prefab;
			registeredItems.Add(this);
			itemDropMap[Prefab.GetComponent<ItemDrop>()] = this;
			Prefab.GetComponent<ItemDrop>().m_itemData.m_dropPrefab = Prefab;
		}

		public void ToggleConfigurationVisibility(Configurability visible)
		{
			configurationVisible = visible;
			if (itemDropConfigs.TryGetValue(this, out ConfigEntry<string> value))
			{
				Toggle((ConfigEntryBase)(object)value, Configurability.Drop);
			}
			if (itemCraftConfigs.TryGetValue(this, out Dictionary<string, ItemConfig> value2))
			{
				foreach (ItemConfig value4 in value2.Values)
				{
					ToggleObj(value4, Configurability.Recipe);
				}
			}
			foreach (Conversion conversion in Conversions)
			{
				if (conversion.config != null)
				{
					ToggleObj(conversion.config, Configurability.Recipe);
				}
			}
			foreach (KeyValuePair<ConfigEntryBase, Action> statsConfig in statsConfigs)
			{
				Toggle(statsConfig.Key, Configurability.Stats);
				if ((visible & Configurability.Stats) != Configurability.Disabled)
				{
					statsConfig.Value();
				}
			}
			reloadConfigDisplay();
			void Toggle(ConfigEntryBase cfg, Configurability check)
			{
				object[] tags = cfg.Description.Tags;
				foreach (object obj in tags)
				{
					if (obj is ConfigurationManagerAttributes configurationManagerAttributes)
					{
						configurationManagerAttributes.Browsable = (visible & check) != Configurability.Disabled && (configurationManagerAttributes.browsability == null || configurationManagerAttributes.browsability());
					}
				}
			}
			void ToggleObj(object obj, Configurability check)
			{
				FieldInfo[] fields = obj.GetType().GetFields();
				foreach (FieldInfo fieldInfo in fields)
				{
					object? value3 = fieldInfo.GetValue(obj);
					ConfigEntryBase val = (ConfigEntryBase)((value3 is ConfigEntryBase) ? value3 : null);
					if (val != null)
					{
						Toggle(val, check);
					}
				}
			}
		}

		internal static void reloadConfigDisplay()
		{
			object obj = configManager?.GetType().GetProperty("DisplayingWindow").GetValue(configManager);
			if (obj is bool && (bool)obj)
			{
				configManager.GetType().GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>());
			}
		}

		private void UpdateItemTableConfig(string recipeKey, CraftingTable table, string customTableValue)
		{
			if (activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(recipeKey, out List<Recipe> value))
			{
				value.First().m_enabled = table != CraftingTable.Disabled;
				if ((uint)table <= 1u)
				{
					value.First().m_craftingStation = null;
				}
				else if (table == CraftingTable.Custom)
				{
					Recipe obj = value.First();
					GameObject prefab = ZNetScene.instance.GetPrefab(customTableValue);
					obj.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
				}
				else
				{
					value.First().m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName(table)).GetComponent<CraftingStation>();
				}
			}
		}

		private void UpdateCraftConfig(string recipeKey, SerializedRequirements craftRequirements, SerializedRequirements upgradeRequirements)
		{
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !activeRecipes.ContainsKey(this) || !activeRecipes[this].TryGetValue(recipeKey, out List<Recipe> value))
			{
				return;
			}
			foreach (Recipe item in value)
			{
				item.m_resources = SerializedRequirements.toPieceReqs(ObjectDB.instance, craftRequirements, upgradeRequirements);
			}
		}

		internal static void Patch_FejdStartup()
		{
			//IL_0eb6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ebb: Unknown result type (might be due to invalid IL or missing references)
			//IL_21af: Unknown result type (might be due to invalid IL or missing references)
			//IL_21b9: Expected O, but got Unknown
			//IL_0f81: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f84: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fda: Expected I4, but got Unknown
			//IL_0b9b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba5: Expected O, but got Unknown
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Expected O, but got Unknown
			//IL_1111: Unknown result type (might be due to invalid IL or missing references)
			//IL_1114: Unknown result type (might be due to invalid IL or missing references)
			//IL_1116: Invalid comparison between Unknown and I4
			//IL_1118: Unknown result type (might be due to invalid IL or missing references)
			//IL_111c: Invalid comparison between Unknown and I4
			//IL_0cc4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cce: Expected O, but got Unknown
			//IL_0d6f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d79: Expected O, but got Unknown
			//IL_111e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1122: Invalid comparison between Unknown and I4
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Expected O, but got Unknown
			//IL_0e23: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e2d: Expected O, but got Unknown
			//IL_1322: Unknown result type (might be due to invalid IL or missing references)
			//IL_1325: Unknown result type (might be due to invalid IL or missing references)
			//IL_1327: Invalid comparison between Unknown and I4
			//IL_1329: Unknown result type (might be due to invalid IL or missing references)
			//IL_132d: Unknown result type (might be due to invalid IL or missing references)
			//IL_132f: Invalid comparison between Unknown and I4
			//IL_0541: Unknown result type (might be due to invalid IL or missing references)
			//IL_054b: Expected O, but got Unknown
			//IL_1331: Unknown result type (might be due to invalid IL or missing references)
			//IL_1335: Invalid comparison between Unknown and I4
			//IL_140c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1411: Unknown result type (might be due to invalid IL or missing references)
			//IL_1413: Unknown result type (might be due to invalid IL or missing references)
			//IL_1416: Invalid comparison between Unknown and I4
			//IL_1418: Unknown result type (might be due to invalid IL or missing references)
			//IL_141c: Invalid comparison between Unknown and I4
			//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0702: Expected O, but got Unknown
			//IL_0659: Unknown result type (might be due to invalid IL or missing references)
			//IL_0663: Expected O, but got Unknown
			//IL_148c: Unknown result type (might be due to invalid IL or missing references)
			//IL_148f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1491: Invalid comparison between Unknown and I4
			//IL_0802: Unknown result type (might be due to invalid IL or missing references)
			//IL_080c: Expected O, but got Unknown
			//IL_1493: Unknown result type (might be due to invalid IL or missing references)
			//IL_1497: Unknown result type (might be due to invalid IL or missing references)
			//IL_1499: Invalid comparison between Unknown and I4
			//IL_149b: Unknown result type (might be due to invalid IL or missing references)
			//IL_149f: Invalid comparison between Unknown and I4
			//IL_15dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_15e0: Invalid comparison between Unknown and I4
			//IL_17e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_17e9: Invalid comparison between Unknown and I4
			//IL_18b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_18b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_18bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_18bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_18c1: Invalid comparison between Unknown and I4
			//IL_1931: Unknown result type (might be due to invalid IL or missing references)
			//IL_1934: Unknown result type (might be due to invalid IL or missing references)
			//IL_1936: Invalid comparison between Unknown and I4
			//IL_1552: Unknown result type (might be due to invalid IL or missing references)
			//IL_1557: Unknown result type (might be due to invalid IL or missing references)
			//IL_1938: Unknown result type (might be due to invalid IL or missing references)
			//IL_193c: Invalid comparison between Unknown and I4
			//IL_193e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1942: Invalid comparison between Unknown and I4
			//IL_1dbd: Unknown result type (might be due to invalid IL or missing references)
			//IL_1dc0: Invalid comparison between Unknown and I4
			Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager");
			if (DefaultConfigurability != Configurability.Disabled)
			{
				bool saveOnConfigSet = plugin.Config.SaveOnConfigSet;
				plugin.Config.SaveOnConfigSet = false;
				foreach (Item item3 in registeredItems.Where((Item i) => i.configurability != Configurability.Disabled))
				{
					Item item = item3;
					string name = item.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name;
					string englishName = new Regex("['\\[\"\\]]").Replace(english.Localize(name), "").Trim();
					string localizedName = Localization.instance.Localize(name).Trim();
					int order = 0;
					if ((item.configurability & Configurability.Recipe) != Configurability.Disabled)
					{
						itemCraftConfigs[item] = new Dictionary<string, ItemConfig>();
						foreach (string item4 in item.Recipes.Keys.DefaultIfEmpty(""))
						{
							string configKey = item4;
							string text = ((configKey == "") ? "" : (" (" + configKey + ")"));
							if (!item.Recipes.ContainsKey(configKey) || item.Recipes[configKey].Crafting.Stations.Count <= 0)
							{
								continue;
							}
							ItemConfig itemConfig = (itemCraftConfigs[item][configKey] = new ItemConfig());
							ItemConfig cfg = itemConfig;
							List<ConfigurationManagerAttributes> hideWhenNoneAttributes = new List<ConfigurationManagerAttributes>()