Decompiled source of PotatoFarmer v1.2.0

plugins/PotatoFarmer.dll

Decompiled 5 hours 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.Text;
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 UnityEngine;
using UnityEngine.Rendering;

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

internal static class Assets
{
	internal static string Dir;

	internal static Mesh LoadMesh(string name, float size = 1f)
	{
		//IL_00bf: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Expected O, but got Unknown
		string text = Path.Combine(Dir, name + ".mesh");
		if (!File.Exists(text))
		{
			Plugin.Log.LogError((object)("Missing " + text));
			return null;
		}
		using BinaryReader binaryReader = new BinaryReader(File.OpenRead(text));
		if (new string(binaryReader.ReadChars(4)) != "PTM1")
		{
			Plugin.Log.LogError((object)(text + " isn't a model file from convert.py."));
			return null;
		}
		int num = binaryReader.ReadInt32();
		int num2 = binaryReader.ReadInt32();
		Vector3[] array = (Vector3[])(object)new Vector3[num];
		Vector3[] array2 = (Vector3[])(object)new Vector3[num];
		Vector2[] array3 = (Vector2[])(object)new Vector2[num];
		int[] array4 = new int[num2];
		for (int i = 0; i < num; i++)
		{
			array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()) * size;
		}
		for (int j = 0; j < num; j++)
		{
			array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
		}
		for (int k = 0; k < num; k++)
		{
			array3[k] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
		}
		for (int l = 0; l < num2; l++)
		{
			array4[l] = binaryReader.ReadInt32();
		}
		Mesh val = new Mesh
		{
			name = "potato_" + name
		};
		if (num > 65535)
		{
			val.indexFormat = (IndexFormat)1;
		}
		val.vertices = array;
		val.normals = array2;
		val.uv = array3;
		val.triangles = array4;
		val.RecalculateTangents();
		val.RecalculateBounds();
		return val;
	}
}
internal sealed class PieceLook
{
	internal readonly Material Material;

	internal PieceLook(string name, float brightness, float shine, string templateName = "ironchest", Color? metalColor = null, float valueNoise = -1f)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_002f: 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_0175: Unknown result type (might be due to invalid IL or missing references)
		Material prefab = Cache.GetPrefab<Material>(templateName);
		Material = (Object.op_Implicit((Object)(object)prefab) ? new Material(prefab) : new Material(Shader.Find("Custom/Piece") ?? Shader.Find("Standard")));
		if (!Object.op_Implicit((Object)(object)prefab))
		{
			Plugin.Log.LogWarning((object)("The material " + templateName + " wasn't found; using a plain one."));
		}
		((Object)Material).name = "potato_" + name;
		if (Material.HasProperty("_Metallic"))
		{
			Material.SetFloat("_Metallic", 1f);
		}
		if (Material.HasProperty("_BumpScale"))
		{
			Material.SetFloat("_BumpScale", 1f);
		}
		if (Material.HasProperty("_Color"))
		{
			Material.SetColor("_Color", new Color(brightness, brightness, brightness, 1f));
		}
		if (shine >= 0f && Material.HasProperty("_MetallicAlphaGloss"))
		{
			Material.SetFloat("_MetallicAlphaGloss", shine);
		}
		if (shine >= 0f && Material.HasProperty("_GlossMapScale"))
		{
			Material.SetFloat("_GlossMapScale", shine);
		}
		if (metalColor.HasValue && Material.HasProperty("_MetalColor"))
		{
			Material.SetColor("_MetalColor", metalColor.Value);
		}
		if (valueNoise >= 0f && Material.HasProperty("_ValueNoise"))
		{
			Material.SetFloat("_ValueNoise", valueNoise);
		}
		if (valueNoise >= 0f && Material.HasProperty("_ValueNoiseVertex"))
		{
			Material.SetFloat("_ValueNoiseVertex", 0f);
		}
		if (!GUIManager.IsHeadless())
		{
			SetTexture("_MainTex", name + "_d.png", linear: false);
			SetTexture("_BumpMap", name + "_n.png", linear: true);
			Texture2D val = SetTexture("_MetallicTex", name + "_m.png", linear: true);
			if (Object.op_Implicit((Object)(object)val) && Material.HasProperty("_MetallicGlossMap"))
			{
				Material.SetTexture("_MetallicGlossMap", (Texture)(object)val);
			}
		}
	}

	private Texture2D SetTexture(string property, string file, bool linear)
	{
		//IL_0040: 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_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		if (!Material.HasProperty(property))
		{
			return null;
		}
		string text = Path.Combine(Assets.Dir, file);
		if (!File.Exists(text))
		{
			Plugin.Log.LogWarning((object)("Missing " + text));
			return null;
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear)
		{
			name = Path.GetFileNameWithoutExtension(file),
			wrapMode = (TextureWrapMode)0
		};
		if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text), true))
		{
			Plugin.Log.LogWarning((object)("Couldn't read " + text));
			return null;
		}
		((Texture)val).filterMode = (FilterMode)0;
		Material.SetTexture(property, (Texture)(object)val);
		return val;
	}
}
public class Cask : MonoBehaviour, Hoverable, Interactable
{
	private struct Batch
	{
		public string Prefab;

		public long Start;
	}

	private const string BatchesKey = "PotatoCask.Batches";

	private const float TapDelay = 1.5f;

	private const float CoverEvery = 10f;

	internal const float Size = 1.5f;

	private static readonly Vector3 OutputPoint = new Vector3(-1.05f, 0.58f, 0f);

	private static readonly Vector3 RoofCheck = new Vector3(0f, 2.15f, 0f);

	private static Fermenter fermenter;

	private ZNetView view;

	private float nextCover;

	private float nextCheck;

	private bool exposed;

	private bool hasRoof = true;

	private bool Valid
	{
		get
		{
			if (Object.op_Implicit((Object)(object)view))
			{
				return view.IsValid();
			}
			return false;
		}
	}

