Decompiled source of LynxLeftovers v1.0.1

plugins/LynxLeftovers.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace LynxLeftovers;

internal static class Content
{
	public static void Register()
	{
		RegisterLeftovers();
		RegisterGrinder();
		RegisterStewpot();
	}

	private static void RegisterLeftovers()
	{
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: 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_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: 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_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Expected O, but got Unknown
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Expected O, but got Unknown
		GameObject val = PrefabManager.Instance.CreateClonedPrefab("LynxLeftovers", "Entrails");
		SharedData shared = val.GetComponent<ItemDrop>().m_itemData.m_shared;
		shared.m_name = "$item_lynx_leftovers";
		shared.m_description = "$item_lynx_leftovers_desc";
		shared.m_maxStackSize = 50;
		shared.m_weight = 0.3f;
		shared.m_food = 0f;
		shared.m_foodStamina = 0f;
		shared.m_foodEitr = 0f;
		shared.m_teleportable = true;
		Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
		}
		Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
		}
		MeshFilter[] componentsInChildren3 = val.GetComponentsInChildren<MeshFilter>(true);
		for (int i = 0; i < componentsInChildren3.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
		}
		LODGroup[] componentsInChildren4 = val.GetComponentsInChildren<LODGroup>(true);
		for (int i = 0; i < componentsInChildren4.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
		}
		GameObject val2 = CopyChild(PrefabManager.Instance.GetPrefab("piece_chest_barrel"), "New/blackmetalchest", val.transform, Vector3.zero, new Vector3(0f, 180f, 0f), 0.25f);
		((Object)val2).name = "leftovers_jar";
		Transform val3 = val.transform.Find("attach");
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = new GameObject("attach").transform;
			val3.SetParent(val.transform, false);
		}
		foreach (Transform item in ((IEnumerable)val3).Cast<Transform>().ToList())
		{
			Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
		}
		Vector3 position = val2.transform.position;
		Quaternion rotation = val2.transform.rotation;
		Vector3 lossyScale = val2.transform.lossyScale;
		val2.transform.SetParent(val3, true);
		val2.transform.position = position;
		val2.transform.rotation = rotation;
		Vector3 lossyScale2 = val3.lossyScale;
		val2.transform.localScale = new Vector3(lossyScale.x / lossyScale2.x, lossyScale.y / lossyScale2.y, lossyScale.z / lossyScale2.z);
		BoxCollider obj = val.AddComponent<BoxCollider>();
		obj.center = new Vector3(0f, 0.112f, 0f);
		obj.size = new Vector3(0.2f, 0.225f, 0.2f);
		SetLayerRecursive(val2, val.layer);
		Sprite val4 = RenderManager.Instance.Render(new RenderRequest(val)
		{
			Rotation = RenderManager.IsometricRotation,
			Width = 128,
			Height = 128,
			UseCache = false
		});
		if ((Object)(object)val4 != (Object)null)
		{
			shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 };
		}
		else
		{
			Plugin.Log.LogWarning((object)"Leftovers icon render failed; keeping the Entrails icon");
		}
		ItemManager.Instance.AddItem(new CustomItem(val, false));
	}

	private static void RegisterGrinder()
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Expected O, but got Unknown
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Expected O, but got Unknown
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Expected O, but got Unknown
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Expected O, but got Unknown
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Expected O, but got Unknown
		GameObject val = PrefabManager.Instance.CreateClonedPrefab("LynxMeatGrinder", "piece_chest_barrel");
		Transform transform = val.transform;
		GameObject prefab = PrefabManager.Instance.GetPrefab("windmill");
		PrepareContainerBase(val, "$piece_lynx_grinder", stripBarrelMesh: false);
		GameObject val2 = CopyChild(prefab, "grindstone", transform, new Vector3(0f, 0.32999998f, 0f), Vector3.zero, 0.5f);
		float num = 1.44f;
		float num2 = num + 0.45f;
		Material mat = FirstMaterial(prefab, "grindstone");
		AddCylinder(transform, "mast", new Vector3(0f, (num + num2) / 2f, 0f), new Vector3(0.06f, (num2 - num) / 2f + 0.03f, 0.06f), mat);
		Transform val3 = prefab.transform.Find("rotating/propeller");
		GameObject val4 = CopyTransform(val3, transform, new Vector3(0f, num2, -0.285f), val3.localEulerAngles, 0.15f);
		GameObject val5 = CopyChild(prefab, "_enabled", transform, new Vector3(0f, num - 0.684f, 0f), Vector3.zero, 0.6f);
		DestroyChild(val5.transform, "smoke (1)");
		val5.SetActive(false);
		Transform transform2 = new GameObject("output").transform;
		transform2.SetParent(transform, false);
		transform2.localPosition = new Vector3(0f, 0.5f, -0.75f);
		MeatGrinder meatGrinder = val.AddComponent<MeatGrinder>();
		meatGrinder.m_activeVisual = val5;
		meatGrinder.m_outputPoint = transform2;
		meatGrinder.m_spinY = (Transform[])(object)new Transform[1] { val2.transform };
		meatGrinder.m_spinZ = (Transform[])(object)new Transform[1] { val4.transform };
		meatGrinder.m_spinYSpeed = 150f;
		meatGrinder.m_spinZSpeed = -300f;
		Sprite icon = prefab.GetComponent<Piece>()?.m_icon;
		ApplyVanillaCategory(val);
		PieceManager instance = PieceManager.Instance;
		PieceConfig val6 = new PieceConfig();
		val6.Name = "$piece_lynx_grinder";
		val6.Description = "$piece_lynx_grinder_desc";
		val6.PieceTable = "Hammer";
		val6.Category = CustomCategoryOrNull();
		val6.CraftingStation = "forge";
		val6.Icon = icon;
		val6.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
		{
			new RequirementConfig("Iron", 3, 0, true),
			new RequirementConfig("SurtlingCore", 1, 0, true),
			new RequirementConfig("BarrelRings", 2, 0, true)
		};
		instance.AddPiece(new CustomPiece(val, false, val6));
	}

	private static void RegisterStewpot()
	{
		//IL_005a: 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)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Expected O, but got Unknown
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Expected O, but got Unknown
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Expected O, but got Unknown
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Expected O, but got Unknown
		GameObject val = PrefabManager.Instance.CreateClonedPrefab("LynxStockCask", "piece_chest_barrel");
		Transform transform = val.transform;
		GameObject prefab = PrefabManager.Instance.GetPrefab("cauldron_ext7_smoker");
		GameObject prefab2 = PrefabManager.Instance.GetPrefab("fire_pit");
		PrepareContainerBase(val, "$piece_lynx_stockcask", stripBarrelMesh: true);
		Transform parent = transform.Find("New");
		MakeMetal(CopyChild(prefab, "new/high", parent, Vector3.zero, Vector3.zero, 1f));
		GameObject val2 = new GameObject("_simmer");
		val2.transform.SetParent(transform, false);
		CopyChild(prefab, "new/SmokerFX", val2.transform, new Vector3(-0.621f, 1.088f, 0f), Vector3.zero, 1f);
		CopyChild(prefab2, "_enabled_high/Point light", val2.transform, new Vector3(0f, 0.35f, -0.5f), Vector3.zero, 1f);
		val2.SetActive(false);
		Transform transform2 = new GameObject("output").transform;
		transform2.SetParent(transform, false);
		transform2.localPosition = new Vector3(0f, 0.45f, 0.65f);
		GameObject val3 = new GameObject("collider")
		{
			layer = LayerMask.NameToLayer("piece")
		};
		val3.transform.SetParent(transform, false);
		BoxCollider obj = val3.AddComponent<BoxCollider>();
		obj.center = new Vector3(-0.02f, 0.52f, 0f);
		obj.size = new Vector3(1.05f, 1.02f, 0.66f);
		Stewpot stewpot = val.AddComponent<Stewpot>();
		stewpot.m_activeVisual = val2;
		stewpot.m_outputPoint = transform2;
		Sprite icon = prefab.GetComponent<Piece>()?.m_icon;
		ApplyVanillaCategory(val);
		PieceManager instance = PieceManager.Instance;
		PieceConfig val4 = new PieceConfig();
		val4.Name = "$piece_lynx_stockcask";
		val4.Description = "$piece_lynx_stockcask_desc";
		val4.PieceTable = "Hammer";
		val4.Category = CustomCategoryOrNull();
		val4.CraftingStation = "forge";
		val4.Icon = icon;
		val4.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
		{
			new RequirementConfig("Iron", 5, 0, true),
			new RequirementConfig("BarrelRings", 1, 0, true)
		};
		instance.AddPiece(new CustomPiece(val, false, val4));
	}

	private static bool VanillaCategory(out PieceCategory cat)
	{
		string text = (Plugin.BuildCategory.Value ?? "").Trim();
		cat = (PieceCategory)1;
		if (text.Length == 0)
		{
			return true;
		}
		if (Enum.TryParse<PieceCategory>(text, ignoreCase: true, out cat) && (int)cat != 100)
		{
			return (int)cat != 9;
		}
		return false;
	}

	private static void ApplyVanillaCategory(GameObject go)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		if (VanillaCategory(out var cat))
		{
			go.GetComponent<Piece>().m_category = cat;
		}
	}

	private static string CustomCategoryOrNull()
	{
		if (!VanillaCategory(out var _))
		{
			return Plugin.BuildCategory.Value.Trim();
		}
		return null;
	}

	private static void MakeMetal(GameObject go)
	{
		Shader standard = FindStandardShader();
		Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer obj in componentsInChildren)
		{
			obj.sharedMaterials = ((IEnumerable<Material>)obj.sharedMaterials).Select((Func<Material, Material>)delegate(Material m)
			{
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0100: Expected O, but got Unknown
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Expected O, but got Unknown
				//IL_0122: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)m == (Object)null)
				{
					return m;
				}
				Material val;
				if ((Object)(object)standard != (Object)null)
				{
					val = new Material(standard)
					{
						name = ((Object)m).name + "_lynxsteel"
					};
					if (m.HasProperty("_MainTex"))
					{
						val.SetTexture("_MainTex", m.GetTexture("_MainTex"));
					}
					if (m.HasProperty("_BumpMap") && (Object)(object)m.GetTexture("_BumpMap") != (Object)null)
					{
						val.SetTexture("_BumpMap", m.GetTexture("_BumpMap"));
						val.EnableKeyword("_NORMALMAP");
					}
					val.SetFloat("_Metallic", 0.85f);
					val.SetFloat("_Glossiness", 0.55f);
					val.color = new Color(0.78f, 0.8f, 0.86f, 1f);
				}
				else
				{
					val = new Material(m)
					{
						name = ((Object)m).name + "_lynxsteel"
					};
					if (val.HasProperty("_Color"))
					{
						val.color = new Color(0.62f, 0.66f, 0.72f, 1f);
					}
				}
				return val;
			}).ToArray();
		}
	}

	private static Shader FindStandardShader()
	{
		Shader val = Shader.Find("Standard");
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		GameObject prefab = PrefabManager.Instance.GetPrefab("smelter");
		Transform val2 = (((Object)(object)prefab != (Object)null) ? prefab.transform.Find("Worn/default") : null);
		Renderer val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<Renderer>() : null);
		if (!((Object)(object)val3 != (Object)null) || !((Object)(object)val3.sharedMaterial != (Object)null))
		{
			return null;
		}
		return val3.sharedMaterial.shader;
	}

	private static void PrepareContainerBase(GameObject go, string name, bool stripBarrelMesh)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		Transform transform = go.transform;
		Container component = go.GetComponent<Container>();
		component.m_name = name;
		component.m_width = 4;
		component.m_height = 2;
		GameObject val = new GameObject("lid_none");
		val.transform.SetParent(transform, false);
		component.m_open = val;
		component.m_closed = val;
		Transform val2 = transform.Find("New");
		if ((Object)(object)val2 != (Object)null)
		{
			LODGroup component2 = ((Component)val2).GetComponent<LODGroup>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
			DestroyChild(val2, "Open");
			DestroyChild(val2, "Closed");
			DestroyChild(val2, "blackmetalchestLOD");
			if (stripBarrelMesh)
			{
				DestroyChild(val2, "blackmetalchest");
			}
		}
		DestroyChild(transform, "floor_2x2_snow");
		if (stripBarrelMesh)
		{
			DestroyChild(transform, "collider");
		}
		Piece component3 = go.GetComponent<Piece>();
		if ((Object)(object)component3 != (Object)null)
		{
			component3.m_name = name;
		}
	}

	private static GameObject CopyChild(GameObject srcPrefab, string path, Transform parent, Vector3 pos, Vector3 euler, float scale)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		Transform val = srcPrefab.transform.Find(path);
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogWarning((object)("Missing " + ((Object)srcPrefab).name + "/" + path + "; skipping that visual"));
			GameObject val2 = new GameObject("missing_" + path.Replace('/', '_'));
			val2.transform.SetParent(parent, false);
			return val2;
		}
		return CopyTransform(val, parent, pos, euler, scale);
	}

	private static GameObject CopyTransform(Transform src, Transform parent, Vector3 pos, Vector3 euler, float scale)
	{
		//IL_0027: 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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(((Component)src).gameObject, parent, false);
		((Object)val).name = ((Object)src).name;
		val.SetActive(true);
		val.transform.localPosition = pos;
		val.transform.localRotation = Quaternion.Euler(euler);
		val.transform.localScale = src.localScale * scale;
		Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
		}
		LODGroup[] componentsInChildren2 = val.GetComponentsInChildren<LODGroup>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
		}
		Transform[] array = val.GetComponentsInChildren<Transform>(true).ToArray();
		foreach (Transform val2 in array)
		{
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)val.transform))
			{
				string text = ((Object)val2).name.ToLowerInvariant();
				if (text == "low" || text == "lod" || text.EndsWith("lod"))
				{
					Object.DestroyImmediate((Object)(object)((Component)val2).gameObject);
				}
			}
		}
		MonoBehaviour[] componentsInChildren3 = val.GetComponentsInChildren<MonoBehaviour>(true);
		foreach (MonoBehaviour val3 in componentsInChildren3)
		{
			if (!((Object)(object)val3 == (Object)null))
			{
				string name = ((object)val3).GetType().Name;
				if (!(name == "LightFlicker") && !(name == "LightLod"))
				{
					Object.DestroyImmediate((Object)(object)val3);
				}
			}
		}
		ParticleSystem[] componentsInChildren4 = val.GetComponentsInChildren<ParticleSystem>(true);
		for (int i = 0; i < componentsInChildren4.Length; i++)
		{
			MainModule main = componentsInChildren4[i].main;
			((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
		}
		SetLayerRecursive(val, LayerMask.NameToLayer("piece_nonsolid"));
		return val;
	}

	private static void AddCylinder(Transform parent, string name, Vector3 pos, Vector3 scale, Material mat)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
		((Object)val).name = name;
		Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
		val.transform.SetParent(parent, false);
		val.transform.localPosition = pos;
		val.transform.localScale = scale;
		if ((Object)(object)mat != (Object)null)
		{
			val.GetComponent<Renderer>().sharedMaterial = mat;
		}
		val.layer = LayerMask.NameToLayer("piece_nonsolid");
	}

	private static Material FirstMaterial(GameObject prefab, string path)
	{
		Transform val = prefab.transform.Find(path);
		Renderer val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren<Renderer>(true) : null);
		if (!((Object)(object)val2 != (Object)null))
		{
			return null;
		}
		return val2.sharedMaterial;
	}

	private static void DestroyChild(Transform parent, string name)
	{
		Transform val = parent.Find(name);
		if ((Object)(object)val != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
		}
	}

	private static void SetLayerRecursive(GameObject go, int layer)
	{
		if (layer >= 0)
		{
			Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.layer = layer;
			}
		}
	}
}
internal static class DrawersCompat
{
	public const string ItemDrawersGuid = "com.rossdwest.itemdrawers";

