Decompiled source of RestlessCook v0.1.9

RestlessCook.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("RestlessCook")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.9.0")]
[assembly: AssemblyInformationalVersion("0.1.9+ad4a593175051de8fe6db4b8cd706e4428a6234b")]
[assembly: AssemblyProduct("RestlessCook")]
[assembly: AssemblyTitle("RestlessCook")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.9.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 RestlessCook
{
	internal static class CookIcons
	{
		private static readonly Dictionary<string, Sprite> Cache = new Dictionary<string, Sprite>();

		private static MethodInfo? _loadImage;

		private static bool _searched;

		public static Sprite? Sprite(string id)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			string text = id.Replace('_', '-');
			if (Cache.TryGetValue(text, out Sprite value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Texture2D val = Texture(text);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
			((Object)value).name = text;
			Cache[text] = value;
			return value;
		}

		private static Texture2D? Texture(string key)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			Stream manifestResourceStream = typeof(CookIcons).Assembly.GetManifestResourceStream("RestlessCook.Assets." + key + ".png");
			if (manifestResourceStream == null)
			{
				Plugin.Log.LogWarning((object)("cook icon missing " + key));
				return null;
			}
			using (manifestResourceStream)
			{
				byte[] array = new byte[manifestResourceStream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = manifestResourceStream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				MethodInfo methodInfo = LoadImage();
				if (methodInfo == null || !(bool)methodInfo.Invoke(null, new object[2] { val, array }))
				{
					Object.Destroy((Object)(object)val);
					Plugin.Log.LogWarning((object)("cook icon decode failed " + key));
					return null;
				}
				((Object)val).name = key;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				return val;
			}
		}

		private static MethodInfo? LoadImage()
		{
			if (_searched)
			{
				return _loadImage;
			}
			_searched = true;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType("UnityEngine.ImageConversion");
				if (!(type == null))
				{
					_loadImage = type.GetMethod("LoadImage", new Type[2]
					{
						typeof(Texture2D),
						typeof(byte[])
					});
					if (_loadImage != null)
					{
						return _loadImage;
					}
				}
			}
			return null;
		}
	}
	internal static class CookMesh
	{
		private static readonly Dictionary<string, Mesh> Meshes = new Dictionary<string, Mesh>();

		private static readonly Dictionary<string, Texture2D> Albedos = new Dictionary<string, Texture2D>();

		private static string? _folder;

		private static MethodInfo? _loadImage;

		private static bool _searched;

		public static string Folder()
		{
			if (_folder != null)
			{
				return _folder;
			}
			string[] array = PluginRoots();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string dir = Path.Combine(text, "mesh");
				if (HasRcm(dir))
				{
					return Remember(dir);
				}
				if (HasRcm(text))
				{
					return Remember(text);
				}
			}
			_folder = Path.Combine((array.Length != 0) ? array[0] : ".", "mesh");
			Plugin.Log.LogWarning((object)("cook mesh folder missing, looking in " + _folder));
			return _folder;
		}

		private static string[] PluginRoots()
		{
			List<string> list = new List<string>();
			Plugin instance = Plugin.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				PluginInfo info = ((BaseUnityPlugin)instance).Info;
				obj = ((info != null) ? info.Location : null);
			}
			string text = (string)obj;
			if (!string.IsNullOrEmpty(text))
			{
				AddRoot(list, Path.GetDirectoryName(text));
			}
			string location = typeof(CookMesh).Assembly.Location;
			if (!string.IsNullOrEmpty(location))
			{
				AddRoot(list, Path.GetDirectoryName(location));
			}
			return list.ToArray();
		}

		private static void AddRoot(List<string> roots, string? root)
		{
			if (string.IsNullOrEmpty(root))
			{
				return;
			}
			foreach (string root2 in roots)
			{
				if (string.Equals(root2, root, StringComparison.OrdinalIgnoreCase))
				{
					return;
				}
			}
			roots.Add(root);
		}

		private static string Remember(string dir)
		{
			_folder = dir;
			Plugin.Log.LogInfo((object)("cook mesh folder " + dir));
			return dir;
		}

		private static bool HasRcm(string dir)
		{
			if (Directory.Exists(dir))
			{
				return Directory.GetFiles(dir, "*.rcm").Length != 0;
			}
			return false;
		}

		public static Mesh? Mesh(string id)
		{
			string text = id.Replace('_', '-');
			if (Meshes.TryGetValue(text, out Mesh value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			string path = Path.Combine(Folder(), text + ".rcm");
			if (!File.Exists(path))
			{
				Plugin.Log.LogWarning((object)("cook mesh missing " + text));
				return null;
			}
			value = ReadRcm(File.ReadAllBytes(path), text);
			if ((Object)(object)value != (Object)null)
			{
				Meshes[text] = value;
			}
			return value;
		}

		public static Texture2D? Albedo(string id)
		{
			string text = id.Replace('_', '-');
			if (Albedos.TryGetValue(text, out Texture2D value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			string path = Path.Combine(Folder(), text + ".png");
			if (!File.Exists(path))
			{
				Plugin.Log.LogWarning((object)("cook albedo missing " + text));
				return null;
			}
			value = DecodePng(File.ReadAllBytes(path), text);
			if ((Object)(object)value != (Object)null)
			{
				Albedos[text] = value;
			}
			return value;
		}

		private static Mesh? ReadRcm(byte[] data, string name)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Expected O, but got Unknown
			if (data.Length < 12 || data[0] != 82 || data[1] != 67 || data[2] != 77 || (data[3] != 49 && data[3] != 50))
			{
				Plugin.Log.LogWarning((object)("cook mesh bad header " + name));
				return null;
			}
			bool flag = data[3] == 49;
			int num = 4;
			int num2 = BitConverter.ToInt32(data, num);
			num += 4;
			int num3 = BitConverter.ToInt32(data, num);
			num += 4;
			if (num2 <= 0 || num3 <= 0 || num + num2 * 32 + num3 * 4 > data.Length)
			{
				Plugin.Log.LogWarning((object)("cook mesh truncated " + name));
				return null;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[num2];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num2];
			Vector2[] array3 = (Vector2[])(object)new Vector2[num2];
			for (int i = 0; i < num2; i++)
			{
				array[i] = new Vector3(BitConverter.ToSingle(data, num), BitConverter.ToSingle(data, num + 4), BitConverter.ToSingle(data, num + 8));
				array2[i] = new Vector3(BitConverter.ToSingle(data, num + 12), BitConverter.ToSingle(data, num + 16), BitConverter.ToSingle(data, num + 20));
				float num4 = BitConverter.ToSingle(data, num + 28);
				array3[i] = new Vector2(BitConverter.ToSingle(data, num + 24), flag ? (1f - num4) : num4);
				num += 32;
			}
			int[] array4 = new int[num3];
			for (int j = 0; j < num3; j++)
			{
				array4[j] = BitConverter.ToInt32(data, num);
				num += 4;
			}
			Mesh val = new Mesh
			{
				name = name,
				indexFormat = (IndexFormat)(num2 > 65000)
			};
			val.SetVertices(array);
			val.SetNormals(array2);
			val.SetUVs(0, array3);
			val.SetTriangles(array4, 0);
			val.RecalculateBounds();
			return val;
		}

		private static Texture2D? DecodePng(byte[] bytes, string name)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			MethodInfo methodInfo = LoadImage();
			if (methodInfo == null || !(bool)methodInfo.Invoke(null, new object[2] { val, bytes }))
			{
				Object.Destroy((Object)(object)val);
				Plugin.Log.LogWarning((object)("cook albedo decode failed " + name));
				return null;
			}
			((Object)val).name = name;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).anisoLevel = 4;
			val.Apply(true, false);
			return val;
		}

		private static MethodInfo? LoadImage()
		{
			if (_searched)
			{
				return _loadImage;
			}
			_searched = true;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType("UnityEngine.ImageConversion");
				if (!(type == null))
				{
					_loadImage = type.GetMethod("LoadImage", new Type[2]
					{
						typeof(Texture2D),
						typeof(byte[])
					});
					if (_loadImage != null)
					{
						return _loadImage;
					}
				}
			}
			return null;
		}
	}
	public sealed class CookUse
	{
		public string Item { get; set; } = "";

		public int Amount { get; set; }
	}
	public sealed class CookRow
	{
		public string Id { get; set; } = "";

		public string Name { get; set; } = "";

		public string Kind { get; set; } = "";

		public string Source { get; set; } = "";

		public string Operation { get; set; } = "";

		public string Tier { get; set; } = "";

		public string Prefab { get; set; } = "";

		public string RecipeId { get; set; } = "";

		public string CloneFrom { get; set; } = "";

		public int Food { get; set; }

		public int FoodStamina { get; set; }

		public int FoodEitr { get; set; }

		public float FoodRegen { get; set; }

		public int FoodMinutes { get; set; }

		public List<string> Feeds { get; } = new List<string>();

		public List<CookUse> Uses { get; } = new List<CookUse>();

		public int OutputAmount { get; set; } = 1;

		public string Station { get; set; } = "";

		public int StationLevel { get; set; } = 1;

		public bool IsAdd => Operation == "add";

		public bool IsRewrite => Operation == "rewrite";

		public bool IsReference => Operation == "reference";

		public bool IsMeal => Kind == "meal";

		public bool IsFeast => Kind == "feast";

		public bool IsSideboard => Kind == "sideboard";

		public bool IsStation => Kind == "station";

		public bool IsTool => Kind == "tool";
	}
	public sealed class CookBook
	{
		public List<CookRow> Items { get; } = new List<CookRow>();

		public List<CookRow> Kit { get; } = new List<CookRow>();
	}
	internal static class CookVisual
	{
		private const string ChildName = "RestlessCookMesh";

		private const float FeastMeshScale = 3f;

		private static readonly Vector3 ModelScale = Vector3.one * 2.5f;

		public static void Apply(CustomItem item, CookRow row)
		{
			if ((Object)(object)((item != null) ? item.ItemPrefab : null) != (Object)null)
			{
				Apply(item.ItemPrefab, row);
			}
		}

		public static void Apply(GameObject prefab, CookRow row)
		{
			if (!((Object)(object)prefab == (Object)null))
			{
				Mesh val = CookMesh.Mesh(row.Id);
				Texture2D albedo = CookMesh.Albedo(row.Id);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)("RestlessCook: no custom model for '" + row.Id + "', using vanilla appearance."));
					return;
				}
				GameObject val2 = FindOrCreate(prefab);
				(val2.GetComponent<MeshFilter>() ?? val2.AddComponent<MeshFilter>()).sharedMesh = val;
				MeshRenderer obj = val2.GetComponent<MeshRenderer>() ?? val2.AddComponent<MeshRenderer>();
				((Renderer)obj).enabled = true;
				Paint((Renderer)(object)obj, albedo, prefab);
				KeepPlate(prefab);
			}
		}

		public static void KeepPlate(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Transform obj = prefab.transform.Find("RestlessCookMesh");
			Renderer val = ((obj != null) ? ((Component)obj).GetComponent<Renderer>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			val.enabled = true;
			((Component)val).gameObject.SetActive(true);
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val) && (val2 is MeshRenderer || val2 is SkinnedMeshRenderer))
				{
					val2.enabled = false;
				}
			}
			EnsureHit(prefab);
		}

		public static void EnsureHit(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Transform val = prefab.transform.Find("RestlessCookMesh");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)prefab.GetComponent<Feast>() == (Object)null)
			{
				Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
				foreach (Collider obj in componentsInChildren)
				{
					MeshCollider val2 = (MeshCollider)(object)((obj is MeshCollider) ? obj : null);
					if (val2 != null)
					{
						Object.DestroyImmediate((Object)(object)val2);
					}
				}
				if ((Object)(object)prefab.GetComponentInChildren<Collider>(true) == (Object)null)
				{
					SitOnGround(val);
				}
			}
			else
			{
				DressFeast(prefab, val);
			}
		}

		private static void DressFeast(GameObject prefab, Transform keep)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			keep.localScale = Vector3.one * 3f;
			keep.localPosition = new Vector3(0f, 0.02f, 0f);
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform == (Object)(object)keep) && !((Component)val).transform.IsChildOf(keep))
				{
					val.enabled = false;
				}
			}
			Piece component = prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_clipGround = true;
				component.m_noInWater = true;
				component.m_cultivatedGroundOnly = false;
				component.m_groundOnly = false;
			}
			MeshFilter component2 = ((Component)keep).GetComponent<MeshFilter>();
			if (!((Object)(object)((component2 != null) ? component2.sharedMesh : null) == (Object)null))
			{
				MeshCollider obj = ((Component)keep).GetComponent<MeshCollider>() ?? ((Component)keep).gameObject.AddComponent<MeshCollider>();
				obj.sharedMesh = component2.sharedMesh;
				obj.convex = true;
				((Collider)obj).enabled = true;
			}
		}

		private static void SitOnGround(Transform keep)
		{
			//IL_0037: 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)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter component = ((Component)keep).GetComponent<MeshFilter>();
			if (!((Object)(object)((component != null) ? component.sharedMesh : null) == (Object)null))
			{
				BoxCollider obj = ((Component)keep).GetComponent<BoxCollider>() ?? ((Component)keep).gameObject.AddComponent<BoxCollider>();
				Bounds bounds = component.sharedMesh.bounds;
				obj.center = ((Bounds)(ref bounds)).center;
				obj.size = Vector3.Max(((Bounds)(ref bounds)).size, new Vector3(0.08f, 0.04f, 0.08f));
				((Collider)obj).enabled = true;
			}
		}

		private static GameObject FindOrCreate(GameObject prefab)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_0028: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			Transform val = prefab.transform.Find("RestlessCookMesh");
			if ((Object)(object)val != (Object)null)
			{
				val.SetParent(prefab.transform, false);
				val.localPosition = Vector3.zero;
				val.localRotation = Quaternion.identity;
				val.localScale = ModelScale;
				((Component)val).gameObject.layer = prefab.layer;
				((Component)val).gameObject.SetActive(true);
				return ((Component)val).gameObject;
			}
			GameObject val2 = new GameObject("RestlessCookMesh")
			{
				layer = prefab.layer
			};
			val2.transform.SetParent(prefab.transform, false);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = ModelScale;
			return val2;
		}

		private static void Paint(Renderer renderer, Texture2D? albedo, GameObject prefab)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Material val = CopyLit(prefab);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			val.color = Color.white;
			SetColor(val, "_Color", Color.white);
			SetColor(val, "_BaseColor", Color.white);
			SetColor(val, "_Tint", Color.white);
			SetFloat(val, "_Metallic", 0f);
			SetFloat(val, "_Glossiness", 0.12f);
			SetFloat(val, "_Smoothness", 0.12f);
			SetFloat(val, "_GlossMapScale", 0.12f);
			MuteGlow(val);
			if ((Object)(object)albedo != (Object)null)
			{
				if (val.HasProperty("_MainTex"))
				{
					val.SetTexture("_MainTex", (Texture)(object)albedo);
				}
				if (val.HasProperty("_BaseMap"))
				{
					val.SetTexture("_BaseMap", (Texture)(object)albedo);
				}
				if (val.HasProperty("_Diffuse"))
				{
					val.SetTexture("_Diffuse", (Texture)(object)albedo);
				}
			}
			renderer.sharedMaterial = val;
		}

		private static Material? CopyLit(GameObject prefab)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			Material val = QuietMat(prefab) ?? QuietFeast();
			if ((Object)(object)val != (Object)null)
			{
				return new Material(val);
			}
			Shader val2 = Shader.Find("Standard") ?? Shader.Find("Diffuse") ?? Shader.Find("Legacy Shaders/Diffuse");
			if (!((Object)(object)val2 != (Object)null))
			{
				return null;
			}
			return new Material(val2);
		}

		private static Material? QuietFeast()
		{
			string[] array = new string[2] { "FeastMeadows", "FeastBlackforest" };
			foreach (string text in array)
			{
				PrefabManager instance = PrefabManager.Instance;
				Material val = QuietMat((instance != null) ? instance.GetPrefab(text) : null);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Material? QuietMat(GameObject? prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(((Object)((Component)val).transform).name == "RestlessCookMesh") && val is MeshRenderer && !Garnish(((Component)val).transform))
				{
					Material sharedMaterial = val.sharedMaterial;
					if (!((Object)(object)((sharedMaterial != null) ? sharedMaterial.shader : null) == (Object)null) && !Glows(sharedMaterial))
					{
						return sharedMaterial;
					}
				}
			}
			return null;
		}

		private static bool Garnish(Transform node)
		{
			Transform val = node;
			while ((Object)(object)val != (Object)null)
			{
				string name = ((Object)val).name;
				if (Has(name, "thistle") || Has(name, "spice") || Has(name, "eitr") || Has(name, "glow") || Has(name, "garnish") || Has(name, "magecap") || Has(name, "jotun") || Has(name, "wisp") || Has(name, "mist"))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static bool Glows(Material mat)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			string text = ((Object)mat).name + " " + ((Object)mat.shader).name;
			if (Has(text, "thistle") || Has(text, "spice") || Has(text, "eitr") || Has(text, "glow"))
			{
				return true;
			}
			if (mat.IsKeywordEnabled("_EMISSION") || mat.IsKeywordEnabled("EMISSION"))
			{
				return true;
			}
			if (mat.HasProperty("_EmissionMap") && (Object)(object)mat.GetTexture("_EmissionMap") != (Object)null)
			{
				return true;
			}
			if (mat.HasProperty("_EmissionColorMap") && (Object)(object)mat.GetTexture("_EmissionColorMap") != (Object)null)
			{
				return true;
			}
			Color color;
			if (mat.HasProperty("_EmissionColor"))
			{
				color = mat.GetColor("_EmissionColor");
				if (((Color)(ref color)).maxColorComponent > 0.02f)
				{
					return true;
				}
			}
			if (mat.HasProperty("_EmissiveColor"))
			{
				color = mat.GetColor("_EmissiveColor");
				if (((Color)(ref color)).maxColorComponent > 0.02f)
				{
					return true;
				}
			}
			if (mat.HasProperty("_EnableEmission") && mat.GetFloat("_EnableEmission") > 0.5f)
			{
				return true;
			}
			return false;
		}

		private static void MuteGlow(Material mat)
		{
			//IL_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			SetColor(mat, "_EmissionColor", Color.black);
			SetColor(mat, "_EmissiveColor", Color.black);
			SetColor(mat, "_GlowColor", Color.black);
			SetFloat(mat, "_EnableEmission", 0f);
			SetFloat(mat, "_EmissionIntensity", 0f);
			if (mat.HasProperty("_EmissionMap"))
			{
				mat.SetTexture("_EmissionMap", (Texture)null);
			}
			if (mat.HasProperty("_EmissionColorMap"))
			{
				mat.SetTexture("_EmissionColorMap", (Texture)null);
			}
			mat.DisableKeyword("_EMISSION");
			mat.DisableKeyword("EMISSION");
		}

		private static bool Has(string text, string token)
		{
			return text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static void SetColor(Material mat, string prop, Color color)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (mat.HasProperty(prop))
			{
				mat.SetColor(prop, color);
			}
		}

		private static void SetFloat(Material mat, string prop, float value)
		{
			if (mat.HasProperty(prop))
			{
				mat.SetFloat(prop, value);
			}
		}
	}
	public static class CookYaml
	{
		public static CookBook LoadEmbedded()
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("RestlessCook.cook.yaml") ?? throw new InvalidOperationException("Missing embedded cook.yaml");
			using StreamReader streamReader = new StreamReader(stream);
			return Parse(streamReader.ReadToEnd());
		}

		public static CookBook Parse(string text)
		{
			CookBook book = new CookBook();
			CookRow cur = null;
			CookUse cookUse = null;
			string text2 = null;
			string section = null;
			string[] array = text.Split(new string[2] { "\r\n", "\n" }, StringSplitOptions.None);
			for (int i = 0; i < array.Length; i++)
			{
				string text3 = array[i].TrimEnd(Array.Empty<char>());
				if (text3 == "kit:" || text3 == "items:")
				{
					Flush();
					section = text3.TrimEnd(new char[1] { ':' });
					cookUse = null;
					text2 = null;
				}
				else
				{
					if (section == null)
					{
						continue;
					}
					if (text3.StartsWith("  - id:", StringComparison.Ordinal))
					{
						Flush();
						cur = new CookRow
						{
							Id = Value(text3)
						};
						cookUse = null;
						text2 = null;
					}
					else
					{
						if (cur == null)
						{
							continue;
						}
						if (text3.StartsWith("    feeds:", StringComparison.Ordinal))
						{
							text2 = "feeds";
							if (text3.Contains("[]"))
							{
								text2 = null;
							}
						}
						else if (text3.StartsWith("    uses:", StringComparison.Ordinal))
						{
							text2 = "uses";
						}
						else if (text2 == "feeds" && text3.StartsWith("      - ", StringComparison.Ordinal))
						{
							cur.Feeds.Add(text3.Substring(text3.IndexOf('-') + 1).Trim());
						}
						else if (text2 == "uses" && text3.StartsWith("      - item:", StringComparison.Ordinal))
						{
							cookUse = new CookUse
							{
								Item = Value(text3)
							};
							cur.Uses.Add(cookUse);
						}
						else if (text2 == "uses" && cookUse != null && text3.StartsWith("        amount:", StringComparison.Ordinal))
						{
							cookUse.Amount = int.Parse(Value(text3));
						}
						else if (text3.StartsWith("    ", StringComparison.Ordinal) && text3.Contains(":") && !text3.StartsWith("      ", StringComparison.Ordinal))
						{
							text2 = null;
							int num = text3.IndexOf(':');
							string text4 = text3.Substring(0, num).Trim();
							string text5 = Unquote(text3.Substring(num + 1).Trim());
							switch (text4)
							{
							case "name":
								cur.Name = text5;
								break;
							case "kind":
								cur.Kind = text5;
								break;
							case "source":
								cur.Source = text5;
								break;
							case "operation":
								cur.Operation = text5;
								break;
							case "tier":
								cur.Tier = text5;
								break;
							case "prefab":
								cur.Prefab = text5;
								break;
							case "recipe_id":
								cur.RecipeId = text5;
								break;
							case "clone_from":
								cur.CloneFrom = text5;
								break;
							case "food":
								cur.Food = int.Parse(text5);
								break;
							case "food_stamina":
								cur.FoodStamina = int.Parse(text5);
								break;
							case "food_eitr":
								cur.FoodEitr = int.Parse(text5);
								break;
							case "food_regen":
								cur.FoodRegen = float.Parse(text5, CultureInfo.InvariantCulture);
								break;
							case "food_minutes":
								cur.FoodMinutes = int.Parse(text5);
								break;
							case "output_amount":
								cur.OutputAmount = int.Parse(text5);
								break;
							case "station":
								cur.Station = text5;
								break;
							case "station_level":
								cur.StationLevel = int.Parse(text5);
								break;
							}
						}
					}
				}
			}
			Flush();
			Validate(book.Items);
			ValidateKit(book.Kit);
			return book;
			void Flush()
			{
				if (cur != null)
				{
					if (section == "kit")
					{
						book.Kit.Add(cur);
					}
					else if (section == "items")
					{
						book.Items.Add(cur);
					}
					cur = null;
				}
			}
		}

		public static void Validate(IReadOnlyList<CookRow> items)
		{
			if (items.Count != 81)
			{
				throw new InvalidOperationException($"cook.yaml must have 81 rows, got {items.Count}");
			}
			HashSet<string> hashSet = new HashSet<string>(items.Select((CookRow i) => i.Id), StringComparer.Ordinal);
			if (hashSet.Count != 81)
			{
				throw new InvalidOperationException("cook.yaml has duplicate ids");
			}
			foreach (CookRow item in items)
			{
				if (item.Uses.Count == 0)
				{
					throw new InvalidOperationException(item.Id + ": empty uses[]");
				}
				foreach (string feed in item.Feeds)
				{
					if (!hashSet.Contains(feed))
					{
						throw new InvalidOperationException(item.Id + ": feeds unknown id " + feed);
					}
				}
			}
			Require(Count((CookRow i) => i.IsAdd) == 35, "35 add rows");
			Require(Count((CookRow i) => i.IsRewrite) == 16, "16 rewrite rows");
			Require(Count((CookRow i) => i.IsReference) == 30, "30 reference rows");
			Require(Count((CookRow i) => i.IsAdd || i.IsRewrite) == 51, "51 recipe operations");
			Require(Count((CookRow i) => i.IsMeal && i.Source == "custom" && i.IsAdd) == 17, "17 custom meals");
			Require(Count((CookRow i) => i.IsFeast && i.Source == "custom" && i.IsAdd) == 16, "16 custom feasts");
			Require(Count((CookRow i) => i.IsSideboard && i.IsAdd) == 2, "2 sideboards");
			Require(Count((CookRow i) => i.IsMeal && i.IsRewrite) == 14, "14 cooked-first rewrites");
			Require(Count((CookRow i) => i.IsFeast && i.IsRewrite) == 2, "2 feast reroutes");
			Require(Count((CookRow i) => i.IsMeal && i.IsReference) == 24, "24 meal references");
			Require(Count((CookRow i) => i.IsFeast && i.IsReference) == 6, "6 feast references");
			foreach (CookRow item2 in items.Where((CookRow i) => i.IsAdd))
			{
				if (string.IsNullOrEmpty(item2.CloneFrom))
				{
					throw new InvalidOperationException(item2.Id + ": add requires clone_from");
				}
				if (string.IsNullOrEmpty(item2.Prefab))
				{
					throw new InvalidOperationException(item2.Id + ": add requires prefab");
				}
			}
			foreach (CookRow item3 in items.Where((CookRow i) => i.IsAdd && (i.IsMeal || i.IsFeast)))
			{
				if (item3.Food == 0 && item3.FoodStamina == 0 && item3.FoodEitr == 0)
				{
					throw new InvalidOperationException(item3.Id + ": custom meal/feast needs food stats");
				}
				if (item3.FoodMinutes <= 0)
				{
					throw new InvalidOperationException(item3.Id + ": custom meal/feast needs food_minutes");
				}
				if (item3.FoodRegen <= 0f)
				{
					throw new InvalidOperationException(item3.Id + ": custom meal/feast needs food_regen");
				}
			}
			foreach (CookRow item4 in items.Where((CookRow i) => i.IsSideboard))
			{
				if (item4.Food != 0 || item4.FoodStamina != 0 || item4.FoodEitr != 0 || item4.FoodMinutes != 0)
				{
					throw new InvalidOperationException(item4.Id + ": sideboard is not edible");
				}
			}
			foreach (CookRow item5 in items.Where((CookRow i) => i.IsRewrite))
			{
				if (string.IsNullOrEmpty(item5.RecipeId))
				{
					throw new InvalidOperationException(item5.Id + ": rewrite requires recipe_id");
				}
			}
			Dictionary<string, CookRow> byId = items.ToDictionary<CookRow, string>((CookRow i) => i.Id, StringComparer.Ordinal);
			foreach (CookRow item6 in items.Where((CookRow i) => i.IsMeal))
			{
				if (!ReachesFeast(item6, byId))
				{
					throw new InvalidOperationException(item6.Id + ": meal has no path to a feast");
				}
			}
			foreach (CookRow item7 in items.Where((CookRow i) => i.IsFeast && i.Source == "custom" && i.IsAdd && (i.Tier == "meadows" || i.Tier == "blackforest")))
			{
				if (item7.Uses.Any((CookUse u) => u.Item == "SpiceForests"))
				{
					throw new InvalidOperationException(item7.Id + ": early custom feast cannot require Bog Witch spices");
				}
			}
			int Count(Func<CookRow, bool> pred)
			{
				return items.Count(pred);
			}
		}

		private static void ValidateKit(IReadOnlyList<CookRow> kit)
		{
			if (kit.Count != 2)
			{
				throw new InvalidOperationException($"cook.yaml kit must have 2 rows, got {kit.Count}");
			}
			CookRow cookRow = kit.FirstOrDefault((CookRow i) => i.Id == "food_preparation_table");
			CookRow cookRow2 = kit.FirstOrDefault((CookRow i) => i.Id == "serving_tray");
			if (cookRow == null || !cookRow.IsStation || !cookRow.IsRewrite || cookRow.Prefab != "piece_preptable" || cookRow.Uses.Count == 0)
			{
				throw new InvalidOperationException("kit: food_preparation_table must rewrite piece_preptable");
			}
			if (cookRow2 == null || !cookRow2.IsTool || !cookRow2.IsAdd || cookRow2.Prefab != "Feaster" || cookRow2.Uses.Count == 0)
			{
				throw new InvalidOperationException("kit: serving_tray must add a Feaster recipe");
			}
		}

		private static bool ReachesFeast(CookRow start, IReadOnlyDictionary<string, CookRow> byId)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			Stack<string> stack = new Stack<string>();
			stack.Push(start.Id);
			while (stack.Count > 0)
			{
				string text = stack.Pop();
				if (!hashSet.Add(text) || !byId.TryGetValue(text, out CookRow value))
				{
					continue;
				}
				if (value.IsFeast && text != start.Id)
				{
					return true;
				}
				foreach (string feed in value.Feeds)
				{
					stack.Push(feed);
				}
			}
			return start.IsFeast;
		}

		private static void Require(bool ok, string label)
		{
			if (!ok)
			{
				throw new InvalidOperationException("cook.yaml failed check: " + label);
			}
		}

		private static string Value(string line)
		{
			int num = line.IndexOf(':');
			return Unquote(line.Substring(num + 1).Trim());
		}

		private static string Unquote(string val)
		{
			if (val.Length >= 2 && ((val[0] == '"' && val[val.Length - 1] == '"') || (val[0] == '\'' && val[val.Length - 1] == '\'')))
			{
				return val.Substring(1, val.Length - 2);
			}
			return val;
		}
	}
	[BepInPlugin("restless.cook", "RestlessCook", "0.1.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "restless.cook";

		public const string PluginName = "RestlessCook";

		public const string PluginVersion = "0.1.9";

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			CookBook cookBook = CookYaml.LoadEmbedded();
			RecipeEngine.Load(cookBook);
			Log.LogInfo((object)string.Format("{0} {1} loaded ({2} cook.yaml rows, {3} kit).", "RestlessCook", "0.1.9", cookBook.Items.Count, cookBook.Kit.Count));
		}
	}
	internal static class RecipeEngine
	{
		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		public static class CopyOtherDbPatch
		{
			public static void Postfix(ObjectDB __instance)
			{
				Rewrite(__instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		public static class AwakePatch
		{
			public static void Postfix(ObjectDB __instance)
			{
				Rewrite(__instance);
			}
		}

		[HarmonyPatch(typeof(Feast), "UpdateVisual")]
		public static class FeastVisualPatch
		{
			public static void Postfix(Feast __instance)
			{
				if ((Object)(object)__instance != (Object)null)
				{
					ReadyFeast(__instance);
					CookVisual.KeepPlate(((Component)__instance).gameObject);
				}
			}
		}

		[HarmonyPatch(typeof(Feast), "Interact")]
		public static class FeastInteractPatch
		{
			public static void Prefix(Feast __instance)
			{
				ReadyFeast(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "AddKnownRecipe")]
		public static class AddKnownRecipePatch
		{
			public static bool Prefix(Recipe recipe)
			{
				if (Ours(recipe))
				{
					return ReqsComplete(recipe);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")]
		public static class KnownFeastPatch
		{
			public static void Postfix(Player __instance)
			{
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				TeachOurs(__instance);
				foreach (CookRow item in _rows.Where((CookRow r) => r.IsAdd && r.IsFeast))
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab(item.Prefab);
					Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
					if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.m_name) && !__instance.m_knownRecipes.Contains(val.m_name) && __instance.HaveRequirements(val, (RequirementMode)1))
					{
						__instance.AddKnownPiece(val);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "IsRecipeKnown")]
		public static class IsRecipeKnownPatch
		{
			public static void Postfix(Player __instance, string name, ref bool __result)
			{
				if (!__result)
				{
					return;
				}
				ObjectDB instance = ObjectDB.instance;
				if (instance?.m_recipes != null)
				{
					Recipe val = FindRecipeByKnownName(instance, name);
					if (!((Object)(object)val == (Object)null) && Ours(val) && !ShouldShow(val))
					{
						__result = false;
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
		public static class RecipeListPatch
		{
			public static void Prefix(object __0)
			{
				HideUnknown(__0);
			}
		}

		private static IReadOnlyList<CookRow> _rows = Array.Empty<CookRow>();

		private static IReadOnlyList<CookRow> _kit = Array.Empty<CookRow>();

		private static bool _added;

		private static Harmony? _harmony;

		public static void Load(CookBook book)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			_rows = book.Items;
			_kit = book.Kit;
			PrefabManager.OnVanillaPrefabsAvailable += AddCustom;
			ItemManager.OnItemsRegistered += RewriteRegistered;
			ItemManager.OnItemsRegistered += RewriteSoon;
			PieceManager.OnPiecesRegistered += WireFeasts;
			_harmony = new Harmony("restless.cook.recipes");
			_harmony.PatchAll(typeof(RecipeEngine).Assembly);
		}

		private static string StationName(string station)
		{
			return station switch
			{
				"piece_preptable" => CraftingStations.FoodPreparationTable, 
				"piece_cauldron" => CraftingStations.Cauldron, 
				"piece_workbench" => CraftingStations.Workbench, 
				_ => station, 
			};
		}

		internal static string CloneSource(CookRow row)
		{
			string cloneFrom = row.CloneFrom;
			if (row.IsFeast && cloneFrom.StartsWith("Feast", StringComparison.Ordinal) && !cloneFrom.EndsWith("_Material", StringComparison.Ordinal))
			{
				return cloneFrom + "_Material";
			}
			return cloneFrom;
		}

		private static void AddCustom()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= AddCustom;
			if (_added)
			{
				return;
			}
			_added = true;
			RewritePrepTable();
			GrantTrayRecipe();
			foreach (CookRow item in _rows.Where((CookRow r) => r.IsAdd && r.IsMeal))
			{
				RegisterItem(item);
			}
			foreach (CookRow item2 in _rows.Where((CookRow r) => r.IsAdd && r.IsSideboard))
			{
				RegisterItem(item2);
			}
			foreach (CookRow item3 in _rows.Where((CookRow r) => r.IsAdd && r.IsFeast))
			{
				RegisterFeast(item3);
			}
			int num = _rows.Count((CookRow r) => r.IsAdd || r.IsRewrite);
			Plugin.Log.LogInfo((object)$"RestlessCook registered {_rows.Count((CookRow r) => r.IsAdd)} custom items from cook.yaml ({num} recipe operations).");
		}

		private static void RegisterItem(CookRow row)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_002e: 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_0047: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			ItemConfig val = new ItemConfig
			{
				Name = row.Name,
				Description = Description(row),
				CraftingStation = StationName(row.Station),
				MinStationLevel = row.StationLevel,
				Amount = row.OutputAmount
			};
			Sprite val2 = CookIcons.Sprite(row.Id);
			if ((Object)(object)val2 != (Object)null)
			{
				val.Icon = val2;
			}
			foreach (CookUse use in row.Uses)
			{
				val.AddRequirement(use.Item, use.Amount, 0);
			}
			string text = CloneSource(row);
			GameObject val3 = PrefabManager.Instance.CreateClonedPrefab(row.Prefab, text);
			CustomItem val4 = ((!((Object)(object)val3 != (Object)null)) ? new CustomItem(row.Prefab, text, val) : new CustomItem(val3, true, val));
			ItemManager.Instance.AddItem(val4);
			CookVisual.Apply(((Object)(object)val3 != (Object)null) ? val3 : val4.ItemPrefab, row);
			if (row.IsSideboard)
			{
				StripFood(val4);
			}
			else if (row.IsMeal)
			{
				ApplyFood(row, val4);
			}
		}

		private static void RegisterFeast(CookRow row)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			Sprite val = CookIcons.Sprite(row.Id);
			string text = row.Prefab + "_Material";
			string text2 = (row.CloneFrom.EndsWith("_Material", StringComparison.Ordinal) ? row.CloneFrom : (row.CloneFrom + "_Material"));
			if ((Object)(object)PrefabManager.Instance.GetPrefab(text2) == (Object)null)
			{
				text2 = row.CloneFrom;
			}
			GameObject val2 = PrefabManager.Instance.CreateClonedPrefab(text, text2);
			if ((Object)(object)val2 != (Object)null)
			{
				SharedData val3 = val2.GetComponent<ItemDrop>()?.m_itemData?.m_shared;
				if (val3 != null)
				{
					val3.m_name = row.Name;
					val3.m_description = Description(row);
					if ((Object)(object)val != (Object)null)
					{
						val3.m_icons = (Sprite[])(object)new Sprite[1] { val };
					}
				}
				ItemManager.Instance.AddItem(new CustomItem(val2, true));
				CookVisual.Apply(val2, row);
				ApplyFood(row, val2.GetComponent<ItemDrop>());
				GrantItemRecipe(row, text);
			}
			else
			{
				Plugin.Log.LogWarning((object)("cook feast missing material " + text2));
			}
			string text3 = (row.CloneFrom.EndsWith("_Material", StringComparison.Ordinal) ? row.CloneFrom.Substring(0, row.CloneFrom.Length - "_Material".Length) : row.CloneFrom);
			GameObject val4 = PrefabManager.Instance.CreateClonedPrefab(row.Prefab, text3);
			if ((Object)(object)val4 == (Object)null)
			{
				Plugin.Log.LogWarning((object)("cook feast missing piece " + text3));
				return;
			}
			PieceConfig val5 = new PieceConfig
			{
				Name = row.Name,
				Description = Description(row),
				PieceTable = PieceTables.ServingTray,
				CraftingStation = CraftingStations.None
			};
			if ((Object)(object)val != (Object)null)
			{
				val5.Icon = val;
			}
			val5.AddRequirement(text, 1, true);
			PieceManager.Instance.AddPiece(new CustomPiece(val4, true, val5));
			CookVisual.Apply(val4, row);
			Plugin.Log.LogInfo((object)("cook feast piece " + row.Prefab));
		}

		private static void GrantTrayRecipe()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			CookRow cookRow = _kit.FirstOrDefault((CookRow r) => r.IsTool && r.IsAdd);
			if (cookRow == null)
			{
				return;
			}
			if ((Object)(object)PrefabManager.Instance.GetPrefab(cookRow.Prefab) == (Object)null)
			{
				Plugin.Log.LogWarning((object)("cook kit missing item " + cookRow.Prefab));
				return;
			}
			RecipeConfig val = new RecipeConfig
			{
				Name = "Recipe_Restless_" + cookRow.Id,
				Item = cookRow.Prefab,
				Amount = cookRow.OutputAmount,
				CraftingStation = StationName(string.IsNullOrEmpty(cookRow.Station) ? "piece_workbench" : cookRow.Station),
				RepairStation = CraftingStations.Workbench,
				MinStationLevel = ((cookRow.StationLevel < 1) ? 1 : cookRow.StationLevel)
			};
			foreach (CookUse use in cookRow.Uses)
			{
				val.AddRequirement(use.Item, use.Amount, 0);
			}
			ItemManager.Instance.AddRecipe(new CustomRecipe(val));
			Plugin.Log.LogInfo((object)("cook kit recipe " + cookRow.Prefab));
		}

		private static void GrantItemRecipe(CookRow row, string itemName)
		{
			//IL_0029: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			if ((Object)(object)PrefabManager.Instance.GetPrefab(itemName) == (Object)null)
			{
				Plugin.Log.LogWarning((object)("cook feast leftover missing " + itemName));
				return;
			}
			RecipeConfig val = new RecipeConfig
			{
				Name = "Recipe_Restless_" + row.Id,
				Item = itemName,
				Amount = row.OutputAmount,
				CraftingStation = StationName(string.IsNullOrEmpty(row.Station) ? "piece_preptable" : row.Station),
				MinStationLevel = ((row.StationLevel < 1) ? 1 : row.StationLevel)
			};
			foreach (CookUse use in row.Uses)
			{
				val.AddRequirement(use.Item, use.Amount, 0);
			}
			ItemManager.Instance.AddRecipe(new CustomRecipe(val));
			Plugin.Log.LogInfo((object)("cook feast leftover recipe " + itemName));
		}

		private static void RewritePrepTable()
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			CookRow cookRow = _kit.FirstOrDefault((CookRow r) => r.IsStation && r.IsRewrite);
			if (cookRow == null)
			{
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(cookRow.Prefab);
			Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("cook kit missing " + cookRow.Prefab));
				return;
			}
			List<Requirement> list = new List<Requirement>();
			foreach (CookUse use in cookRow.Uses)
			{
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(use.Item);
				ItemDrop val2 = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("cook kit missing ingredient " + use.Item));
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = val2,
					m_amount = use.Amount,
					m_amountPerLevel = 0,
					m_recover = true
				});
			}
			if (list.Count != 0)
			{
				val.m_resources = list.ToArray();
				Plugin.Log.LogInfo((object)("cook kit piece " + cookRow.Prefab));
			}
		}

		private static string Description(CookRow row)
		{
			if (row.IsSideboard)
			{
				return "A prepared board for feast assembly. Not edible on its own.";
			}
			if (row.IsFeast)
			{
				return "A Restless feast assembled from prepared meals.";
			}
			return "A Restless prepared meal.";
		}

		private static void ApplyFood(CookRow row, CustomItem item)
		{
			ApplyFood(row, item.ItemDrop);
		}

		private static void ApplyFood(CookRow row, ItemDrop? drop)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			SharedData val = drop?.m_itemData?.m_shared;
			if (val != null)
			{
				val.m_food = row.Food;
				val.m_foodStamina = row.FoodStamina;
				val.m_foodEitr = row.FoodEitr;
				val.m_foodRegen = row.FoodRegen;
				val.m_foodBurnTime = (float)row.FoodMinutes * 60f;
				val.m_itemType = (ItemType)2;
				val.m_consumeStatusEffect = null;
			}
		}

		private static void StripFood(CustomItem item)
		{
			StripFood(item.ItemDrop);
		}

		private static void StripFood(ItemDrop? drop)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			SharedData val = drop?.m_itemData?.m_shared;
			if (val != null)
			{
				val.m_itemType = (ItemType)1;
				val.m_food = 0f;
				val.m_foodStamina = 0f;
				val.m_foodEitr = 0f;
				val.m_foodRegen = 0f;
				val.m_foodBurnTime = 0f;
				val.m_consumeStatusEffect = null;
				if (val.m_maxStackSize < 20)
				{
					val.m_maxStackSize = 20;
				}
			}
		}

		private static void RewriteRegistered()
		{
			DressRegistered();
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				Rewrite(ObjectDB.instance);
			}
		}

		private static void RewriteSoon()
		{
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(RewriteAfterRecipes());
			}
		}

		private static IEnumerator RewriteAfterRecipes()
		{
			yield return null;
			yield return null;
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				Rewrite(ObjectDB.instance);
			}
		}

		private static void DressRegistered()
		{
			int num = 0;
			foreach (CookRow item in _rows.Where((CookRow r) => r.IsAdd))
			{
				foreach (string item2 in PrefabNames(item))
				{
					object obj = PrefabManager.Instance.GetPrefab(item2);
					if (obj == null)
					{
						ObjectDB instance = ObjectDB.instance;
						obj = ((instance != null) ? instance.GetItemPrefab(item2) : null);
					}
					GameObject val = (GameObject)obj;
					if (!((Object)(object)val == (Object)null))
					{
						CookVisual.Apply(val, item);
						ItemDrop component = val.GetComponent<ItemDrop>();
						if (item.IsSideboard)
						{
							StripFood(component);
						}
						else if (item.IsMeal || item.IsFeast)
						{
							ApplyFood(item, component);
						}
						num++;
					}
				}
			}
			Plugin.Log.LogInfo((object)$"cook dressed {num} prefabs");
		}

		private static IEnumerable<string> PrefabNames(CookRow row)
		{
			yield return row.Prefab;
			if (row.IsFeast)
			{
				yield return row.Prefab + "_Material";
			}
		}

		private static void WireFeasts()
		{
			foreach (CookRow item in _rows.Where((CookRow r) => r.IsAdd && r.IsFeast))
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(item.Prefab);
				Feast val = ((prefab != null) ? prefab.GetComponent<Feast>() : null);
				object obj = PrefabManager.Instance.GetPrefab(item.Prefab + "_Material");
				if (obj == null)
				{
					ObjectDB instance = ObjectDB.instance;
					obj = ((instance != null) ? instance.GetItemPrefab(item.Prefab + "_Material") : null);
				}
				ItemDrop val2 = ((obj != null) ? ((GameObject)obj).GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)("cook feast leftover missing " + item.Prefab));
					continue;
				}
				val.m_foodItem = val2;
				ApplyFood(item, val2);
				if (val.m_eatStacks < 1)
				{
					val.m_eatStacks = 10;
				}
				CookVisual.Apply(((Component)val).gameObject, item);
				BindFeastPiece(item, ((Component)val).GetComponent<Piece>(), ObjectDB.instance);
			}
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				Rewrite(ObjectDB.instance);
			}
		}

		private static void BindFeastPiece(CookRow row, Piece? piece, ObjectDB? db)
		{
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			if (!((Object)(object)piece == (Object)null))
			{
				piece.m_craftingStation = null;
				piece.m_enabled = true;
				EnsureOnTray(((Component)piece).gameObject);
				DetachFromOtherTables(((Component)piece).gameObject);
				string text = row.Prefab + "_Material";
				GameObject val = (((Object)(object)db != (Object)null) ? db.GetItemPrefab(text) : null);
				if ((Object)(object)val == (Object)null)
				{
					val = PrefabManager.Instance.GetPrefab(text);
				}
				ItemDrop val2 = ((val != null) ? val.GetComponent<ItemDrop>() : null);
				if (val2?.m_itemData?.m_shared == null)
				{
					Plugin.Log.LogWarning((object)("cook feast " + row.Id + " missing leftover " + text));
					return;
				}
				piece.m_resources = (Requirement[])(object)new Requirement[1]
				{
					new Requirement
					{
						m_resItem = val2,
						m_amount = 1,
						m_amountPerLevel = 0,
						m_recover = true
					}
				};
			}
		}

		private static void EnsureOnTray(GameObject go)
		{
			foreach (PieceTable item in PieceTablesInPlay())
			{
				if (IsServingTray(item) && item.m_pieces != null && !item.m_pieces.Contains(go))
				{
					item.m_pieces.Add(go);
					Plugin.Log.LogInfo((object)("cook feast added to " + ((Object)item).name));
				}
			}
		}

		private static void DetachFromOtherTables(GameObject go)
		{
			foreach (PieceTable item in PieceTablesInPlay())
			{
				if (!IsServingTray(item) && item.m_pieces != null && item.m_pieces.Remove(go))
				{
					Plugin.Log.LogInfo((object)("cook feast removed from " + ((Object)item).name));
				}
			}
		}

		private static bool IsServingTray(PieceTable table)
		{
			string text = (((Object)(object)table != (Object)null) ? ((Object)table).name : "");
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (text.IndexOf("Feaster", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (text.IndexOf("ServingTray", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			string text2 = PieceTables.ServingTray ?? "";
			if (text2.Length > 0)
			{
				return text.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static IEnumerable<PieceTable> PieceTablesInPlay()
		{
			HashSet<PieceTable> seen = new HashSet<PieceTable>();
			PieceTable[] array = Resources.FindObjectsOfTypeAll<PieceTable>();
			foreach (PieceTable val in array)
			{
				if ((Object)(object)val != (Object)null && seen.Add(val))
				{
					yield return val;
				}
			}
		}

		internal static void Rewrite(ObjectDB db)
		{
			if (db?.m_recipes == null || (Object)(object)FindItem(db, "Wood") == (Object)null)
			{
				return;
			}
			CookRow tray = _kit.FirstOrDefault((CookRow r) => r.IsTool && r.IsAdd);
			if (tray != null && !db.m_recipes.Any((Recipe r) => (Object)(object)r != (Object)null && MatchesKitRecipe(r, tray)))
			{
				Plugin.Log.LogWarning((object)("cook kit recipe missing from ObjectDB: Recipe_Restless_" + tray.Id));
			}
			foreach (CookRow row in _rows.Where((CookRow r) => r.IsRewrite))
			{
				List<Requirement> list = BuildReqs(db, row);
				if (list.Count != 0)
				{
					Recipe val = ((IEnumerable<Recipe>)db.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => (Object)(object)r != (Object)null && ((Object)r).name == row.RecipeId));
					if ((Object)(object)val != (Object)null)
					{
						val.m_resources = list.ToArray();
						val.m_amount = row.OutputAmount;
					}
					string text = (row.Prefab.EndsWith("_Material", StringComparison.Ordinal) ? row.Prefab.Substring(0, row.Prefab.Length - "_Material".Length) : row.Prefab);
					GameObject prefab = PrefabManager.Instance.GetPrefab(text);
					Piece val2 = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.m_resources = list.ToArray();
					}
					else if ((Object)(object)val == (Object)null)
					{
						Plugin.Log.LogWarning((object)("RestlessCook: missing " + row.RecipeId + " / " + text + " for " + row.Id));
					}
				}
			}
			foreach (CookRow item in _rows.Where((CookRow r) => r.IsAdd && r.IsFeast))
			{
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(item.Prefab);
				Piece piece = ((prefab2 != null) ? prefab2.GetComponent<Piece>() : null);
				BindFeastPiece(item, piece, db);
			}
			foreach (Recipe recipe in db.m_recipes)
			{
				CookRow cookRow = RowForRecipe(recipe);
				if (cookRow != null)
				{
					List<Requirement> list2 = BuildReqs(db, cookRow);
					if (list2.Count != 0)
					{
						recipe.m_resources = list2.ToArray();
						recipe.m_amount = cookRow.OutputAmount;
					}
				}
			}
			GateOurs(db);
		}

		private static void GateOurs(ObjectDB db)
		{
			if (db?.m_recipes == null)
			{
				return;
			}
			foreach (Recipe recipe in db.m_recipes)
			{
				if (Ours(recipe))
				{
					recipe.m_enabled = ReqsComplete(recipe);
				}
			}
		}

		private static bool MatchesKitRecipe(Recipe recipe, CookRow tray)
		{
			if ((Object)(object)recipe == (Object)null)
			{
				return false;
			}
			if (((Object)recipe).name == "Recipe_Restless_" + tray.Id)
			{
				return true;
			}
			string text = (((Object)(object)recipe.m_item != (Object)null) ? ((Object)recipe.m_item).name : "");
			if (!(text == tray.Prefab))
			{
				return text.IndexOf(tray.Prefab, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static CookRow? RowForRecipe(Recipe? recipe)
		{
			if ((Object)(object)recipe == (Object)null)
			{
				return null;
			}
			foreach (CookRow row in _rows)
			{
				if (row.IsAdd && (row.IsMeal || row.IsSideboard || row.IsFeast) && MatchesAddRecipe(recipe, row))
				{
					return row;
				}
			}
			return null;
		}

		private static bool MatchesAddRecipe(Recipe? recipe, CookRow row)
		{
			if ((Object)(object)recipe == (Object)null)
			{
				return false;
			}
			string text = (row.IsFeast ? (row.Prefab + "_Material") : row.Prefab);
			string text2 = (((Object)(object)recipe.m_item != (Object)null) ? ((Object)recipe.m_item).name : "");
			if (text2 == text || text2 == row.Prefab)
			{
				return true;
			}
			if (text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			string text3 = ((Object)recipe).name ?? "";
			if (text3 == "Recipe_Restless_" + row.Id)
			{
				return true;
			}
			if (text3.IndexOf(text, StringComparison.OrdinalIgnoreCase) < 0 && text3.IndexOf(row.Prefab, StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text3.IndexOf(row.Id, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static List<Requirement> BuildReqs(ObjectDB db, CookRow row)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			List<Requirement> list = new List<Requirement>();
			foreach (CookUse use in row.Uses)
			{
				GameObject val = FindItem(db, use.Item);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)("RestlessCook: " + row.Id + " missing ingredient " + use.Item));
					continue;
				}
				ItemDrop component = val.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null)
				{
					Plugin.Log.LogWarning((object)("RestlessCook: " + use.Item + " has no ItemDrop"));
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = component,
					m_amount = use.Amount,
					m_amountPerLevel = 0,
					m_recover = row.IsFeast
				});
			}
			return list;
		}

		private static GameObject? FindItem(ObjectDB db, string name)
		{
			GameObject itemPrefab = db.GetItemPrefab(name);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				return itemPrefab;
			}
			itemPrefab = PrefabManager.Instance.GetPrefab(name);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				return itemPrefab;
			}
			if (db.m_items == null)
			{
				return null;
			}
			foreach (GameObject item in db.m_items)
			{
				if ((Object)(object)item != (Object)null && ((Object)item).name.Equals(name, StringComparison.OrdinalIgnoreCase))
				{
					return item;
				}
			}
			return null;
		}

		private static bool Ours(Recipe? recipe)
		{
			if ((Object)(object)recipe?.m_item == (Object)null)
			{
				return false;
			}
			string crafted = ((Object)recipe.m_item).name;
			if (crafted.StartsWith("Restless", StringComparison.Ordinal))
			{
				return true;
			}
			if ((((Object)recipe).name ?? "").IndexOf("Restless", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return _rows.Any((CookRow r) => r.IsAdd && (crafted == r.Prefab || crafted == r.Prefab + "_Material"));
		}

		private static bool ReqsComplete(Recipe? recipe)
		{
			if (recipe?.m_resources == null || recipe.m_resources.Length == 0)
			{
				return false;
			}
			int num = 0;
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if (val != null && val.m_amount > 0)
				{
					num++;
					ItemDrop resItem = val.m_resItem;
					if ((Object)(object)resItem == (Object)null || ((Object)resItem).name.IndexOf("Mock", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return false;
					}
					if (resItem.m_itemData?.m_shared == null || string.IsNullOrEmpty(resItem.m_itemData.m_shared.m_name))
					{
						return false;
					}
				}
			}
			return num > 0;
		}

		private static bool ShouldShow(Recipe recipe)
		{
			return ReqsComplete(recipe);
		}

		private static void TeachOurs(Player player)
		{
			ObjectDB instance = ObjectDB.instance;
			if (instance?.m_recipes == null || player.m_knownRecipes == null)
			{
				return;
			}
			GateOurs(instance);
			List<string> list = new List<string>();
			foreach (string knownRecipe in player.m_knownRecipes)
			{
				Recipe val = FindRecipeByKnownName(instance, knownRecipe);
				if ((Object)(object)val != (Object)null && Ours(val) && !ReqsComplete(val))
				{
					list.Add(knownRecipe);
				}
			}
			foreach (string item in list)
			{
				player.m_knownRecipes.Remove(item);
			}
			foreach (Recipe recipe in instance.m_recipes)
			{
				if (Ours(recipe) && ShouldShow(recipe))
				{
					string text = recipe.m_item.m_itemData?.m_shared?.m_name;
					if (!string.IsNullOrEmpty(text) && !player.m_knownRecipes.Contains(text))
					{
						player.AddKnownRecipe(recipe);
					}
				}
			}
		}

		private static Recipe? FindRecipeByKnownName(ObjectDB db, string name)
		{
			foreach (Recipe recipe in db.m_recipes)
			{
				if (recipe?.m_item?.m_itemData?.m_shared?.m_name == name)
				{
					return recipe;
				}
			}
			return null;
		}

		private static void HideUnknown(object? list)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null || list == null)
			{
				return;
			}
			if (list is List<Recipe> list2)
			{
				list2.RemoveAll((Recipe recipe) => Ours(recipe) && !ShouldShow(recipe));
			}
			else
			{
				if (!(list is IList list3))
				{
					return;
				}
				for (int num = list3.Count - 1; num >= 0; num--)
				{
					Recipe val = RecipeOf(list3[num]);
					if ((Object)(object)val != (Object)null && Ours(val) && !ShouldShow(val))
					{
						list3.RemoveAt(num);
					}
				}
			}
		}

		private static Recipe? RecipeOf(object? entry)
		{
			Recipe val = (Recipe)((entry is Recipe) ? entry : null);
			if (val != null)
			{
				return val;
			}
			if (entry == null)
			{
				return null;
			}
			object? obj = (AccessTools.Field(entry.GetType(), "Recipe") ?? AccessTools.Field(entry.GetType(), "m_recipe") ?? AccessTools.Field(entry.GetType(), "recipe"))?.GetValue(entry);
			return (Recipe?)((obj is Recipe) ? obj : null);
		}

		internal static void DumpForSizeTest()
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print("restlesscook: no player");
				}
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			List<string> list = new List<string>();
			CookRow cookRow = _kit.FirstOrDefault((CookRow r) => r.IsTool && r.IsAdd);
			if (cookRow != null)
			{
				list.Add(cookRow.Prefab);
			}
			foreach (CookRow row in _rows)
			{
				if (row.IsAdd && (row.IsMeal || row.IsSideboard))
				{
					list.Add(row.Prefab);
				}
				else if (row.IsAdd && row.IsFeast)
				{
					list.Add(row.Prefab + "_Material");
				}
				else if (row.IsFeast && (row.IsRewrite || row.IsReference))
				{
					list.Add(row.Prefab);
				}
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			Vector3 val = ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward + Vector3.up;
			foreach (string item in list.Distinct())
			{
				GameObject val2 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(item) : null);
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = PrefabManager.Instance.GetPrefab(item);
				}
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.GetComponent<ItemDrop>() == (Object)null)
				{
					num3++;
					Plugin.Log.LogWarning((object)("restlesscook dump missing " + item));
					continue;
				}
				if (inventory.AddItem(val2, 1))
				{
					num++;
					continue;
				}
				ItemData obj = val2.GetComponent<ItemDrop>().m_itemData.Clone();
				obj.m_stack = 1;
				ItemDrop.DropItem(obj, 1, val, Quaternion.identity);
				num2++;
			}
			string text = $"restlesscook: {num} in bag, {num2} at feet" + ((num3 > 0) ? $", {num3} missing" : "");
			Console instance2 = Console.instance;
			if (instance2 != null)
			{
				instance2.Print(text);
			}
			Plugin.Log.LogInfo((object)text);
		}

		private static void ReadyFeast(Feast? feast)
		{
			if ((Object)(object)feast == (Object)null)
			{
				return;
			}
			string name = Utils.GetPrefabName(((Component)feast).gameObject);
			CookRow cookRow = _rows.FirstOrDefault((CookRow r) => r.IsAdd && r.IsFeast && r.Prefab == name);
			if (cookRow != null)
			{
				GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(cookRow.Prefab + "_Material") : null);
				if ((Object)(object)val == (Object)null)
				{
					val = PrefabManager.Instance.GetPrefab(cookRow.Prefab + "_Material");
				}
				ItemDrop val2 = ((val != null) ? val.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					feast.m_foodItem = val2;
					ApplyFood(cookRow, val2);
				}
				if (feast.m_eatStacks < 1)
				{
					feast.m_eatStacks = 10;
				}
				CookVisual.EnsureHit(((Component)feast).gameObject);
			}
		}
	}
}