	private void Awake()
	{
		view = ((Component)this).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)view) && view.GetZDO() != null)
		{
			view.Register<string, int>("PotatoCask_Add", (Action<long, string, int>)RPC_Add);
			view.Register("PotatoCask_Tap", (Action<long>)RPC_Tap);
			view.Register<string, int>("PotatoCask_Give", (Action<long, string, int>)RPC_Give);
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
			}
		}
	}

	private static Fermenter Fermenter()
	{
		if (Object.op_Implicit((Object)(object)fermenter))
		{
			return fermenter;
		}
		GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab("fermenter") : null);
		fermenter = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Fermenter>() : null);
		return fermenter;
	}

	private static ItemConversion Recipe(string prefab)
	{
		return Fermenter()?.m_conversion?.FirstOrDefault((Func<ItemConversion, bool>)((ItemConversion c) => c != null && Object.op_Implicit((Object)(object)c.m_from) && ((Object)((Component)c.m_from).gameObject).name == prefab));
	}

	private static float TweaksSetting(string key)
	{
		try
		{
			ConfigEntry<float> val = default(ConfigEntry<float>);
			if (Chainloader.PluginInfos.TryGetValue("potato.tweaks", out var value) && Object.op_Implicit((Object)(object)value.Instance) && value.Instance.Config.TryGetEntry<float>("13 - Fermenters", key, ref val))
			{
				return Mathf.Max(0.1f, val.Value);
			}
		}
		catch (Exception)
		{
		}
		return 1f;
	}

	private static float Duration()
	{
		return (Object.op_Implicit((Object)(object)Fermenter()) ? Fermenter().m_fermentationDuration : 2400f) / TweaksSetting("Speed");
	}

	private static int Yield(ItemConversion recipe)
	{
		return Math.Max(1, Mathf.RoundToInt((float)recipe.m_producedItems * TweaksSetting("Output")));
	}

	private List<Batch> Read()
	{
		List<Batch> list = new List<Batch>();
		if (!Valid)
		{
			return list;
		}
		string[] array = view.GetZDO().GetString("PotatoCask.Batches", "").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			int num = text.LastIndexOf('@');
			if (num > 0 && long.TryParse(text.Substring(num + 1), out var result))
			{
				list.Add(new Batch
				{
					Prefab = text.Substring(0, num),
					Start = result
				});
			}
		}
		return list;
	}

	private void Write(List<Batch> batches)
	{
		view.GetZDO().Set("PotatoCask.Batches", string.Join(";", batches.Select((Batch b) => b.Prefab + "@" + b.Start).ToArray()));
	}

	private static string Brewing(List<Batch> batches)
	{
		if (!Plugin.CaskMix.Value && batches.Count != 0)
		{
			return batches[0].Prefab;
		}
		return null;
	}

	private static double Age(Batch batch)
	{
		return (ZNet.instance.GetTime() - new DateTime(batch.Start)).TotalSeconds;
	}

	private static bool Ready(Batch batch)
	{
		return Age(batch) >= (double)Duration();
	}

	private void Update()
	{
		if (Valid && !(Time.time < nextCheck))
		{
			nextCheck = Time.time + 2f;
			UpdateCover(now: false);
		}
	}

	private void UpdateCover(bool now)
	{
		//IL_0028: 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_0037: Unknown result type (might be due to invalid IL or missing references)
		if (!now && Time.time < nextCover)
		{
			return;
		}
		nextCover = Time.time + 10f;
		float num = default(float);
		bool flag = default(bool);
		Cover.GetCoverForPoint(((Component)this).transform.TransformPoint(RoofCheck * 1.5f), ref num, ref flag, 0.5f);
		exposed = num < 0.7f;
		hasRoof = flag;
		if ((!exposed && hasRoof) || !view.IsOwner())
		{
			return;
		}
		List<Batch> list = Read();
		bool flag2 = false;
		long ticks = ZNet.instance.GetTime().Ticks;
		for (int i = 0; i < list.Count; i++)
		{
			if (!Ready(list[i]))
			{
				list[i] = new Batch
				{
					Prefab = list[i].Prefab,
					Start = ticks
				};
				flag2 = true;
			}
		}
		if (flag2)
		{
			Write(list);
		}
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$piece_potato_cask");
	}

	public string GetHoverText()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid)
		{
			return "";
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
		{
			return Localization.instance.Localize("$piece_potato_cask\n$piece_noaccess");
		}
		List<Batch> list = Read();
		StringBuilder stringBuilder = new StringBuilder("$piece_potato_cask" + $" ({list.Count}/{Plugin.CaskBatches.Value})");
		if (list.Count == 0)
		{
			stringBuilder.Append("\n$piece_container_empty");
		}
		float num = Duration();
		foreach (Batch item in list)
		{
			ItemConversion val = Recipe(item.Prefab);
			string text = ((val != null && Object.op_Implicit((Object)(object)val.m_from)) ? val.m_from.m_itemData.m_shared.m_name : item.Prefab);
			if (Ready(item))
			{
				stringBuilder.Append("\n" + text + ": <color=yellow>$piece_fermenter_ready</color>");
			}
			else if (!hasRoof)
			{
				stringBuilder.Append("\n" + text + ": $piece_fermenter_needroof");
			}
			else if (exposed)
			{
				stringBuilder.Append("\n" + text + ": $piece_fermenter_exposed");
			}
			else
			{
				stringBuilder.Append($"\n{text}: {Mathf.CeilToInt((float)((double)num - Age(item)) / 60f)} min left");
			}
		}
		if (list.Any(Ready))
		{
			stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_fermenter_tap");
		}
		else if (list.Count < Plugin.CaskBatches.Value)
		{
			stringBuilder.Append("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_fermenter_add");
		}
		if (list.Count < Plugin.CaskBatches.Value)
		{
			stringBuilder.Append("\n[<color=yellow><b>1-8</b></color>] Add mead bases from your hotbar");
		}
		return Localization.instance.Localize(stringBuilder.ToString());
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (hold || !Valid)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		if (Read().Any(Ready))
		{
			view.InvokeRPC("PotatoCask_Tap", Array.Empty<object>());
			return true;
		}
		string brewing = Brewing(Read());
		ItemData val = (from c in Fermenter()?.m_conversion?.Where((ItemConversion c) => c != null && Object.op_Implicit((Object)(object)c.m_from) && (brewing == null || ((Object)((Component)c.m_from).gameObject).name == brewing))
			select user.GetInventory().GetItem(c.m_from.m_itemData.m_shared.m_name, -1, false)).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i != null));
		if (val == null)
		{
			((Character)user).Message((MessageType)2, "$msg_noprocessableitems", 0, (Sprite)null, false);
			return true;
		}
		Add(user, val, 1);
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || item == null)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || Recipe(((Object)item.m_dropPrefab).name) == null)
		{
			((Character)user).Message((MessageType)2, "That doesn't brew", 0, (Sprite)null, false);
			return true;
		}
		Add(user, item, item.m_stack);
		return true;
	}

	private void Add(Humanoid user, ItemData item, int wanted)
	{
		UpdateCover(now: true);
		if (!hasRoof)
		{
			((Character)user).Message((MessageType)2, "$piece_fermenter_needroof", 0, (Sprite)null, false);
			return;
		}
		if (exposed)
		{
			((Character)user).Message((MessageType)2, "$piece_fermenter_exposed", 0, (Sprite)null, false);
			return;
		}
		List<Batch> list = Read();
		string text = Brewing(list);
		if (text != null && text != ((Object)item.m_dropPrefab).name)
		{
			((Character)user).Message((MessageType)2, "The cask is brewing " + (Recipe(text)?.m_from?.m_itemData.m_shared.m_name ?? text), 0, (Sprite)null, false);
			return;
		}
		int num = Plugin.CaskBatches.Value - list.Count;
		if (num <= 0)
		{
			((Character)user).Message((MessageType)2, "The cask is full", 0, (Sprite)null, false);
			return;
		}
		int num2 = Math.Min(num, Math.Min(wanted, item.m_stack));
		string name = ((Object)item.m_dropPrefab).name;
		string name2 = item.m_shared.m_name;
		if (user.GetInventory().RemoveItem(item, num2))
		{
			view.InvokeRPC("PotatoCask_Add", new object[2] { name, num2 });
			((Character)user).Message((MessageType)2, $"$msg_added {name2} x{num2}", 0, (Sprite)null, false);
		}
	}

	private void RPC_Add(long sender, string prefab, int count)
	{
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || !view.IsOwner() || count <= 0 || Recipe(prefab) == null)
		{
			return;
		}
		List<Batch> list = Read();
		string text = Brewing(list);
		int num = ((text == null || !(text != prefab)) ? Math.Min(count, Math.Max(0, Plugin.CaskBatches.Value - list.Count)) : 0);
		long ticks = ZNet.instance.GetTime().Ticks;
		for (int i = 0; i < num; i++)
		{
			list.Add(new Batch
			{
				Prefab = prefab,
				Start = ticks
			});
		}
		if (num > 0)
		{
			Write(list);
			Fermenter obj = Fermenter();
			if (obj != null)
			{
				obj.m_addedEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
		}
		if (count > num)
		{
			view.InvokeRPC(sender, "PotatoCask_Give", new object[2]
			{
				prefab,
				count - num
			});
		}
	}

	private void RPC_Tap(long sender)
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || !view.IsOwner())
		{
			return;
		}
		List<Batch> source = Read();
		List<Batch> list = source.Where(Ready).ToList();
		if (list.Count != 0)
		{
			Write(source.Where((Batch b) => !Ready(b)).ToList());
			Fermenter obj = Fermenter();
			if (obj != null)
			{
				obj.m_tapEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
			((MonoBehaviour)this).StartCoroutine(Pour(list.Select((Batch b) => b.Prefab).ToList()));
		}
	}

	private IEnumerator Pour(List<string> prefabs)
	{
		yield return (object)new WaitForSeconds(1.5f);
		Vector3 val = ((Component)this).transform.TransformPoint(OutputPoint * 1.5f);
		Fermenter obj = Fermenter();
		if (obj != null)
		{
			obj.m_spawnEffects.Create(val, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
		}
		float num = 0.3f;
		foreach (string prefab in prefabs)
		{
			ItemConversion val2 = Recipe(prefab);
			if (val2 != null && Object.op_Implicit((Object)(object)val2.m_to))
			{
				for (int i = 0; i < Yield(val2); i++)
				{
					ItemDrop.OnCreateNew(Object.Instantiate<ItemDrop>(val2.m_to, val + Vector3.up * num, Quaternion.identity), false);
					num += 0.05f;
				}
			}
		}
	}

	private void RPC_Give(long sender, string prefab, int count)
	{
		//IL_007d: 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_0087: 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_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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)
		Player localPlayer = Player.m_localPlayer;
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		if (!Object.op_Implicit((Object)(object)val) || count <= 0)
		{
			return;
		}
		Inventory val2 = (Object.op_Implicit((Object)(object)localPlayer) ? ((Humanoid)localPlayer).GetInventory() : null);
		if (val2 == null || !val2.CanAddItem(val, count) || !val2.AddItem(val, count))
		{
			Vector3 val3 = (Object.op_Implicit((Object)(object)localPlayer) ? (((Component)localPlayer).transform.position + Vector3.up) : (((Component)this).transform.position + Vector3.up));
			for (int i = 0; i < count; i++)
			{
				ItemDrop.OnCreateNew(Object.Instantiate<GameObject>(val, val3, Quaternion.identity), false);
			}
		}
	}

	private void OnDestroyed()
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: 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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || !view.IsOwner())
		{
			return;
		}
		List<Batch> list = Read();
		Write(new List<Batch>());
		foreach (Batch item in list)
		{
			ItemConversion val = Recipe(item.Prefab);
			if (val != null)
			{
				bool num = Ready(item);
				ItemDrop val2 = (num ? val.m_to : val.m_from);
				int num2 = ((!num) ? 1 : Yield(val));
				for (int i = 0; i < num2; i++)
				{
					Vector3 val3 = ((Component)this).transform.position + Vector3.up + Random.insideUnitSphere * 0.4f;
					ItemDrop.OnCreateNew(Object.Instantiate<GameObject>(((Component)val2).gameObject, val3, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)), false);
				}
			}
		}
	}
}
internal static class Feeding
{
	[HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")]
	private static class Watch
	{
		private static void Prefix(MonsterAI __instance)
		{
		}
	}

	[HarmonyPatch(typeof(MonsterAI), "FindClosestConsumableItem")]
	private static class FromTrough
	{
		private static void Postfix(MonsterAI __instance, float maxRange, ref ItemDrop __result)
		{
			//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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if (Trough.All.Count == 0 || CanConsume == null)
			{
				return;
			}
			maxRange = Mathf.Max(maxRange, Plugin.TroughReach.Value);
			if (Object.op_Implicit((Object)(object)__result))
			{
				Note(__instance, "found food on the ground: " + ((Object)__result).name.Replace("(Clone)", ""));
				return;
			}
			try
			{
				Vector3 at = ((Component)__instance).transform.position;
				foreach (Trough item in from trough in Trough.All
					where Object.op_Implicit((Object)(object)trough)
					orderby Vector3.Distance(at, ((Component)trough).transform.position)
					select trough)
				{
					float num = Vector3.Distance(at, ((Component)item).transform.position);
					if (num > maxRange)
					{
						Note(__instance, $"hungry, but the nearest trough is {num:0.0} m away (reach {maxRange:0} m)");
						break;
					}
					string text = item.FoodFor(__instance);
					if (text == null)
					{
						Note(__instance, string.Format("hungry, trough {0:0.0} m away has nothing it eats (it eats: {1})", num, string.Join(", ", (from item in __instance.m_consumeItems
							where Object.op_Implicit((Object)(object)item)
							select ((Object)item).name).ToArray())));
						continue;
					}
					if (!Reachable(__instance, item))
					{
						Note(__instance, $"hungry, trough {num:0.0} m away has {text}, but its route doesn't get close enough");
						continue;
					}
					ItemDrop val = item.Dispense(text);
					Note(__instance, Object.op_Implicit((Object)(object)val) ? $"hungry, took {text} from the trough {num:0.0} m away and is walking to it" : $"hungry, asked the trough {num:0.0} m away for {text} (waiting for a bite, or the bowl is busy)");
					if (Object.op_Implicit((Object)(object)val))
					{
						__result = val;
					}
					else
					{
						SearchTimer.Invoke(__instance) = Mathf.Max(SearchTimer.Invoke(__instance), __instance.m_consumeSearchInterval - 2f);
					}
					break;
				}
			}
			catch (Exception ex)
			{
				if (!warned)
				{
					warned = true;
					Plugin.Log.LogWarning((object)("Trough feeding failed; animals eat off the ground as usual: " + ex));
				}
			}
		}
	}

	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	private static class BaitStaysPut
	{
		private static void Postfix(ItemDrop __instance)
		{
			if (IsBait(__instance))
			{
				__instance.m_autoPickup = false;
			}
		}
	}

	private const string BaitKey = "PotatoTrough.Bait";

	private static readonly Func<MonsterAI, ItemData, bool> CanConsume = AccessTools.MethodDelegate<Func<MonsterAI, ItemData, bool>>(AccessTools.Method(typeof(MonsterAI), "CanConsume", (Type[])null, (Type[])null), (object)null, true);

	private static readonly FieldRef<MonsterAI, float> SearchTimer = AccessTools.FieldRefAccess<MonsterAI, float>("m_consumeSearchTimer");

	private static HashSet<string> animalFood;

	private static ZNetScene foodFrom;

	private static bool warned;

	private static readonly List<Vector3> route = new List<Vector3>();

	internal const bool Diagnostics = false;

	private static readonly Dictionary<int, float> lastNote = new Dictionary<int, float>();

	internal static bool IsAnimalFood(ItemData item)
	{
		ZNetScene instance = ZNetScene.instance;
		if (!Object.op_Implicit((Object)(object)instance))
		{
			return false;
		}
		if (animalFood == null || (Object)(object)foodFrom != (Object)(object)instance)
		{
			foodFrom = instance;
			animalFood = new HashSet<string>();
			foreach (GameObject prefab in instance.m_prefabs)
			{
				MonsterAI val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<MonsterAI>() : null);
				if (!Object.op_Implicit((Object)(object)val) || val.m_consumeItems == null || (!Object.op_Implicit((Object)(object)prefab.GetComponent<Tameable>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<Procreation>())))
				{
					continue;
				}
				foreach (ItemDrop consumeItem in val.m_consumeItems)
				{
					if (Object.op_Implicit((Object)(object)consumeItem) && consumeItem.m_itemData?.m_shared != null)
					{
						animalFood.Add(consumeItem.m_itemData.m_shared.m_name);
					}
				}
			}
		}
		if (item?.m_shared != null)
		{
			return animalFood.Contains(item.m_shared.m_name);
		}
		return false;
	}