	private static FieldInfo _instancesField;

	private static readonly List<KeyValuePair<ItemDrop, ItemData>> Blanked = new List<KeyValuePair<ItemDrop, ItemData>>();

	public static void TryApply(Harmony harmony)
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Expected O, but got Unknown
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Expected O, but got Unknown
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Expected O, but got Unknown
		//IL_014c: Expected O, but got Unknown
		if (!Chainloader.PluginInfos.ContainsKey("com.rossdwest.itemdrawers"))
		{
			return;
		}
		try
		{
			Type type = AccessTools.TypeByName("ItemDrawers.Game.DrawerComponent");
			Type type2 = AccessTools.TypeByName("ItemDrawers.Game.DrawerManager");
			Type type3 = AccessTools.TypeByName("ItemDrawers.Game.ItemFacts");
			_instancesField = AccessTools.Field(typeof(ItemDrop), "s_instances");
			int num = 0;
			MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "UseItem", (Type[])null, (Type[])null) : null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DrawersCompat), "UseItemPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			MethodInfo methodInfo2 = ((type3 != null) ? AccessTools.Method(type3, "PrefabNameOf", (Type[])null, (Type[])null) : null);
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(DrawersCompat), "PrefabNameOfPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			MethodInfo methodInfo3 = ((type2 != null) ? AccessTools.Method(type2, "RunAutoPickup", (Type[])null, (Type[])null) : null);
			if (methodInfo3 != null && _instancesField != null)
			{
				harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(typeof(DrawersCompat), "PickupPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(DrawersCompat), "PickupFinalizer", (Type[])null), (HarmonyMethod)null);
				num++;
			}
			Plugin.Log.LogInfo((object)$"ItemDrawers found: applied {num}/3 Hearty-food compatibility patches");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("ItemDrawers compatibility patch failed (Hearty food may lose its bonus in drawers): " + ex.Message));
		}
	}

	private static bool UseItemPrefix(Humanoid __0, ItemData __1, ref bool __result)
	{
		if (!FoodRules.IsHearty(__1))
		{
			return true;
		}
		if (__0 != null)
		{
			((Character)__0).Message((MessageType)2, "Drawers can't keep Hearty food Hearty", 0, (Sprite)null, false);
		}
		__result = true;
		return false;
	}

	private static void PrefabNameOfPostfix(ItemData __0, ref string __result)
	{
		if (FoodRules.IsHearty(__0))
		{
			__result = null;
		}
	}

	private static void PickupPrefix()
	{
		Blanked.Clear();
		if (!(_instancesField.GetValue(null) is List<ItemDrop> list))
		{
			return;
		}
		foreach (ItemDrop item in list)
		{
			if ((Object)(object)item != (Object)null && FoodRules.IsHearty(item.m_itemData))
			{
				Blanked.Add(new KeyValuePair<ItemDrop, ItemData>(item, item.m_itemData));
				item.m_itemData = null;
			}
		}
	}

	private static Exception PickupFinalizer(Exception __exception)
	{
		foreach (KeyValuePair<ItemDrop, ItemData> item in Blanked)
		{
			if ((Object)(object)item.Key != (Object)null)
			{
				item.Key.m_itemData = item.Value;
			}
		}
		Blanked.Clear();
		return __exception;
	}
}
public static class FoodRules
{
	public const string LeftoversPrefab = "LynxLeftovers";