	internal static bool CanEat(MonsterAI animal, string prefab)
	{
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
		if (Object.op_Implicit((Object)(object)val2))
		{
			return CanConsume(animal, val2.m_itemData);
		}
		return false;
	}

	internal static void MarkBait(ItemDrop bite)
	{
		if (Object.op_Implicit((Object)(object)bite))
		{
			bite.m_autoPickup = false;
			ZNetView component = ((Component)bite).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.GetZDO() != null)
			{
				component.GetZDO().Set("PotatoTrough.Bait", true);
			}
		}
	}

	internal static bool IsBait(ItemDrop drop)
	{
		ZNetView component = ((Component)drop).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)component) && component.GetZDO() != null)
		{
			return component.GetZDO().GetBool("PotatoTrough.Bait", false);
		}
		return false;
	}

	private static bool Reachable(MonsterAI animal, Trough trough)
	{
		//IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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)
		//IL_0026: 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)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: 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_007d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)animal).transform.position;
		Vector3 position2 = ((Component)trough).transform.position;
		float num = animal.m_consumeRange + 2.42f;
		if (Utils.DistanceXZ(position, position2) <= num)
		{
			return true;
		}
		Pathfinding instance = Pathfinding.instance;
		if (!Object.op_Implicit((Object)(object)instance))
		{
			return true;
		}
		if (!instance.GetPath(position, position2, route, ((BaseAI)animal).m_pathAgentType, false, false, false) || route.Count == 0)
		{
			return false;
		}
		return Utils.DistanceXZ(route[route.Count - 1], position2) <= num;
	}

	internal static void Note(MonsterAI animal, string text)
	{
	}

	private static Trough Nearest(MonsterAI animal, out float distance)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		distance = float.MaxValue;
		Trough result = null;
		foreach (Trough item in Trough.All)
		{
			if (Object.op_Implicit((Object)(object)item))
			{
				float num = Vector3.Distance(((Component)animal).transform.position, ((Component)item).transform.position);
				if (num < distance)
				{
					distance = num;
					result = item;
				}
			}
		}
		return result;
	}
}
[BepInPlugin("potato.farmer", "PotatoFarmer", "1.2.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string Id = "potato.farmer";

	public const string Version = "1.2.0";

	public const string TroughPiece = "piece_potato_trough";

	public const string TroughName = "$piece_potato_trough";

	private const string TroughDescription = "$piece_potato_trough_description";

	private const string TroughSection = "1 - Trough";

	public const string RoostPiece = "piece_potato_roost";

	public const string RoostName = "$piece_potato_roost";

	private const string RoostDescription = "$piece_potato_roost_description";

	private const string RoostSection = "2 - Roost";

	public const string CaskPiece = "piece_potato_cask";

	public const string CaskName = "$piece_potato_cask";

	private const string CaskDescription = "$piece_potato_cask_description";

	private const string CaskSection = "3 - Cask";

	internal static ManualLogSource Log;

	internal static ConfigEntry<int> TroughCapacity;

	internal static ConfigEntry<int> RoostCapacity;

	internal static ConfigEntry<int> RoostFlock;

	internal static ConfigEntry<int> CaskBatches;

	internal static ConfigEntry<bool> TroughEnabled;

	internal static ConfigEntry<bool> TroughShowFood;

	internal static ConfigEntry<bool> RoostEnabled;

	internal static ConfigEntry<bool> CaskEnabled;

	internal static ConfigEntry<bool> CaskMix;

	internal static ConfigEntry<float> TroughReach;

	internal static ConfigEntry<float> RoostReach;

	private static Piece troughPiece;

	private static Piece roostPiece;

	private static Piece caskPiece;

	private void Awake()
	{
		//IL_0033: 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)
		//IL_0040: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Expected O, but got Unknown
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Expected O, but got Unknown
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Expected O, but got Unknown
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Expected O, but got Unknown
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Expected O, but got Unknown
		//IL_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Expected O, but got Unknown
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Expected O, but got Unknown
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Expected O, but got Unknown
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		Assets.Dir = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? "", "assets");
		ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};
		TroughEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Trough", "Enabled", true, new ConfigDescription("Show the feeding trough on the hammer. Troughs already built stay and keep working. Set by the server.", (AcceptableValueBase)null, new object[1] { val }));
		TroughCapacity = ((BaseUnityPlugin)this).Config.Bind<int>("1 - Trough", "Capacity", 100, new ConfigDescription("How many food items one trough holds. Set by the server.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), new object[1] { val }));
		TroughReach = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Trough", "Reach", 25f, new ConfigDescription("How far away (metres) hungry animals notice the trough and walk over to eat. 25 covers a big farm pen; animals on their own only look about 10 m for food. Set by the server.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 60f), new object[1] { val }));
		TroughShowFood = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Trough", "Show food in the bowl", true, "Show what is in the trough as food models in the bowl (only on your screen).");
		TroughEnabled.SettingChanged += delegate
		{
			if (Object.op_Implicit((Object)(object)troughPiece))
			{
				troughPiece.m_enabled = TroughEnabled.Value;
			}
		};
		RoostEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Roost", "Enabled", true, new ConfigDescription("Show the roost on the hammer. Roosts already built stay and keep working. Set by the server.", (AcceptableValueBase)null, new object[1] { val }));
		RoostCapacity = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Roost", "Capacity", 60, new ConfigDescription("How many eggs one roost holds. Set by the server.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), new object[1] { val }));
		RoostReach = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Roost", "Reach", 10f, new ConfigDescription("How far away (metres) the roost gathers eggs. Hens only breed with others within 10 m, so 10 covers a coop. Set by the server.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), new object[1] { val }));
		RoostFlock = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Roost", "Flock size", 6, new ConfigDescription("With a fire near the roost, it hatches its eggs one at a time while there are fewer hens (and chicks) than this within its reach. 0 = never hatch. Set by the server.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), new object[1] { val }));
		RoostEnabled.SettingChanged += delegate
		{
			if (Object.op_Implicit((Object)(object)roostPiece))
			{
				roostPiece.m_enabled = RoostEnabled.Value;
			}
		};
		CaskEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Cask", "Enabled", true, new ConfigDescription("Show the cask on the hammer. Casks already built stay and keep working. Set by the server.", (AcceptableValueBase)null, new object[1] { val }));
		CaskBatches = ((BaseUnityPlugin)this).Config.Bind<int>("3 - Cask", "Batches", 4, new ConfigDescription("How many mead bases one cask brews at once, each like a fermenter of its own. Set by the server.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[1] { val }));
		CaskMix = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Cask", "Mix mead bases", false, new ConfigDescription("Let one cask brew different mead bases at once. Off: a cask brews one kind at a time, until it's emptied. Set by the server.", (AcceptableValueBase)null, new object[1] { val }));
		CaskEnabled.SettingChanged += delegate
		{
			if (Object.op_Implicit((Object)(object)caskPiece))
			{
				caskPiece.m_enabled = CaskEnabled.Value;
			}
		};
		new Harmony("potato.farmer").PatchAll(typeof(Plugin).Assembly);
		PrefabManager.OnVanillaPrefabsAvailable += AddPieces;
	}

	private static void AddPieces()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= AddPieces;
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{
				"$piece_potato_trough".Substring(1),
				"Gullinbursti's Trough"
			},
			{
				"$piece_potato_trough_description".Substring(1),
				"A feeding trough blessed by Freyr's golden boar. Fill it with food and hungry animals nearby come to eat: taming, breeding and feeding all count."
			},
			{
				"$piece_potato_roost".Substring(1),
				"Gullinkambi's Roost"
			},
			{
				"$piece_potato_roost_description".Substring(1),
				"A nesting box watched over by Gullinkambi, the golden-combed rooster of Valhalla. Gathers the eggs your hens lay nearby, so they keep laying."
			},
			{
				"$piece_potato_cask".Substring(1),
				"Heiðrún's Cask"
			},
			{
				"$piece_potato_cask_description".Substring(1),
				"A great mead cask blessed by Heiðrún, the goat whose udder runs with mead in Valhalla. Brews several mead bases at once, each like a fermenter of its own. Needs a roof."
			}
		});
		try
		{
			AddTrough();
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Couldn't add the feeding trough: " + ex));
		}
		try
		{
			AddRoost();
		}
		catch (Exception ex2)
		{
			Log.LogError((object)("Couldn't add the roost: " + ex2));
		}
		try
		{
			AddCask();
		}
		catch (Exception ex3)
		{
			Log.LogError((object)("Couldn't add the cask: " + ex3));
		}
	}

	private static void AddTrough()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: 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_0158: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		PieceConfig val = new PieceConfig();
		val.Name = "$piece_potato_trough";
		val.Description = "$piece_potato_trough_description";
		val.PieceTable = "Hammer";
		val.Category = "Furniture";
		val.CraftingStation = "forge";
		val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
		{
			new RequirementConfig("Wood", 10, 0, true),
			new RequirementConfig("Bronze", 2, 0, true)
		};
		CustomPiece val2 = new CustomPiece("piece_potato_trough", "piece_table", val);
		if (!Object.op_Implicit((Object)(object)val2.PiecePrefab))
		{
			Log.LogWarning((object)"The wooden table to build the trough from wasn't found; no trough this session.");
			return;
		}
		Mesh val3 = Assets.LoadMesh("trough", 1.21f);
		if (Object.op_Implicit((Object)(object)val3))
		{
			PieceLook pieceLook = new PieceLook("trough", 1f, 0.6f);
			GameObject piecePrefab = val2.PiecePrefab;
			Rebuild(piecePrefab, val3, pieceLook.Material);
			AddBox(piecePrefab, "Floor", new Vector3(0f, 0.11f, 0f), new Vector3(1.52f, 0.215f, 0.52f), 1.21f);
			AddBox(piecePrefab, "Side", new Vector3(0f, 0.28f, 0.25f), new Vector3(1.52f, 0.14f, 0.06f), 1.21f);
			AddBox(piecePrefab, "Side", new Vector3(0f, 0.28f, -0.25f), new Vector3(1.52f, 0.14f, 0.06f), 1.21f);
			AddBox(piecePrefab, "End", new Vector3(0.88f, 0.25f, 0f), new Vector3(0.24f, 0.5f, 0.42f), 1.21f);
			AddBox(piecePrefab, "End", new Vector3(-0.88f, 0.25f, 0f), new Vector3(0.24f, 0.5f, 0.42f), 1.21f);
			piecePrefab.GetComponent<WearNTear>().m_materialType = (MaterialType)0;
			piecePrefab.AddComponent<Trough>();
			troughPiece = val2.Piece;
			troughPiece.m_enabled = TroughEnabled.Value;
			if (!GUIManager.IsHeadless())
			{
				troughPiece.m_icon = RenderManager.Instance.Render(piecePrefab, Quaternion.Euler(20f, 200f, 0f));
			}
			PieceManager.Instance.AddPiece(val2);
			Log.LogInfo((object)"Feeding trough added to the hammer.");
		}
	}

	private static void AddRoost()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: 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_0158: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: 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_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
		PieceConfig val = new PieceConfig();
		val.Name = "$piece_potato_roost";
		val.Description = "$piece_potato_roost_description";
		val.PieceTable = "Hammer";
		val.Category = "Furniture";
		val.CraftingStation = "forge";
		val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
		{
			new RequirementConfig("FineWood", 10, 0, true),
			new RequirementConfig("BlackMetal", 2, 0, true)
		};
		CustomPiece val2 = new CustomPiece("piece_potato_roost", "piece_table", val);
		if (!Object.op_Implicit((Object)(object)val2.PiecePrefab))
		{
			Log.LogWarning((object)"The wooden table to build the roost from wasn't found; no roost this session.");
			return;
		}
		Mesh val3 = Assets.LoadMesh("roost", 1.3f);
		if (Object.op_Implicit((Object)(object)val3))
		{
			PieceLook pieceLook = new PieceLook("roost", 1f, -1f, "BlackMetalChest_mat", null, 0f);
			GameObject piecePrefab = val2.PiecePrefab;
			Rebuild(piecePrefab, val3, pieceLook.Material);
			AddBox(piecePrefab, "Base", new Vector3(0f, 0.12f, 0f), new Vector3(1.5f, 0.245f, 0.5f), 1.3f);
			AddBox(piecePrefab, "Lid", new Vector3(0f, 0.52f, 0f), new Vector3(1.6f, 0.19f, 0.64f), 1.3f);
			AddBox(piecePrefab, "Back", new Vector3(0f, 0.335f, -0.19f), new Vector3(1.5f, 0.19f, 0.09f), 1.3f);
			AddBox(piecePrefab, "Side", new Vector3(0.715f, 0.335f, 0f), new Vector3(0.07f, 0.19f, 0.45f), 1.3f);
			AddBox(piecePrefab, "Side", new Vector3(-0.715f, 0.335f, 0f), new Vector3(0.07f, 0.19f, 0.45f), 1.3f);
			AddBox(piecePrefab, "End", new Vector3(0.85f, 0.42f, 0f), new Vector3(0.2f, 0.84f, 0.22f), 1.3f);
			AddBox(piecePrefab, "End", new Vector3(-0.85f, 0.42f, 0f), new Vector3(0.2f, 0.84f, 0.22f), 1.3f);
			piecePrefab.GetComponent<WearNTear>().m_materialType = (MaterialType)0;
			piecePrefab.AddComponent<Roost>();
			roostPiece = val2.Piece;
			roostPiece.m_enabled = RoostEnabled.Value;
			if (!GUIManager.IsHeadless())
			{
				roostPiece.m_icon = RenderManager.Instance.Render(piecePrefab, Quaternion.Euler(20f, 200f, 0f));
			}
			PieceManager.Instance.AddPiece(val2);
			Log.LogInfo((object)"Roost added to the hammer.");
		}
	}

	private static void AddCask()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Expected O, but got Unknown
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: 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_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: 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_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Unknown result type (might be due to invalid IL or missing references)
		PieceConfig val = new PieceConfig();
		val.Name = "$piece_potato_cask";
		val.Description = "$piece_potato_cask_description";
		val.PieceTable = "Hammer";
		val.Category = "Crafting";
		val.CraftingStation = "forge";
		val.Requirements = (RequirementConfig[])(object)new RequirementConfig[4]
		{
			new RequirementConfig("FineWood", 30, 0, true),
			new RequirementConfig("BlackMetal", 6, 0, true),
			new RequirementConfig("Tar", 4, 0, true),
			new RequirementConfig("IronNails", 20, 0, true)
		};
		CustomPiece val2 = new CustomPiece("piece_potato_cask", "piece_table", val);
		if (!Object.op_Implicit((Object)(object)val2.PiecePrefab))
		{
			Log.LogWarning((object)"The wooden table to build the cask from wasn't found; no cask this session.");
			return;
		}
		Mesh val3 = Assets.LoadMesh("cask", 1.5f);
		if (Object.op_Implicit((Object)(object)val3))
		{
			PieceLook pieceLook = new PieceLook("cask", 1f, -1f, "BlackMetalChest_mat", null, 0f);
			GameObject piecePrefab = val2.PiecePrefab;
			GameObject val4 = Rebuild(piecePrefab, val3, pieceLook.Material);
			Mesh val5 = Assets.LoadMesh("caskhoops", 1.5f);
			if (Object.op_Implicit((Object)(object)val5))
			{
				GameObject val6 = new GameObject("Hoops")
				{
					layer = piecePrefab.layer
				};
				val6.transform.SetParent(val4.transform, false);
				val6.AddComponent<MeshFilter>().sharedMesh = val5;
				((Renderer)val6.AddComponent<MeshRenderer>()).sharedMaterial = new PieceLook("caskhoops", 1f, -1f, "BlackMetalChest_mat", null, 0f).Material;
			}
			AddBox(piecePrefab, "Barrel", new Vector3(0.055f, 1.19f, 0f), new Vector3(1.71f, 1.78f, 1.81f), 1.5f);
			AddBox(piecePrefab, "Cradle", new Vector3(0.064f, 0.2f, 0f), new Vector3(1.87f, 0.4f, 1.64f), 1.5f);
			piecePrefab.GetComponent<WearNTear>().m_materialType = (MaterialType)0;
			piecePrefab.AddComponent<Cask>();
			caskPiece = val2.Piece;
			caskPiece.m_enabled = CaskEnabled.Value;
			if (!GUIManager.IsHeadless())
			{
				caskPiece.m_icon = RenderManager.Instance.Render(piecePrefab, Quaternion.Euler(20f, 230f, 0f));
			}
			PieceManager.Instance.AddPiece(val2);
			Log.LogInfo((object)"Cask added to the hammer.");
		}
	}

	private static GameObject Rebuild(GameObject prefab, Mesh mesh, Material material)
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		foreach (Transform item in ((IEnumerable)prefab.transform).Cast<Transform>().ToList())
		{
			Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
		}
		Component[] components = prefab.GetComponents<Component>();
		foreach (Component val in components)
		{
			if (!(val is Transform) && !(val is ZNetView) && !(val is Piece) && !(val is WearNTear))
			{
				Log.LogDebug((object)("Removing the base piece's " + ((object)val).GetType().Name));
				Object.DestroyImmediate((Object)(object)val);
			}
		}
		GameObject val2 = new GameObject("Model");
		val2.layer = prefab.layer;
		val2.transform.SetParent(prefab.transform, false);
		val2.AddComponent<MeshFilter>().sharedMesh = mesh;
		((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = material;
		Piece component = prefab.GetComponent<Piece>();
		component.m_comfort = 0;
		component.m_comfortGroup = (ComfortGroup)0;
		((StaticTarget)component).m_primaryTarget = false;
		WearNTear component2 = prefab.GetComponent<WearNTear>();
		component2.m_new = (component2.m_worn = (component2.m_broken = val2));
		component2.m_fragmentRoots = null;
		component2.m_autoCreateFragments = false;
		return val2;
	}

	private static void AddBox(GameObject prefab, string name, Vector3 center, Vector3 size, float scale)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		center *= scale;
		size *= scale;
		GameObject val = new GameObject(name)
		{
			layer = prefab.layer
		};
		val.transform.SetParent(prefab.transform, false);
		BoxCollider obj = val.AddComponent<BoxCollider>();
		obj.center = center;
		obj.size = size;
	}
}
public class Roost : MonoBehaviour, Hoverable, Interactable
{
	private const string EggsKey = "PotatoRoost.Eggs";