	public const int HeartyQuality = 2;

	private static HashSet<string> _excluded;

	private static string _excludedConfigSnapshot;

	public static string PrefabName(ItemData item)
	{
		if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
		{
			return null;
		}
		return ((Object)item.m_dropPrefab).name;
	}

	public static float Value(ItemData item)
	{
		if (item == null || item.m_shared == null)
		{
			return 0f;
		}
		SharedData shared = item.m_shared;
		return Mathf.Max(0f, shared.m_food) + Mathf.Max(0f, shared.m_foodStamina) + Mathf.Max(0f, shared.m_foodEitr);
	}

	public static bool IsHeartyCapable(ItemData item)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Invalid comparison between Unknown and I4
		if (item != null && item.m_shared != null && (int)item.m_shared.m_itemType == 2 && item.m_shared.m_maxQuality <= 1)
		{
			return Value(item) > 0f;
		}
		return false;
	}

	public static bool IsHearty(ItemData item)
	{
		if (item != null && item.m_quality >= 2)
		{
			return IsHeartyCapable(item);
		}
		return false;
	}

	public static bool IsLeftovers(ItemData item)
	{
		return PrefabName(item) == "LynxLeftovers";
	}

	public static bool IsEligibleFood(ItemData item)
	{
		if (!IsHeartyCapable(item) || IsHearty(item))
		{
			return false;
		}
		string text = PrefabName(item);
		if (string.IsNullOrEmpty(text))
		{
			return false;
		}
		return !Excluded().Contains(text);
	}

	public static float Multiplier(ItemData item)
	{
		if (!IsHearty(item))
		{
			return 1f;
		}
		return Plugin.HeartyMultiplier.Value;
	}

	public static float Health(ItemData item)
	{
		return item.m_shared.m_food * Multiplier(item);
	}

	public static float Stamina(ItemData item)
	{
		return item.m_shared.m_foodStamina * Multiplier(item);
	}

	public static float Eitr(ItemData item)
	{
		return item.m_shared.m_foodEitr * Multiplier(item);
	}

	private static HashSet<string> Excluded()
	{
		string text = Plugin.ExcludedFoods.Value ?? "";
		if (_excluded != null && text == _excludedConfigSnapshot)
		{
			return _excluded;
		}
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return _excluded ?? new HashSet<string>();
		}
		HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
		string[] array = text.Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string text2 = array[i].Trim();
			if (text2.Length > 0)
			{
				hashSet.Add(text2);
			}
		}
		int num = 0;
		foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				continue;
			}
			Pickable[] componentsInChildren = prefab.GetComponentsInChildren<Pickable>(true);
			foreach (Pickable val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_itemPrefab != (Object)null && hashSet.Add(((Object)val.m_itemPrefab).name))
				{
					num++;
				}
			}
		}
		_excluded = hashSet;
		_excludedConfigSnapshot = text;
		Plugin.Log.LogInfo((object)$"Food exclusion list built: {hashSet.Count} items ({num} from pickables)");
		return hashSet;
	}
}
internal static class HeartyMultiplyTranspiler
{
	private static readonly Dictionary<MethodBase, Func<CodeInstruction[]>> ItemLoaders = new Dictionary<MethodBase, Func<CodeInstruction[]>>();

	public static bool Patch(Harmony harmony, MethodBase target, Func<CodeInstruction[]> loadItem, string label)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		if (target == null)
		{
			Plugin.Log.LogWarning((object)(label + ": method not found; Hearty numbers there will show base values"));
			return false;
		}
		ItemLoaders[target] = loadItem;
		harmony.Patch(target, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(HeartyMultiplyTranspiler), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
		return true;
	}

	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Expected O, but got Unknown
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Expected O, but got Unknown
		List<CodeInstruction> list = instructions.ToList();
		if (!ItemLoaders.TryGetValue(original, out var value))
		{
			return list;
		}
		HashSet<FieldInfo> hashSet = new HashSet<FieldInfo>
		{
			AccessTools.Field(typeof(SharedData), "m_food"),
			AccessTools.Field(typeof(SharedData), "m_foodStamina"),
			AccessTools.Field(typeof(SharedData), "m_foodEitr")
		};
		MethodInfo methodInfo = AccessTools.Method(typeof(FoodRules), "Multiplier", (Type[])null, (Type[])null);
		int num = 0;
		for (int i = 0; i < list.Count; i++)
		{
			if (!(list[i].opcode != OpCodes.Ldfld) && list[i].operand is FieldInfo item && hashSet.Contains(item))
			{
				List<CodeInstruction> list2 = value().ToList();
				list2.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo));
				list2.Add(new CodeInstruction(OpCodes.Mul, (object)null));
				list.InsertRange(i + 1, list2);
				i += list2.Count;
				num++;
			}
		}
		Plugin.Log.LogDebug((object)$"Hearty multiply inserted in {original.DeclaringType?.Name}.{original.Name}: {num}");
		return list;
	}
}
internal static class PovCompat
{
	public const string Guid = "treextr.pathofvalheiman";

	private static MethodInfo _stamp;

	private static MethodInfo _refresh;

	private static MethodInfo _bonus;

	private static MethodInfo _cookBonuses;

	private static MethodInfo _roll;

	public static bool Active { get; private set; }

	public static void TryApply(Harmony harmony)
	{
		if (!Chainloader.PluginInfos.ContainsKey("treextr.pathofvalheiman"))
		{
			return;
		}
		try
		{
			Type type = AccessTools.TypeByName("PassiveTree.FoodMasteries");
			Type foodType = typeof(Food);
			MethodInfo target = type?.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "Value" && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == foodType);
			FieldInfo foodItem = AccessTools.Field(foodType, "m_item");
			HeartyMultiplyTranspiler.Patch(harmony, target, () => (CodeInstruction[])(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)foodItem)
			}, "PoV food masteries");
			Type type2 = AccessTools.TypeByName("PassiveTree.UI.ItemTooltip");
			MethodInfo target2 = ((type2 != null) ? AccessTools.Method(type2, "MainStats", (Type[])null, (Type[])null) : null);
			HeartyMultiplyTranspiler.Patch(harmony, target2, () => (CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldarg_1, (object)null)
			}, "PoV item tooltip");
			Type type3 = AccessTools.TypeByName("PassiveTree.Credit");
			Type type4 = AccessTools.TypeByName("PassiveTree.Crafting");
			Type type5 = AccessTools.TypeByName("PassiveTree.ChainRolls");
			_stamp = ((type3 != null) ? AccessTools.Method(type3, "Stamp", (Type[])null, (Type[])null) : null);
			_refresh = ((type3 != null) ? AccessTools.Method(type3, "Refresh", (Type[])null, (Type[])null) : null);
			_bonus = ((type3 != null) ? AccessTools.Method(type3, "Bonus", (Type[])null, (Type[])null) : null);
			_cookBonuses = ((type4 != null) ? AccessTools.Method(type4, "CookBonuses", (Type[])null, (Type[])null) : null);
			_roll = ((type5 != null) ? AccessTools.Method(type5, "Roll", (Type[])null, (Type[])null) : null);
			Active = true;
			bool flag = _stamp != null && _refresh != null && _bonus != null && _cookBonuses != null;
			Plugin.Log.LogInfo((object)("Path of Valheiman found: Hearty patched into food masteries/tooltip; cooking credit " + (flag ? "on" : "unavailable")));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Path of Valheiman compatibility failed: " + ex.Message));
		}
	}

	public static void StampLoader(ZNetView view, Player by)
	{
		if (!Active || _stamp == null || _cookBonuses == null || (Object)(object)view == (Object)null || (Object)(object)by == (Object)null)
		{
			return;
		}
		try
		{
			_stamp.Invoke(null, new object[3]
			{
				view,
				by,
				_cookBonuses.Invoke(null, null)
			});
		}
		catch (Exception ex)
		{
			Plugin.Log.LogDebug((object)("PoV credit stamp failed: " + ex.Message));
		}
	}

	public static void Refresh(ZNetView view)
	{
		if (!Active || _refresh == null || _cookBonuses == null || (Object)(object)view == (Object)null)
		{
			return;
		}
		try
		{
			_refresh.Invoke(null, new object[2]
			{
				view,
				_cookBonuses.Invoke(null, null)
			});
		}
		catch (Exception ex)
		{
			Plugin.Log.LogDebug((object)("PoV credit refresh failed: " + ex.Message));
		}
	}

	private static float Bonus(ZNetView view, string what)
	{
		if (!Active || _bonus == null || (Object)(object)view == (Object)null)
		{
			return 0f;
		}
		try
		{
			return (float)_bonus.Invoke(null, new object[2] { view, what });
		}
		catch
		{
			return 0f;
		}
	}

	public static float SpeedFactor(ZNetView view)
	{
		return 1f + Mathf.Max(0f, Bonus(view, "cook"));
	}

	public static int ExtraRolls(ZNetView view, int produced)
	{
		float num = Bonus(view, "extra");
		if (num <= 0f || _roll == null)
		{
			return 0;
		}
		int num2 = 0;
		try
		{
			for (int i = 0; i < produced; i++)
			{
				num2 += (int)_roll.Invoke(null, new object[1] { num });
			}
		}
		catch
		{
		}
		return num2;
	}
}
internal static class SeneaLCompat
{
	public const string Guid = "seneaL.valheim.ui";

	private const string MarkerName = "lynx_hearty";

	private static FieldInfo _root;

	private static FieldInfo _count;

	public static void TryApply(Harmony harmony)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Expected O, but got Unknown
		if (!Chainloader.PluginInfos.ContainsKey("seneaL.valheim.ui"))
		{
			return;
		}
		try
		{
			int num = 0;
			Type type = AccessTools.TypeByName("SeneaLUI.Inv.Tips");
			MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "Food", new Type[1] { typeof(ItemData) }, (Type[])null) : null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(FoodStatPatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			Type type2 = AccessTools.TypeByName("SeneaLUI.Components.Slot");
			MethodInfo methodInfo2 = ((type2 != null) ? AccessTools.Method(type2, "Set", new Type[1] { typeof(ItemData) }, (Type[])null) : null);
			_root = ((type2 != null) ? AccessTools.Field(type2, "Root") : null);
			_count = ((type2 != null) ? AccessTools.Field(type2, "_count") : null);
			if (methodInfo2 != null && _root != null && _count != null)
			{
				harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(SeneaLCompat), "SlotSetPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			Plugin.Log.LogInfo((object)$"SeneaL UI found: applied {num}/2 Hearty display patches");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("SeneaL UI compatibility failed: " + ex.Message));
		}
	}