	private const string OffKey = "PotatoRoost.Off";

	private const string WarmKey = "PotatoRoost.Warming";

	private const float GatherEvery = 3f;

	internal const float Size = 1.3f;

	private static readonly float[] CubbyX = new float[3] { -0.466f, -0.017f, 0.447f };

	private const float CubbyFloor = 0.25f;

	private const float CubbyZ = 0.05f;

	private const float MaxShownPerCubby = 4f;

	private const float EggLength = 0.12f;

	private static bool eggSizeLogged;

	private static readonly Vector3[] Clutch = (Vector3[])(object)new Vector3[4]
	{
		new Vector3(-0.5f, 0f, 0f),
		new Vector3(0.5f, 0f, 0f),
		new Vector3(0f, 0f, 0.85f),
		new Vector3(0f, 0f, -0.85f)
	};

	private static int itemMask;

	private ZNetView view;

	private string shown;

	private GameObject eggModels;

	private float nextCheck;

	private float nextGather;

	private const float Stagger = 300f;

	private bool Valid
	{
		get
		{
			if (Object.op_Implicit((Object)(object)view))
			{
				return view.IsValid();
			}
			return false;
		}
	}

	private bool Gathering
	{
		get
		{
			if (Valid)
			{
				return !view.GetZDO().GetBool("PotatoRoost.Off", false);
			}
			return false;
		}
	}