	private static void SlotSetPostfix(object __instance, ItemData item)
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: 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_00ba: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			object? value = _root.GetValue(__instance);
			RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			bool flag = FoodRules.IsHearty(item);
			Transform val2 = ((Transform)val).Find("lynx_hearty");
			if ((Object)(object)val2 == (Object)null)
			{
				if (!flag)
				{
					return;
				}
				object? value2 = _count.GetValue(__instance);
				TextMeshProUGUI val3 = (TextMeshProUGUI)((value2 is TextMeshProUGUI) ? value2 : null);
				if ((Object)(object)val3 == (Object)null)
				{
					return;
				}
				GameObject obj = Object.Instantiate<GameObject>(((Component)val3).gameObject, (Transform)(object)val, false);
				((Object)obj).name = "lynx_hearty";
				TextMeshProUGUI component = obj.GetComponent<TextMeshProUGUI>();
				((TMP_Text)component).text = "<color=#FFB060>H</color>";
				((TMP_Text)component).alignment = (TextAlignmentOptions)1025;
				RectTransform val4 = (RectTransform)obj.transform;
				val4.anchorMin = Vector2.zero;
				val4.anchorMax = Vector2.zero;
				val4.pivot = Vector2.zero;
				val4.anchoredPosition = new Vector2(4f, 2f);
				val4.sizeDelta = new Vector2(24f, 20f);
				val2 = obj.transform;
			}
			if (((Component)val2).gameObject.activeSelf != flag)
			{
				((Component)val2).gameObject.SetActive(flag);
			}
		}
		catch
		{
		}
	}
}
[HarmonyPatch]
internal static class FoodStatPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		yield return AccessTools.Method(typeof(Player), "EatFood", (Type[])null, (Type[])null);
		yield return AccessTools.Method(typeof(Player), "UpdateFood", (Type[])null, (Type[])null);
		MethodInfo methodInfo = AccessTools.GetDeclaredMethods(typeof(ItemData)).FirstOrDefault((MethodInfo m) => m.Name.Contains("printConsumable"));
		if (methodInfo != null)
		{
			yield return methodInfo;
		}
		else
		{
			Plugin.Log.LogWarning((object)"Tooltip consumable printer not found; Hearty tooltip numbers will show base values");
		}
	}

	internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original, ILGenerator generator)
	{
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Expected O, but got Unknown
		List<CodeInstruction> list = instructions.ToList();
		FieldInfo fieldInfo = AccessTools.Field(typeof(ItemData), "m_shared");
		Dictionary<FieldInfo, MethodInfo> dictionary = new Dictionary<FieldInfo, MethodInfo>
		{
			{
				AccessTools.Field(typeof(SharedData), "m_food"),
				AccessTools.Method(typeof(FoodRules), "Health", (Type[])null, (Type[])null)
			},
			{
				AccessTools.Field(typeof(SharedData), "m_foodStamina"),
				AccessTools.Method(typeof(FoodRules), "Stamina", (Type[])null, (Type[])null)
			},
			{
				AccessTools.Field(typeof(SharedData), "m_foodEitr"),
				AccessTools.Method(typeof(FoodRules), "Eitr", (Type[])null, (Type[])null)
			}
		};
		int num = 0;
		LocalBuilder localBuilder = null;
		for (int i = 0; i < list.Count - 1; i++)
		{
			if (!CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false))
			{
				continue;
			}
			CodeInstruction val = list[i + 1];
			if (!(val.operand is FieldInfo key) || !dictionary.TryGetValue(key, out var value))
			{
				continue;
			}
			if (val.opcode == OpCodes.Ldfld)
			{
				list[i].opcode = OpCodes.Call;
				list[i].operand = value;
				val.opcode = OpCodes.Nop;
				val.operand = null;
				num++;
			}
			else if (val.opcode == OpCodes.Ldflda)
			{
				if (localBuilder == null)
				{
					localBuilder = generator.DeclareLocal(typeof(float));
				}
				list[i].opcode = OpCodes.Call;
				list[i].operand = value;
				val.opcode = OpCodes.Stloc;
				val.operand = localBuilder;
				list.Insert(i + 2, new CodeInstruction(OpCodes.Ldloca, (object)localBuilder));
				num++;
			}
		}
		Plugin.Log.LogDebug((object)$"Hearty stat reads patched in {original.Name}: {num}");
		return list;
	}
}
internal static class PlayerAccess
{
	private static readonly FieldInfo FoodsField = AccessTools.Field(typeof(Player), "m_foods");

	public static List<Food> Foods(Player p)
	{
		return (List<Food>)FoodsField.GetValue(p);
	}
}
[HarmonyPatch(typeof(Player), "EatFood")]
internal static class EatFoodPatch
{
	private static List<Food> Foods(Player p)
	{
		return PlayerAccess.Foods(p);
	}

	private static void Postfix(Player __instance, ItemData item, bool __result)
	{
		if (!__result || item == null || !FoodRules.IsHeartyCapable(item))
		{
			return;
		}
		foreach (Food item2 in Foods(__instance))
		{
			if (item2.m_item != null && !(item2.m_item.m_shared.m_name != item.m_shared.m_name))
			{
				ItemData val = item.Clone();
				val.m_stack = 1;
				item2.m_item = val;
			}
		}
	}
}
[HarmonyPatch]
internal static class SaveLoadPatch
{
	private const string Key = "LynxLeftovers.HeartyFoods";