	private void Awake()
	{
		view = ((Component)this).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)view) && view.GetZDO() != null)
		{
			view.Register("PotatoRoost_Toggle", (Action<long>)RPC_Toggle);
			view.Register("PotatoRoost_Take", (Action<long>)RPC_Take);
			view.Register<string>("PotatoRoost_Give", (Action<long, string>)RPC_Give);
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
			}
			nextGather = Time.time + Random.Range(0f, 3f);
		}
	}

	private Stock Read()
	{
		return Stock.Parse(Valid ? view.GetZDO().GetString("PotatoRoost.Eggs", "") : "");
	}

	private void Write(Stock stock)
	{
		view.GetZDO().Set("PotatoRoost.Eggs", stock.Format());
	}

	private void Update()
	{
		if (!Valid)
		{
			return;
		}
		if (Time.time >= nextGather)
		{
			nextGather = Time.time + 3f;
			if (view.IsOwner())
			{
				if (Gathering)
				{
					Gather();
				}
				Hatch();
			}
		}
		if (!(Time.time < nextCheck))
		{
			nextCheck = Time.time + 0.5f;
			string text = view.GetZDO().GetString("PotatoRoost.Eggs", "");
			if (!(text == shown))
			{
				shown = text;
				ShowEggs(Stock.Parse(text));
			}
		}
	}

	private void Gather()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		Stock stock = Read();
		int num = Plugin.RoostCapacity.Value - stock.Total;
		if (num <= 0)
		{
			return;
		}
		if (itemMask == 0)
		{
			itemMask = LayerMask.GetMask(new string[1] { "item" });
		}
		bool flag = false;
		HashSet<ItemDrop> hashSet = new HashSet<ItemDrop>();
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, Plugin.RoostReach.Value, itemMask);
		foreach (Collider val in array)
		{
			ItemDrop val2 = (Object.op_Implicit((Object)(object)val.attachedRigidbody) ? ((Component)val.attachedRigidbody).GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val2) || !hashSet.Add(val2) || !Object.op_Implicit((Object)(object)((Component)val2).GetComponent<EggGrow>()))
			{
				continue;
			}
			ZNetView component = ((Component)val2).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || component.GetZDO().GetFloat(ZDOVars.s_growStart, 0f) > 0f)
			{
				continue;
			}
			if (!component.IsOwner())
			{
				val2.RequestOwn();
				continue;
			}
			int stack = val2.m_itemData.m_stack;
			int num2 = Math.Min(stack, num);
			stock.Add(Key(((Component)val2).gameObject, val2.m_itemData.m_quality), num2);
			num -= num2;
			flag = true;
			if (num2 >= stack)
			{
				component.Destroy();
			}
			else
			{
				val2.SetStack(stack - num2);
			}
			if (num <= 0)
			{
				break;
			}
		}
		if (flag)
		{
			Write(stock);
		}
	}

	private static string Key(GameObject prefab, int quality)
	{
		return Utils.GetPrefabName(prefab) + "@" + Math.Max(1, quality);
	}

	private static bool Split(string key, out string prefab, out int quality)
	{
		int num = key.LastIndexOf('@');
		prefab = ((num > 0) ? key.Substring(0, num) : key);
		quality = ((num <= 0 || !int.TryParse(key.Substring(num + 1), out var result)) ? 1 : Math.Max(1, result));
		return prefab.Length > 0;
	}

	private void Hatch()
	{
		//IL_0039: 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)
		//IL_0048: 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_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: 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_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: 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_0178: Unknown result type (might be due to invalid IL or missing references)
		ZDO zDO = view.GetZDO();
		Stock stock = Read();
		string key;
		int quality;
		EggGrow val = NextEgg(stock, out key, out quality);
		int num = ((Object.op_Implicit((Object)(object)val) && Plugin.RoostFlock.Value > 0 && Object.op_Implicit((Object)(object)EffectArea.IsPointInsideArea(((Component)this).transform.position + Vector3.up * 0.4f, (Type)1, 0.5f))) ? Mathf.Min(Plugin.RoostFlock.Value - Flock(val), Hatchable(stock)) : 0);
		List<float> list = Starts();
		int count = list.Count;
		if (num <= 0)
		{
			if (count > 0)
			{
				zDO.Set("PotatoRoost.Warming", "");
			}
			return;
		}
		float num2 = (float)ZNet.instance.GetTimeSeconds();
		if (count > 0 && num2 - list[0] >= val.m_growTime)
		{
			list.RemoveAt(0);
			zDO.Set("PotatoRoost.Warming", Join(list));
			if (stock.Remove(key, 1))
			{
				Write(stock);
				Vector3 val2 = ((Component)this).transform.TransformPoint(new Vector3(0f, 0f, 0.9f) * 1.3f);
				Character component = Object.Instantiate<GameObject>(val.m_grownPrefab, val2, ((Component)this).transform.rotation).GetComponent<Character>();
				val.m_hatchEffect.Create(val2, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
				if (Object.op_Implicit((Object)(object)component))
				{
					component.SetTamed(val.m_tamed);
					component.SetLevel(quality);
				}
			}
		}
		else
		{
			while (list.Count > num)
			{
				list.RemoveAt(list.Count - 1);
			}
			while (list.Count < num)
			{
				list.Add((list.Count == 0) ? num2 : Mathf.Max(num2, list[list.Count - 1] + 300f));
			}
			if (list.Count != count)
			{
				zDO.Set("PotatoRoost.Warming", Join(list));
			}
		}
	}

	private List<float> Starts()
	{
		List<float> list = new List<float>();
		string[] array = view.GetZDO().GetString("PotatoRoost.Warming", "").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			if (float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				list.Add(result);
			}
		}
		return list;
	}

	private static string Join(List<float> starts)
	{
		return string.Join(";", starts.Select((float t) => t.ToString("R", CultureInfo.InvariantCulture)));
	}

	private static int Hatchable(Stock stock)
	{
		int num = 0;
		foreach (KeyValuePair<string, int> entry in stock.Entries)
		{
			if (Split(entry.Key, out var prefab, out var _))
			{
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
				EggGrow val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<EggGrow>() : null);
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.m_grownPrefab))
				{
					num += entry.Value;
				}
			}
		}
		return num;
	}

	private static EggGrow NextEgg(Stock stock, out string key, out int quality)
	{
		key = null;
		quality = 1;
		foreach (KeyValuePair<string, int> entry in stock.Entries)
		{
			if (Split(entry.Key, out var prefab, out var quality2))
			{
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
				EggGrow val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<EggGrow>() : null);
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.m_grownPrefab))
				{
					key = entry.Key;
					quality = quality2;
					return val2;
				}
			}
		}
		return null;
	}

	private int Flock(EggGrow egg)
	{
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		string name = ((Object)egg.m_grownPrefab).name;
		Growup component = egg.m_grownPrefab.GetComponent<Growup>();
		string text = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_grownPrefab)) ? ((Object)component.m_grownPrefab).name : null);
		float value = Plugin.RoostReach.Value;
		int num = 0;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (Object.op_Implicit((Object)(object)allCharacter) && !allCharacter.IsDead() && !(Vector3.Distance(((Component)allCharacter).transform.position, ((Component)this).transform.position) > value))
			{
				string prefabName = Utils.GetPrefabName(((Component)allCharacter).gameObject);
				if (prefabName == name || prefabName == text)
				{
					num++;
				}
			}
		}
		return num;
	}

	private string Warming()
	{
		List<float> list = Starts();
		if (list.Count == 0)
		{
			return null;
		}
		string key;
		int quality;
		EggGrow val = NextEgg(Read(), out key, out quality);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return null;
		}
		float num = Mathf.Max(0f, val.m_growTime - (float)(ZNet.instance.GetTimeSeconds() - (double)list[0]));
		string arg = ((list.Count == 1) ? "an egg" : (list.Count + " eggs"));
		return $"Warming {arg}: next chick in {Mathf.CeilToInt(num / 60f)} min";
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$piece_potato_roost");
	}

	public string GetHoverText()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid)
		{
			return "";
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
		{
			return Localization.instance.Localize("$piece_potato_roost\n$piece_noaccess");
		}
		Stock stock = Read();
		List<string> list = new List<string>();
		foreach (KeyValuePair<string, int> entry in stock.Entries)
		{
			if (Split(entry.Key, out var prefab, out var quality))
			{
				list.Add(entry.Value + " " + ItemName(prefab) + ((quality > 1) ? (" " + new string('★', quality - 1)) : ""));
			}
		}
		string text = ((list.Count == 0) ? "No eggs" : string.Join(", ", list.ToArray()));
		string text2 = Warming();
		if (text2 != null)
		{
			text = text + "\n" + text2;
		}
		string text3 = "$piece_potato_roost" + $" ({stock.Total}/{Plugin.RoostCapacity.Value})\n" + text + "\n[<color=yellow><b>$KEY_Use</b></color>] Gather eggs: " + (Gathering ? "On" : "Off");
		if (stock.Total > 0)
		{
			text3 += "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] Take the eggs";
		}
		return Localization.instance.Localize(text3);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (hold || !Valid)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		if (alt)
		{
			if (Read().Total > 0)
			{
				view.InvokeRPC("PotatoRoost_Take", Array.Empty<object>());
			}
		}
		else
		{
			bool gathering = Gathering;
			view.InvokeRPC("PotatoRoost_Toggle", Array.Empty<object>());
			((Character)user).Message((MessageType)2, gathering ? "The roost stops gathering eggs" : "The roost gathers eggs again", 0, (Sprite)null, false);
		}
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}

	private static string ItemName(string prefab)
	{
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return prefab;
		}
		return val2.m_itemData.m_shared.m_name;
	}

	private void RPC_Toggle(long sender)
	{
		if (Valid && view.IsOwner())
		{
			view.GetZDO().Set("PotatoRoost.Off", Gathering);
		}
	}

	private void RPC_Take(long sender)
	{
		if (Valid && view.IsOwner())
		{
			Stock stock = Read();
			if (stock.Total != 0)
			{
				Write(new Stock());
				view.InvokeRPC(sender, "PotatoRoost_Give", new object[1] { stock.Format() });
			}
		}
	}

	private void RPC_Give(long sender, string packed)
	{
		//IL_002b: 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_0035: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		Vector3 at = (Object.op_Implicit((Object)(object)localPlayer) ? (((Component)localPlayer).transform.position + Vector3.up) : (((Component)this).transform.position + Vector3.up));
		foreach (KeyValuePair<string, int> entry in Stock.Parse(packed).Entries)
		{
			Hand(entry.Key, entry.Value, Object.op_Implicit((Object)(object)localPlayer) ? ((Humanoid)localPlayer).GetInventory() : null, at);
		}
		if (Object.op_Implicit((Object)(object)localPlayer))
		{
			((Character)localPlayer).Message((MessageType)2, "You take the eggs", 0, (Sprite)null, false);
		}
	}

	private static void Hand(string key, int count, Inventory inventory, Vector3 at)
	{
		//IL_00b8: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		if (!Split(key, out var prefab, out var quality))
		{
			return;
		}
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return;
		}
		int num = count;
		int val3 = Math.Max(1, val2.m_itemData.m_shared.m_maxStackSize);
		while (num > 0)
		{
			int num2 = Math.Min(num, val3);
			num -= num2;
			ItemData val4 = val2.m_itemData.Clone();
			val4.m_dropPrefab = val;
			val4.m_stack = num2;
			val4.m_quality = quality;
			if (inventory == null || !inventory.CanAddItem(val4, num2) || !inventory.AddItem(val4))
			{
				ItemDrop.DropItem(val4, num2, at + Random.insideUnitSphere * 0.3f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
			}
		}
	}

	private void OnDestroyed()
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || !view.IsOwner())
		{
			return;
		}
		Stock stock = Read();
		Write(new Stock());
		foreach (KeyValuePair<string, int> entry in stock.Entries)
		{
			Hand(entry.Key, entry.Value, null, ((Component)this).transform.position + Vector3.up * 0.5f);
		}
	}

	private void ShowEggs(Stock stock)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: 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_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: 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_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0341: Unknown result type (might be due to invalid IL or missing references)
		//IL_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)eggModels))
		{
			Object.Destroy((Object)(object)eggModels);
		}
		eggModels = null;
		if (stock.Total == 0 || GUIManager.IsHeadless() || !Object.op_Implicit((Object)(object)ObjectDB.instance))
		{
			return;
		}
		eggModels = new GameObject("Eggs");
		eggModels.SetActive(false);
		eggModels.transform.SetParent(((Component)this).transform, false);
		ZDOID uid = view.GetZDO().m_uid;
		float num = 0f;
		Random random = new Random((int)(((ZDOID)(ref uid)).ID * 31) + ((ZDOID)(ref uid)).UserID.GetHashCode());
		List<string> list = stock.Entries.SelectMany((KeyValuePair<string, int> entry) => Enumerable.Repeat(entry.Key, entry.Value)).Take(CubbyX.Length * 4).ToList();
		for (int num2 = 0; num2 < list.Count; num2++)
		{
			if (!Split(list[num2], out var prefab, out var _))
			{
				continue;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				continue;
			}
			GameObject val = Object.Instantiate<GameObject>(itemPrefab, eggModels.transform, false);
			Trough.Strip(val);
			int num3 = num2 / 4;
			int num4 = num2 % 4;
			Quaternion rotation = Quaternion.Euler(0f, (float)random.NextDouble() * 360f, 0f) * Quaternion.Euler(90f, 0f, 0f);
			val.transform.localRotation = rotation;
			float num5 = 0f;
			float num6 = 0.096f;
			if (Trough.LocalBounds(val, out var bounds))
			{
				Vector3 val2 = Vector3.Scale(((Bounds)(ref bounds)).size, val.transform.localScale);
				float num7 = Mathf.Max(val2.x, Mathf.Max(val2.y, val2.z));
				float num8 = Mathf.Min(val2.x, Mathf.Min(val2.y, val2.z));
				if (num7 > 0.001f)
				{
					float num9 = 0.12f / num7;
					Transform transform = val.transform;
					transform.localScale *= num9;
					num6 = (num7 + num8) / 2f * num9;
					if (!eggSizeLogged)
					{
						eggSizeLogged = true;
						Plugin.Log.LogInfo((object)$"Roost: {prefab} model is {num7:0.###} m long, shown at {0.12f} m.");
					}
				}
				Vector3 scale = val.transform.localScale;
				num5 = (from k in Enumerable.Range(0, 8)
					select (rotation * Vector3.Scale(new Vector3(((k & 1) == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, ((k & 2) == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, ((k & 4) == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z), scale)).y).Min();
			}
			if (num4 == 0)
			{
				num = (float)random.NextDouble() * 360f;
			}
			Vector3 val3 = Quaternion.Euler(0f, num, 0f) * (Clutch[num4] * num6 * 0.9f);
			float num10 = num6 * 0.08f;
			float num11 = CubbyX[num3] * 1.3f + val3.x + (float)(random.NextDouble() - 0.5) * num10;
			float num12 = 0.065f + val3.z + (float)(random.NextDouble() - 0.5) * num10;
			val.transform.localPosition = new Vector3(num11, 0.325f - num5, num12);
		}
		eggModels.SetActive(true);
	}
}
internal sealed class Stock
{
	private readonly List<KeyValuePair<string, int>> entries = new List<KeyValuePair<string, int>>();

	public IEnumerable<KeyValuePair<string, int>> Entries => entries;

	public int Total => entries.Sum((KeyValuePair<string, int> entry) => entry.Value);

	public static Stock Parse(string text)
	{
		Stock stock = new Stock();
		if (string.IsNullOrEmpty(text))
		{
			return stock;
		}
		string[] array = text.Split(';');
		foreach (string text2 in array)
		{
			int num = text2.LastIndexOf(':');
			if (num > 0 && int.TryParse(text2.Substring(num + 1), out var result))
			{
				stock.Add(text2.Substring(0, num), result);
			}
		}
		return stock;
	}

	public string Format()
	{
		return string.Join(";", entries.Select((KeyValuePair<string, int> entry) => entry.Key + ":" + entry.Value).ToArray());
	}

	public int Count(string item)
	{
		int num = entries.FindIndex((KeyValuePair<string, int> entry) => entry.Key == item);
		if (num >= 0)
		{
			return entries[num].Value;
		}
		return 0;
	}

	public void Add(string item, int count)
	{
		if (!string.IsNullOrEmpty(item) && count > 0 && item.IndexOf(';') < 0 && item.IndexOf(':') < 0)
		{
			int num = entries.FindIndex((KeyValuePair<string, int> entry) => entry.Key == item);
			if (num < 0)
			{
				entries.Add(new KeyValuePair<string, int>(item, count));
			}
			else
			{
				entries[num] = new KeyValuePair<string, int>(item, (int)Math.Min((long)entries[num].Value + (long)count, 2147483647L));
			}
		}
	}

	public bool Remove(string item, int count)
	{
		int num = entries.FindIndex((KeyValuePair<string, int> entry) => entry.Key == item);
		if (num < 0 || count <= 0 || entries[num].Value < count)
		{
			return false;
		}
		int num2 = entries[num].Value - count;
		if (num2 == 0)
		{
			entries.RemoveAt(num);
		}
		else
		{
			entries[num] = new KeyValuePair<string, int>(item, num2);
		}
		return true;
	}
}
public class Trough : MonoBehaviour, Hoverable, Interactable
{
	private const string FoodKey = "PotatoTrough.Food";

	private const int MaxBaitInBowl = 4;

	private const int MaxFoodModels = 20;

	private const float DispenseDelay = 3f;

	internal const float Size = 1.21f;

	internal static readonly Vector3 BowlFloor = new Vector3(0f, 0.215f, 0f) * 1.21f;

	private static readonly Vector3 BowlCenter = new Vector3(0f, 0.3f, 0f) * 1.21f;

	private static readonly Vector3 BowlHalfSize = new Vector3(0.75f, 0.15f, 0.22f) * 1.21f;

	private static int itemMask;

	internal static readonly List<Trough> All = new List<Trough>();

	private ZNetView view;

	private string shown;

	private GameObject foodModels;

	private float nextCheck;

	private float lastDispense = -100f;

	private const float InnerHalfLength = 0.847f;

	private const float InnerHalfWidth = 0.2299f;

	private const float FloorTop = 0.26862f;

	private const float MaxFoodHeight = 0.24200001f;

	private const float SinkIn = 0.35f;

	private bool Valid
	{
		get
		{
			if (Object.op_Implicit((Object)(object)view))
			{
				return view.IsValid();
			}
			return false;
		}
	}

	private void Awake()
	{
		view = ((Component)this).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)view) && view.GetZDO() != null)
		{
			All.Add(this);
			view.Register<string, int>("PotatoTrough_Add", (Action<long, string, int>)RPC_Add);
			view.Register("PotatoTrough_Take", (Action<long>)RPC_Take);
			view.Register<string>("PotatoTrough_Give", (Action<long, string>)RPC_Give);
			view.Register<string>("PotatoTrough_Feed", (Action<long, string>)RPC_Feed);
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.m_onDestroyed = (Action)Delegate.Combine(component.m_onDestroyed, new Action(OnDestroyed));
			}
		}
	}

	private void OnDestroy()
	{
		All.Remove(this);
	}

	internal Stock Read()
	{
		return Stock.Parse(Valid ? view.GetZDO().GetString("PotatoTrough.Food", "") : "");
	}

	private void Write(Stock stock)
	{
		view.GetZDO().Set("PotatoTrough.Food", stock.Format());
	}

	private void Update()
	{
		if (!(Time.time < nextCheck) && Valid)
		{
			nextCheck = Time.time + 0.5f;
			string text = (Plugin.TroughShowFood.Value ? view.GetZDO().GetString("PotatoTrough.Food", "") : "");
			if (!(text == shown))
			{
				shown = text;
				ShowFood(Stock.Parse(text));
			}
		}
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$piece_potato_trough");
	}

	public string GetHoverText()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid)
		{
			return "";
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, false, false))
		{
			return Localization.instance.Localize("$piece_potato_trough\n$piece_noaccess");
		}
		Stock stock = Read();
		string text = ((stock.Total == 0) ? "Empty" : string.Join(", ", stock.Entries.Select((KeyValuePair<string, int> entry) => entry.Value + " " + ItemName(entry.Key)).ToArray()));
		string text2 = "$piece_potato_trough" + $" ({stock.Total}/{Plugin.TroughCapacity.Value})\n" + text + "\n[<color=yellow><b>1-8</b></color>] Add food from your hotbar";
		if (stock.Total > 0)
		{
			text2 += "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] Take the food back";
		}
		return Localization.instance.Localize(text2);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		if (hold || !alt || !Valid)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		if (Read().Total > 0)
		{
			view.InvokeRPC("PotatoTrough_Take", Array.Empty<object>());
		}
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || item == null)
		{
			return false;
		}
		if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
		{
			return true;
		}
		if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !Feeding.IsAnimalFood(item))
		{
			((Character)user).Message((MessageType)2, "No animal eats that", 0, (Sprite)null, false);
			return true;
		}
		return Add(user, item);
	}

	private bool Add(Humanoid user, ItemData item)
	{
		int num = Plugin.TroughCapacity.Value - Read().Total;
		if (num <= 0)
		{
			((Character)user).Message((MessageType)2, "The trough is full", 0, (Sprite)null, false);
			return true;
		}
		int num2 = Math.Min(num, item.m_stack);
		string name = ((Object)item.m_dropPrefab).name;
		string name2 = item.m_shared.m_name;
		if (!user.GetInventory().RemoveItem(item, num2))
		{
			return true;
		}
		view.InvokeRPC("PotatoTrough_Add", new object[2] { name, num2 });
		((Character)user).Message((MessageType)2, $"$msg_added {name2} x{num2}", 0, (Sprite)null, false);
		return true;
	}

	private static string ItemName(string prefab)
	{
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return prefab;
		}
		return val2.m_itemData.m_shared.m_name;
	}

	private void RPC_Add(long sender, string prefab, int count)
	{
		if (Valid && view.IsOwner() && count > 0 && Object.op_Implicit((Object)(object)ObjectDB.instance) && Object.op_Implicit((Object)(object)ObjectDB.instance.GetItemPrefab(prefab)))
		{
			Stock stock = Read();
			stock.Add(prefab, count);
			Write(stock);
		}
	}

	private void RPC_Take(long sender)
	{
		if (Valid && view.IsOwner())
		{
			Stock stock = Read();
			if (stock.Total != 0)
			{
				Write(new Stock());
				view.InvokeRPC(sender, "PotatoTrough_Give", new object[1] { stock.Format() });
			}
		}
	}

	private void RPC_Give(long sender, string packed)
	{
		//IL_0035: 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)
		//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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: 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_0117: 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)
		Player localPlayer = Player.m_localPlayer;
		Vector3 val = (Object.op_Implicit((Object)(object)localPlayer) ? (((Component)localPlayer).transform.position + Vector3.up) : (((Component)this).transform.position + Vector3.up * 0.6f));
		foreach (KeyValuePair<string, int> entry in Stock.Parse(packed).Entries)
		{
			GameObject val2 = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(entry.Key) : null);
			ItemDrop val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				continue;
			}
			int num = entry.Value;
			int val4 = Math.Max(1, val3.m_itemData.m_shared.m_maxStackSize);
			while (num > 0)
			{
				int num2 = Math.Min(num, val4);
				num -= num2;
				Inventory val5 = (Object.op_Implicit((Object)(object)localPlayer) ? ((Humanoid)localPlayer).GetInventory() : null);
				if (val5 == null || !val5.CanAddItem(val2, num2) || !val5.AddItem(val2, num2))
				{
					ItemDrop.DropItem(Item(val2, num2), num2, val, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				}
			}
		}
		if (Object.op_Implicit((Object)(object)localPlayer))
		{
			((Character)localPlayer).Message((MessageType)2, "You take the food back", 0, (Sprite)null, false);
		}
	}

	private static ItemData Item(GameObject prefab, int count)
	{
		ItemData obj = prefab.GetComponent<ItemDrop>().m_itemData.Clone();
		obj.m_dropPrefab = prefab;
		obj.m_stack = count;
		return obj;
	}

	private void OnDestroyed()
	{
		//IL_00b7: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: 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_00e4: 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_010b: Unknown result type (might be due to invalid IL or missing references)
		if (!Valid || !view.IsOwner())
		{
			return;
		}
		Stock stock = Read();
		Write(new Stock());
		foreach (KeyValuePair<string, int> entry in stock.Entries)
		{
			GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(entry.Key) : null);
			ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				int num = entry.Value;
				int val3 = Math.Max(1, val2.m_itemData.m_shared.m_maxStackSize);
				while (num > 0)
				{
					int num2 = Math.Min(num, val3);
					num -= num2;
					Vector3 val4 = ((Component)this).transform.position + Vector3.up * 0.5f + Random.insideUnitSphere * 0.3f;
					ItemDrop.DropItem(Item(val, num2), num2, val4, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
				}
			}
		}
	}

	internal string FoodFor(MonsterAI animal)
	{
		return Read().Entries.Select((KeyValuePair<string, int> entry) => entry.Key).FirstOrDefault((string prefab) => Feeding.CanEat(animal, prefab));
	}

	internal ItemDrop Dispense(string prefab)
	{
		if (Time.time - lastDispense < 3f || BaitInBowl() >= 4)
		{
			return null;
		}
		lastDispense = Time.time;
		if (view.IsOwner())
		{
			return DropBait(prefab);
		}
		view.InvokeRPC("PotatoTrough_Feed", new object[1] { prefab });
		return null;
	}

	private void RPC_Feed(long sender, string prefab)
	{
		if (Valid && view.IsOwner() && BaitInBowl() < 4)
		{
			DropBait(prefab);
		}
	}

	private ItemDrop DropBait(string prefab)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//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_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefab) : null);
		if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.GetComponent<ItemDrop>()))
		{
			return null;
		}
		Stock stock = Read();
		if (!stock.Remove(prefab, 1))
		{
			return null;
		}
		Write(stock);
		Vector3 val2 = ((Component)this).transform.TransformPoint(BowlFloor + new Vector3(Random.Range(-0.45f, 0.45f) * 1.21f, 0.12f, Random.Range(-0.08f, 0.08f) * 1.21f));
		ItemDrop obj = ItemDrop.DropItem(Item(val, 1), 1, val2, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
		Feeding.MarkBait(obj);
		return obj;
	}

	private int BaitInBowl()
	{
		//IL_002b: 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_0035: 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)
		if (itemMask == 0)
		{
			itemMask = LayerMask.GetMask(new string[1] { "item" });
		}
		HashSet<ItemDrop> hashSet = new HashSet<ItemDrop>();
		Collider[] array = Physics.OverlapBox(((Component)this).transform.TransformPoint(BowlCenter), BowlHalfSize, ((Component)this).transform.rotation, itemMask);
		foreach (Collider val in array)
		{
			ItemDrop val2 = (Object.op_Implicit((Object)(object)val.attachedRigidbody) ? ((Component)val.attachedRigidbody).GetComponent<ItemDrop>() : null);
			if (Object.op_Implicit((Object)(object)val2) && Feeding.IsBait(val2))
			{
				hashSet.Add(val2);
			}
		}
		return hashSet.Count;
	}

	private void ShowFood(Stock stock)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)foodModels))
		{
			Object.Destroy((Object)(object)foodModels);
		}
		foodModels = null;
		int total = stock.Total;
		if (total == 0 || GUIManager.IsHeadless() || !Object.op_Implicit((Object)(object)ObjectDB.instance) || !Valid)
		{
			return;
		}
		foodModels = new GameObject("Food");
		foodModels.SetActive(false);
		foodModels.transform.SetParent(((Component)this).transform, false);
		int num = Mathf.Clamp(Mathf.CeilToInt((float)total / 3f), 1, 20);
		int i = 0;
		ZDOID uid = view.GetZDO().m_uid;
		Random random = new Random((int)(((ZDOID)(ref uid)).ID * 31) + ((ZDOID)(ref uid)).UserID.GetHashCode());
		List<GameObject> list = new List<GameObject>();
		foreach (KeyValuePair<string, int> entry in stock.Entries)
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(entry.Key);
			if (!Object.op_Implicit((Object)(object)itemPrefab))
			{
				continue;
			}
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * (float)entry.Value / (float)total));
			for (int j = 0; j < num2; j++)
			{
				if (list.Count >= num)
				{
					break;
				}
				list.Add(itemPrefab);
			}
		}
		for (int num3 = list.Count - 1; num3 > 0; num3--)
		{
			int num4 = random.Next(num3 + 1);
			List<GameObject> list2 = list;
			int index = num3;
			int index2 = num4;
			GameObject value = list[num4];
			GameObject value2 = list[num3];
			list2[index] = value;
			list[index2] = value2;
		}
		for (; i < list.Count; i++)
		{
			GameObject copy = Object.Instantiate<GameObject>(list[i], foodModels.transform, false);
			Strip(copy);
			float num5 = ((list.Count == 1) ? 0f : Mathf.Lerp(-0.66550004f, 0.66550004f, (float)i / (float)(list.Count - 1)));
			Place(copy, num5 + (float)(random.NextDouble() - 0.5) * 0.12f, (float)random.NextDouble(), random);
		}
		foodModels.SetActive(true);
	}

	private static void Place(GameObject copy, float wantX, float sideways, Random random)
	{
		//IL_000c: 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_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: 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_007f: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: 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_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: 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_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Unknown result type (might be due to invalid IL or missing references)
		//IL_031b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		Vector3 localScale = copy.transform.localScale;
		if (!LocalBounds(copy, out var bounds))
		{
			copy.transform.localPosition = new Vector3(Mathf.Clamp(wantX, -0.7260001f, 0.7260001f), 0.29862002f, 0f);
			return;
		}
		Vector3 size = Vector3.Scale(((Bounds)(ref bounds)).size, localScale);
		Vector3[] array = (Vector3[])(object)new Vector3[3]
		{
			Vector3.right,
			Vector3.up,
			Vector3.forward
		};
		int[] array2 = new int[3] { 0, 1, 2 }.OrderByDescending((int axis) => ((Vector3)(ref size))[axis]).ToArray();
		Quaternion val = Quaternion.Inverse(Quaternion.LookRotation(array[array2[1]], array[array2[2]]));
		Quaternion val2 = Quaternion.Euler(0f, (float)random.Next(2) * 180f + (float)(random.NextDouble() - 0.5) * 24f, 0f) * val;
		Vector3[] array3 = (Vector3[])(object)new Vector3[8];
		Vector3 val3 = default(Vector3);
		for (int num = 0; num < 8; num++)
		{
			((Vector3)(ref val3))..ctor(((num & 1) == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, ((num & 2) == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, ((num & 4) == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z);
			array3[num] = val2 * Vector3.Scale(val3, localScale);
		}
		Vector3 val4 = ((IEnumerable<Vector3>)array3).Aggregate((Func<Vector3, Vector3, Vector3>)Vector3.Min);
		Vector3 val5 = ((IEnumerable<Vector3>)array3).Aggregate((Func<Vector3, Vector3, Vector3>)Vector3.Max);
		Vector3 val6 = val5 - val4;
		float num2 = Mathf.Min(new float[4]
		{
			1f,
			1.694f / Mathf.Max(val6.x, 0.001f),
			0.4598f / Mathf.Max(val6.z, 0.001f),
			0.24200001f / Mathf.Max(val6.y, 0.001f)
		});
		val4 *= num2;
		val5 *= num2;
		float num3 = -0.847f - val4.x;
		float num4 = 0.847f - val5.x;
		float num5 = -0.2299f - val4.z;
		float num6 = 0.2299f - val5.z;
		float num7 = ((num3 <= num4) ? Mathf.Clamp(wantX, num3, num4) : ((num3 + num4) / 2f));
		float num8 = ((num5 <= num6) ? Mathf.Lerp(num5, num6, sideways) : ((num5 + num6) / 2f));
		copy.transform.localScale = localScale * num2;
		copy.transform.localRotation = val2;
		copy.transform.localPosition = new Vector3(num7, 0.26862f - val4.y - (val5.y - val4.y) * 0.35f, num8);
	}

	private static bool Shown(Transform part, Transform root)
	{
		while (Object.op_Implicit((Object)(object)part) && (Object)(object)part != (Object)(object)root)
		{
			if (!((Component)part).gameObject.activeSelf)
			{
				return false;
			}
			part = part.parent;
		}
		return true;
	}

	internal static bool LocalBounds(GameObject copy, out Bounds bounds)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: 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_00cc: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or mi