	private static List<Food> Foods(Player p)
	{
		return PlayerAccess.Foods(p);
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Player), "Save")]
	private static void SavePrefix(Player __instance)
	{
		List<string> list = (from f in Foods(__instance)
			where FoodRules.IsHearty(f.m_item)
			select f.m_name).ToList();
		if (list.Count > 0)
		{
			__instance.m_customData["LynxLeftovers.HeartyFoods"] = string.Join("|", list);
		}
		else
		{
			__instance.m_customData.Remove("LynxLeftovers.HeartyFoods");
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Player), "Load")]
	private static void LoadPostfix(Player __instance)
	{
		if (!__instance.m_customData.TryGetValue("LynxLeftovers.HeartyFoods", out var value) || string.IsNullOrEmpty(value))
		{
			return;
		}
		HashSet<string> hashSet = new HashSet<string>(value.Split('|'));
		foreach (Food item in Foods(__instance))
		{
			if (item.m_item != null && hashSet.Contains(item.m_name))
			{
				ItemData val = item.m_item.Clone();
				val.m_quality = 2;
				item.m_item = val;
			}
		}
	}
}
[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
{
	typeof(ItemData),
	typeof(int),
	typeof(bool),
	typeof(float),
	typeof(int),
	typeof(bool)
})]
internal static class TooltipPatch
{
	private static void Postfix(ItemData item, ref string __result)
	{
		if (FoodRules.IsHearty(item))
		{
			int num = Mathf.RoundToInt((Plugin.HeartyMultiplier.Value - 1f) * 100f);
			__result = $"<color=#FFB060>Hearty</color>: +{num}% health, stamina and eitr\n\n" + __result;
		}
	}
}
[HarmonyPatch(typeof(ItemDrop), "GetHoverName")]
internal static class GroundNamePatch
{
	private static void Postfix(ItemDrop __instance, ref string __result)
	{
		if (FoodRules.IsHearty(__instance.m_itemData))
		{
			__result = "Hearty " + __result;
		}
	}
}
[HarmonyPatch(typeof(ItemData), "IsSameType")]
internal static class SameTypePatch
{
	private static void Postfix(ItemData __instance, ItemData other, ref bool __result)
	{
		if (__result && other != null && __instance.m_quality != other.m_quality && FoodRules.IsHeartyCapable(__instance))
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
internal static class GridMergePatch
{
	private static readonly FieldInfo InvField = AccessTools.Field(typeof(InventoryGrid), "m_inventory");

	private static Inventory Inv(InventoryGrid g)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		return (Inventory)InvField.GetValue(g);
	}

	private static bool Prefix(InventoryGrid __instance, ItemData item, Vector2i pos, ref bool __result)
	{
		//IL_000d: 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)
		Inventory obj = Inv(__instance);
		ItemData val = ((obj != null) ? obj.GetItemAt(pos.x, pos.y) : null);
		if (val == null || val == item || item == null)
		{
			return true;
		}
		if (val.m_shared.m_name != item.m_shared.m_name || val.m_quality == item.m_quality)
		{
			return true;
		}
		if (!FoodRules.IsHeartyCapable(item))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
internal static class GridMarkerPatch
{
	private const string MarkerName = "lynx_hearty";

	private static readonly FieldInfo InvField = AccessTools.Field(typeof(InventoryGrid), "m_inventory");

	private static readonly FieldInfo ElementsField = AccessTools.Field(typeof(InventoryGrid), "m_elements");

	private static void Postfix(InventoryGrid __instance)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		Inventory val = (Inventory)InvField.GetValue(__instance);
		List<InventoryElement> list = (List<InventoryElement>)ElementsField.GetValue(__instance);
		if (val == null || list == null)
		{
			return;
		}
		foreach (InventoryElement item in list)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item.m_quality == (Object)null)
			{
				continue;
			}
			bool flag = FoodRules.IsHearty(val.GetItemAt(item.Position.x, item.Position.y));
			Transform val2 = item.m_quality.transform.parent.Find("lynx_hearty");
			if ((Object)(object)val2 == (Object)null)
			{
				if (!flag)
				{
					continue;
				}
				val2 = CreateMarker(item);
			}
			if (((Component)val2).gameObject.activeSelf != flag)
			{
				((Component)val2).gameObject.SetActive(flag);
			}
		}
	}

	private static Transform CreateMarker(InventoryElement el)
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		GameObject obj = Object.Instantiate<GameObject>(((Component)el.m_quality).gameObject, el.m_quality.transform.parent, false);
		((Object)obj).name = "lynx_hearty";
		TMP_Text component = obj.GetComponent<TMP_Text>();
		((Behaviour)component).enabled = true;
		component.text = "<color=#FFB060>H</color>";
		component.alignment = (TextAlignmentOptions)1025;
		RectTransform val = (RectTransform)obj.transform;
		val.anchorMin = new Vector2(0f, 0f);
		val.anchorMax = new Vector2(0f, 0f);
		val.pivot = new Vector2(0f, 0f);
		val.anchoredPosition = new Vector2(3f, 1f);
		val.sizeDelta = new Vector2(24f, 20f);
		return obj.transform;
	}
}
[HarmonyPatch(typeof(Container), "Interact")]
internal static class ContainerAltInteractPatch
{
	private static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		LeftoverStation component = ((Component)__instance).GetComponent<LeftoverStation>();
		if ((Object)(object)component == (Object)null)
		{
			return true;
		}
		if (!alt)
		{
			if (!hold && (Object)(object)character == (Object)(object)Player.m_localPlayer)
			{
				PovCompat.StampLoader(((Component)__instance).GetComponent<ZNetView>(), (Player)character);
			}
			return true;
		}
		if (!hold)
		{
			component.RequestTakeOutput();
		}
		__result = true;
		return false;
	}
}
[HarmonyPatch(typeof(ItemStand), "CanAttach")]
internal static class ItemStandPatch
{
	private static void Postfix(ItemData item, ref bool __result)
	{
		if (!__result && FoodRules.IsLeftovers(item) && !((Object)(object)item.m_dropPrefab == (Object)null))
		{
			__result = (Object)(object)ItemStand.GetAttachPrefab(item.m_dropPrefab) != (Object)null;
		}
	}
}
[HarmonyPatch(typeof(Container), "GetHoverText")]
internal static class ContainerHoverPatch
{
	private static void Postfix(Container __instance, ref string __result)
	{
		LeftoverStation component = ((Component)__instance).GetComponent<LeftoverStation>();
		if ((Object)(object)component != (Object)null)
		{
			__result += component.StatusText();
		}
	}
}
[BepInPlugin("lynx.lynxleftovers", "LynxLeftovers", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "lynx.lynxleftovers";

	public const string ModName = "LynxLeftovers";

	public const string Version = "1.0.1";

	public const string BuildLabel = "1.0.1";

	public static Plugin Instance;

	public static ManualLogSource Log;

	public static ConfigEntry<float> PointsPerLeftover;

	public static ConfigEntry<float> GrindSeconds;

	public static ConfigEntry<float> StewSeconds;

	public static ConfigEntry<float> StewCostRatio;

	public static ConfigEntry<float> HeartyMultiplier;

	public static ConfigEntry<string> ExcludedFoods;

	public static ConfigEntry<float> MaxCatchUpMinutes;

	public static ConfigEntry<string> BuildCategory;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_0011: 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_001e: Expected O, but got Unknown
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Expected O, but got Unknown
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Expected O, but got Unknown
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Expected O, but got Unknown
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Expected O, but got Unknown
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Expected O, but got Unknown
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};
		PointsPerLeftover = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "PointsPerLeftover", 100f, new ConfigDescription("Food value (health + stamina + eitr) that makes one Leftovers. The Stewpot uses the same unit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 1000f), new object[1] { val }));
		GrindSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "GrindSeconds", 10f, new ConfigDescription("Seconds the Meat Grinder takes per food item.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), new object[1] { val }));
		StewSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "StewSeconds", 30f, new ConfigDescription("Seconds the Stewpot takes to make one food item Hearty.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 600f), new object[1] { val }));
		StewCostRatio = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "StewCostRatio", 1f, new ConfigDescription("Leftovers cost to make a food Hearty, as a multiple of that food's own value. 1.0 = one food's worth of scraps upgrades one food of equal worth.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), new object[1] { val }));
		HeartyMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "HeartyMultiplier", 1.15f, new ConfigDescription("Multiplier applied to a Hearty food's health, stamina and eitr. Duration is unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), new object[1] { val }));
		ExcludedFoods = ((BaseUnityPlugin)this).Config.Bind<string>("Balance", "ExcludedFoods", "Honey", new ConfigDescription("Comma-separated item prefab names the grinder and Stewpot refuse, in addition to anything that comes off a pickable plant/bush.", (AcceptableValueBase)null, new object[1] { val }));
		MaxCatchUpMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "MaxCatchUpMinutes", 60f, new ConfigDescription("When a station's area loads after being away, it catches up on at most this many minutes of work.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1440f), new object[1] { val }));
		BuildCategory = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BuildCategory", "Leftovers", "Hammer menu tab for the Meat Grinder and Stock Cask. Any non-vanilla name gives them their own tab (default: Leftovers). Vanilla tab names (Misc, Crafting, Furniture...) are accepted but may only show them under the All tab. Restart to apply.");
		AddLocalization();
		PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
		_harmony = new Harmony("lynx.lynxleftovers");
		_harmony.PatchAll(typeof(Plugin).Assembly);
		Log.LogInfo((object)"LynxLeftovers 1.0.1 loaded");
	}

	private void Start()
	{
		DrawersCompat.TryApply(_harmony);
		PovCompat.TryApply(_harmony);
		SeneaLCompat.TryApply(_harmony);
	}

	private void OnVanillaPrefabsAvailable()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
		try
		{
			Content.Register();
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Failed to register LynxLeftovers content: " + ex));
		}
	}

	private static void AddLocalization()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "item_lynx_leftovers", "Leftovers" },
			{ "item_lynx_leftovers_desc", "Ground-up scraps of old meals. Rendered into stock in a Stock Cask." },
			{ "piece_lynx_grinder", "Meat Grinder" },
			{ "piece_lynx_grinder_desc", "Put cooked food you'll never eat inside. It grinds it into Leftovers." },
			{ "piece_lynx_stockcask", "Stock Cask" },
			{ "piece_lynx_stockcask_desc", "Put Leftovers and a food stack inside. The Leftovers become stock, and food steeped in it comes out Hearty." },
			{ "lynx_hearty", "Hearty" }
		});
	}
}
public abstract class LeftoverStation : MonoBehaviour
{
	protected const string KeyLast = "lynx_last";

	protected const string KeyProgress = "lynx_progress";

	protected const string KeyPoints = "lynx_points";

	protected const string KeyActive = "lynx_active";

	protected const string KeyStatus = "lynx_status";

	protected const string KeyOutput = "lynx_out";

	private const string RpcTake = "LynxLeftovers_TakeOutput";

	public GameObject m_activeVisual;

	public Transform m_outputPoint;

	public Transform[] m_spinY;

	public Transform[] m_spinZ;

	public float m_spinYSpeed = 120f;

	public float m_spinZSpeed = -360f;

	protected ZNetView m_nview;

	protected Container m_container;

	private float m_tickTimer;

	private const string KeyOutInv = "lynx_outinv";

	protected abstract int OutputQuality { get; }

	protected virtual void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_container = ((Component)this).GetComponent<Container>();
		if ((Object)(object)m_nview != (Object)null && m_nview.GetZDO() != null)
		{
			m_nview.Register("LynxLeftovers_TakeOutput", (Action<long>)RPC_TakeOutput);
		}
		WearNTear component = ((Component)this).GetComponent<WearNTear>();
		if ((Object)(object)component != (Object)null)
		{
			component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyedPiece));
		}
	}

	private static Inventory LoadOut(ZDO zdo)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		Inventory val = new Inventory("lynx_out", (Sprite)null, 8, 8);
		byte[] byteArray = zdo.GetByteArray("lynx_outinv", (byte[])null);
		if (byteArray != null && byteArray.Length != 0)
		{
			val.Load(new ZPackage(byteArray));
		}
		return val;
	}

	private static void SaveOut(ZDO zdo, Inventory inv)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		ZPackage val = new ZPackage();
		inv.Save(val);
		zdo.Set("lynx_outinv", val.GetArray());
	}

	protected void AddOutput(ZDO zdo, ItemData item)
	{
		Inventory val = LoadOut(zdo);
		MigrateOldOutput(zdo, val);
		if (!val.AddItem(item))
		{
			DropItemStack(item, item.m_stack);
		}
		foreach (ItemData item2 in val.GetAllItems().ToList())
		{
			int num = Mathf.Max(1, item2.m_shared.m_maxStackSize);
			if (item2.m_stack >= num)
			{
				DropItemStack(item2, item2.m_stack);
				val.RemoveItem(item2);
			}
		}
		SaveOut(zdo, val);
	}

	protected static ItemData NewItem(string prefab, int count)
	{
		GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
		if ((Object)(object)val2 == (Object)null)
		{
			return null;
		}
		ItemData obj = val2.m_itemData.Clone();
		obj.m_dropPrefab = val;
		obj.m_stack = count;
		return obj;
	}

	private void MigrateOldOutput(ZDO zdo, Inventory inv)
	{
		string text = zdo.GetString("lynx_out", "");
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		string[] array = text.Split('|');
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(':');
			if (array2.Length != 2 || !int.TryParse(array2[1], out var result) || result <= 0)
			{
				continue;
			}
			ItemData val = NewItem(array2[0], result);
			if (val != null)
			{
				val.m_quality = OutputQuality;
				if (!inv.AddItem(val))
				{
					DropItemStack(val, result);
				}
			}
		}
		zdo.Set("lynx_out", "");
	}

	private void DropAllOutput()
	{
		ZDO zDO = m_nview.GetZDO();
		Inventory val = LoadOut(zDO);
		MigrateOldOutput(zDO, val);
		foreach (ItemData item in val.GetAllItems().ToList())
		{
			DropItemStack(item, item.m_stack);
		}
		val.RemoveAll();
		SaveOut(zDO, val);
	}

	private void DropItemStack(ItemData item, int count)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		if (item != null && count > 0)
		{
			ItemDrop.DropItem(item, count, OutputPos(), Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
		}
	}

	public void RequestTakeOutput()
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
		{
			m_nview.InvokeRPC("LynxLeftovers_TakeOutput", Array.Empty<object>());
		}
	}

	private void RPC_TakeOutput(long sender)
	{
		if (m_nview.IsOwner())
		{
			DropAllOutput();
		}
	}

	private void OnDestroyedPiece()
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner())
		{
			DropAllOutput();
		}
	}

	protected string OutputText()
	{
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return "";
		}
		ZDO zDO = m_nview.GetZDO();
		List<string> list = (from it in LoadOut(zDO).GetAllItems()
			select string.Format("{0} {1}{2}", it.m_stack, FoodRules.IsHearty(it) ? "Hearty " : "", Localize(it.m_shared.m_name))).ToList();
		if (!string.IsNullOrEmpty(zDO.GetString("lynx_out", "")))
		{
			list.Add("(older items)");
		}
		if (list.Count == 0)
		{
			return "";
		}
		return "\nReady: " + string.Join(", ", list) + "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] Take it out now";
	}

	protected virtual void Update()
	{
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return;
		}
		bool flag = m_nview.GetZDO().GetBool("lynx_active", false);
		if ((Object)(object)m_activeVisual != (Object)null && m_activeVisual.activeSelf != flag)
		{
			m_activeVisual.SetActive(flag);
		}
		if (flag)
		{
			float deltaTime = Time.deltaTime;
			if (m_spinY != null)
			{
				Transform[] spinY = m_spinY;
				foreach (Transform val in spinY)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						val.Rotate(0f, m_spinYSpeed * deltaTime, 0f, (Space)1);
					}
				}
			}
			if (m_spinZ != null)
			{
				Transform[] spinY = m_spinZ;
				foreach (Transform val2 in spinY)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						val2.Rotate(0f, 0f, m_spinZSpeed * deltaTime, (Space)1);
					}
				}
			}
		}
		if (!m_nview.IsOwner())
		{
			return;
		}
		m_tickTimer += Time.deltaTime;
		if (m_tickTimer < 1f)
		{
			return;
		}
		m_tickTimer = 0f;
		ZDO zDO = m_nview.GetZDO();
		DateTime time = ZNet.instance.GetTime();
		long num = zDO.GetLong("lynx_last", 0L);
		float dt = 1f;
		if (num != 0L)
		{
			dt = (float)(time - new DateTime(num)).TotalSeconds;
			dt = Mathf.Clamp(dt, 0f, Plugin.MaxCatchUpMinutes.Value * 60f + 1f);
		}
		zDO.Set("lynx_last", time.Ticks);
		Inventory val3 = (((Object)(object)m_container != (Object)null) ? m_container.GetInventory() : null);
		if (val3 == null)
		{
			return;
		}
		PovCompat.Refresh(m_nview);
		try
		{
			Tick(zDO, val3, dt);
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"{((Object)this).name} tick failed: {arg}");
		}
	}

	protected abstract void Tick(ZDO zdo, Inventory inv, float dt);

	public abstract string StatusText();

	protected static ItemData FindFirst(Inventory inv, Func<ItemData, bool> pred)
	{
		ItemData val = null;
		foreach (ItemData allItem in inv.GetAllItems())
		{
			if (pred(allItem) && (val == null || allItem.m_gridPos.y < val.m_gridPos.y || (allItem.m_gridPos.y == val.m_gridPos.y && allItem.m_gridPos.x < val.m_gridPos.x)))
			{
				val = allItem;
			}
		}
		return val;
	}

	protected Vector3 OutputPos()
	{
		//IL_002b: 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_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_003f: Unknown result type (might be due to invalid IL or missing references)
		return (((Object)(object)m_outputPoint != (Object)null) ? m_outputPoint.position : (((Component)this).transform.position + Vector3.up)) + Random.insideUnitSphere * 0.05f;
	}

	protected static string Localize(string s)
	{
		if (Localization.instance == null)
		{
			return s;
		}
		return Localization.instance.Localize(s);
	}
}
public class MeatGrinder : LeftoverStation
{
	protected override int OutputQuality => 1;

	protected override void Tick(ZDO zdo, Inventory inv, float dt)
	{
		float num = zdo.GetFloat("lynx_progress", 0f) + dt;
		float num2 = zdo.GetFloat("lynx_points", 0f);
		float num3 = Mathf.Max(0.1f, Plugin.GrindSeconds.Value) / PovCompat.SpeedFactor(m_nview);
		float num4 = Mathf.Max(1f, Plugin.PointsPerLeftover.Value);
		bool flag = false;
		string text = "";
		int num5 = 0;
		int num6 = 1000;
		while (num6-- > 0)
		{
			ItemData val = LeftoverStation.FindFirst(inv, FoodRules.IsEligibleFood);
			if (val == null)
			{
				num = 0f;
				break;
			}
			flag = true;
			text = val.m_shared.m_name;
			if (num < num3)
			{
				break;
			}
			num -= num3;
			num2 += FoodRules.Value(val);
			inv.RemoveItem(val, 1);
			while (num2 >= num4)
			{
				num2 -= num4;
				num5++;
			}
		}
		if (num5 > 0)
		{
			num5 += PovCompat.ExtraRolls(m_nview, num5);
			ItemData val2 = LeftoverStation.NewItem("LynxLeftovers", num5);
			if (val2 != null)
			{
				AddOutput(zdo, val2);
			}
		}
		zdo.Set("lynx_progress", num);
		zdo.Set("lynx_points", num2);
		zdo.Set("lynx_active", flag);
		zdo.Set("lynx_status", text);
	}

	public override string StatusText()
	{
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return "";
		}
		ZDO zDO = m_nview.GetZDO();
		float num = 100f * zDO.GetFloat("lynx_points", 0f) / Mathf.Max(1f, Plugin.PointsPerLeftover.Value);
		string arg = (zDO.GetBool("lynx_active", false) ? ("Grinding: " + LeftoverStation.Localize(zDO.GetString("lynx_status", ""))) : "<color=#a0a0a0>Idle - add cooked food</color>");
		return LeftoverStation.Localize($"\n{arg}\nNext Leftovers: {num:0}%" + OutputText());
	}
}
public class Stewpot : LeftoverStation
{
	protected override int OutputQuality => 2;

	protected override void Tick(ZDO zdo, Inventory inv, float dt)
	{
		float num = zdo.GetFloat("lynx_progress", 0f) + dt;
		float num2 = zdo.GetFloat("lynx_points", 0f);
		float num3 = Mathf.Max(0.1f, Plugin.StewSeconds.Value) / PovCompat.SpeedFactor(m_nview);
		float num4 = Mathf.Max(1f, Plugin.PointsPerLeftover.Value);
		bool flag = false;
		string text = "";
		int num5 = 1000;
		while (num5-- > 0)
		{
			ItemData val = LeftoverStation.FindFirst(inv, FoodRules.IsEligibleFood);
			if (val == null)
			{
				num = 0f;
				text = "";
				break;
			}
			float num6;
			for (num6 = FoodRules.Value(val) * Plugin.StewCostRatio.Value / num4; num2 + 0.0001f < num6; num2 += 1f)
			{
				ItemData val2 = LeftoverStation.FindFirst(inv, FoodRules.IsLeftovers);
				if (val2 == null)
				{
					break;
				}
				inv.RemoveItem(val2, 1);
			}
			if (num2 + 0.0001f < num6)
			{
				num = 0f;
				text = "!" + val.m_shared.m_name + "|" + num6.ToString("0.00");
				break;
			}
			flag = true;
			text = val.m_shared.m_name + "|" + num6.ToString("0.00");
			if (num < num3)
			{
				break;
			}
			num -= num3;
			num2 = Mathf.Max(0f, num2 - num6);
			ItemData val3 = val.Clone();
			val3.m_stack = 1;
			val3.m_quality = 2;
			inv.RemoveItem(val, 1);
			AddOutput(zdo, val3);
		}
		zdo.Set("lynx_progress", num);
		zdo.Set("lynx_points", num2);
		zdo.Set("lynx_active", flag);
		zdo.Set("lynx_status", text);
	}

	public override string StatusText()
	{
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return "";
		}
		ZDO zDO = m_nview.GetZDO();
		float num = zDO.GetFloat("lynx_points", 0f);
		string text = zDO.GetString("lynx_status", "");
		string arg;
		if (string.IsNullOrEmpty(text))
		{
			arg = "<color=#a0a0a0>Idle - add Leftovers and a food stack</color>";
		}
		else
		{
			bool flag = text.StartsWith("!");
			string[] array = text.TrimStart('!').Split('|');
			string text2 = LeftoverStation.Localize(array[0]);
			string text3 = ((array.Length > 1) ? array[1] : "?");
			arg = (flag ? ("<color=#ff8060>Needs " + text3 + " stock for " + text2 + "</color>") : ("Steeping: " + text2 + " (uses " + text3 + " stock)"));
		}
		float num2 = 0f;
		if ((Object)(object)m_container != (Object)null && m_container.GetInventory() != null)
		{
			foreach (ItemData allItem in m_container.GetInventory().GetAllItems())
			{
				if (FoodRules.IsLeftovers(allItem))
				{
					num2 += (float)allItem.m_stack;
				}
			}
		}
		return LeftoverStation.Localize($"\n{arg}\nStock: {num + num2:0.00}" + OutputText());
	}
}