Decompiled source of LeashMe Nursery v0.1.0

LeashMe.Nursery.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LeashMe.Nursery")]
[assembly: AssemblyProduct("LeashMe.Nursery")]
[assembly: ComVisible(false)]
[assembly: Guid("6f1c2a4e-8b3d-4e5f-9a71-2c4d8e0b5f13")]
[assembly: AssemblyFileVersion("0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
namespace LeashMe
{
	internal static class EmbeddedSprite
	{
		public static Sprite Load(string fileName)
		{
			//IL_0080: 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)
			using Stream stream = typeof(EmbeddedSprite).Assembly.GetManifestResourceStream("LeashMe." + fileName);
			if (stream == null)
			{
				Logger.LogWarning((object)("Embedded icon " + fileName + " not found."));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = AssetUtils.LoadImage(array);
			return Object.op_Implicit((Object)(object)val) ? Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)) : null;
		}
	}
	internal static class ModelIcon
	{
		private const int RenderSize = 256;

		[Conditional("DEBUG")]
		public static void Export(GameObject visual, Quaternion rotation, string fileName, int thicken = 0, float brightness = 1f)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			string environmentVariable = Environment.GetEnvironmentVariable("LEASHME_ICON_EXPORT");
			if (string.IsNullOrWhiteSpace(environmentVariable) || !Object.op_Implicit((Object)(object)visual))
			{
				return;
			}
			Texture2D val = null;
			try
			{
				Sprite val2 = RenderManager.Instance.Render(new RenderRequest(visual)
				{
					Width = 256,
					Height = 256,
					Rotation = rotation,
					UseCache = false,
					ParticleSimulationTime = -1f
				});
				if (!Object.op_Implicit((Object)(object)val2) || ((Texture)val2.texture).width != 256 || ((Texture)val2.texture).height != 256)
				{
					Logger.LogWarning((object)("Could not render icon " + fileName + "."));
					return;
				}
				Rect val3 = VisibleSquare(val2.texture);
				val = new Texture2D((int)((Rect)(ref val3)).width, (int)((Rect)(ref val3)).height, (TextureFormat)4, false);
				val.SetPixels(val2.texture.GetPixels((int)((Rect)(ref val3)).x, (int)((Rect)(ref val3)).y, (int)((Rect)(ref val3)).width, (int)((Rect)(ref val3)).height));
				val.SetPixels32(Emphasize(val.GetPixels32(), ((Texture)val).width, ((Texture)val).height, thicken, brightness));
				val.Apply();
				Directory.CreateDirectory(environmentVariable);
				string text = Path.Combine(environmentVariable, fileName + ".png");
				File.WriteAllBytes(text, ImageConversion.EncodeToPNG(val));
				Logger.LogInfo((object)("Exported icon: " + text));
			}
			catch (Exception arg)
			{
				Logger.LogWarning((object)$"Could not export icon {fileName}: {arg}");
			}
			finally
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static Color32[] Emphasize(Color32[] source, int width, int height, int radius, float brightness)
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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_014e: 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_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			Color32[] array = (Color32[])source.Clone();
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					if (radius <= 0 || source[i * width + j].a >= 128)
					{
						continue;
					}
					int num = 0;
					int num2 = 0;
					int num3 = 0;
					int num4 = 0;
					for (int k = -radius; k <= radius; k++)
					{
						for (int l = -radius; l <= radius; l++)
						{
							int num5 = j + l;
							int num6 = i + k;
							if (l * l + k * k <= radius * radius && num5 >= 0 && num6 >= 0 && num5 < width && num6 < height)
							{
								Color32 val = source[num6 * width + num5];
								if (val.a >= 128)
								{
									num2 += val.r;
									num3 += val.g;
									num4 += val.b;
									num++;
								}
							}
						}
					}
					if (num > 0)
					{
						array[i * width + j] = new Color32((byte)(num2 / num), (byte)(num3 / num), (byte)(num4 / num), byte.MaxValue);
					}
				}
			}
			for (int m = 0; m < array.Length; m++)
			{
				Color32 val2 = array[m];
				array[m] = new Color32((byte)Mathf.Min(255f, (float)(int)val2.r * brightness), (byte)Mathf.Min(255f, (float)(int)val2.g * brightness), (byte)Mathf.Min(255f, (float)(int)val2.b * brightness), val2.a);
			}
			return array;
		}

		private static Rect VisibleSquare(Texture2D texture)
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			int width = ((Texture)texture).width;
			int height = ((Texture)texture).height;
			Color32[] pixels = texture.GetPixels32();
			int num = width;
			int num2 = height;
			int num3 = -1;
			int num4 = -1;
			for (int i = 0; i < height; i++)
			{
				for (int j = 0; j < width; j++)
				{
					if (pixels[i * width + j].a != 0)
					{
						num = Mathf.Min(num, j);
						num2 = Mathf.Min(num2, i);
						num3 = Mathf.Max(num3, j);
						num4 = Mathf.Max(num4, i);
					}
				}
			}
			if (num3 < num)
			{
				return new Rect(0f, 0f, (float)width, (float)height);
			}
			int num5 = Mathf.Max(num3 - num + 1, num4 - num2 + 1);
			int num6 = Mathf.CeilToInt((float)num5 * 0.04f);
			int num7 = Mathf.Min(num5 + 2 * num6, Mathf.Min(width, height));
			int num8 = Mathf.Clamp((num + num3 + 1 - num7) / 2, 0, width - num7);
			int num9 = Mathf.Clamp((num2 + num4 + 1 - num7) / 2, 0, height - num7);
			return new Rect((float)num8, (float)num9, (float)num7, (float)num7);
		}
	}
}
namespace LeashMe.Nursery
{
	[HarmonyPatch]
	internal static class NurseryAnimals
	{
		private enum Phase
		{
			Free,
			Requested,
			Confirmed
		}

		private sealed class State
		{
			public NurseryFood.Species Species;

			public bool Owned;

			public Phase Phase;

			public NurseryStation Station;

			public long RequestId;

			public Vector3 Center;

			public Vector3 Ground;

			public bool Arrived;

			public float PickTimer;

			public bool Paused;

			public Vector3 WaitPoint;

			public float SearchTimer;

			public float RequestTimer;

			public float RenewTimer;

			public float PauseTimer;

			public NurseryStation Retry;

			public float RetryTimer;

			public NurseryStation Remembered;

			public float RememberTimer;

			public float RememberFailTime;

			public float NoWayAt = -1f;

			public readonly List<NurseryStation> Round = new List<NurseryStation>();

			public Dictionary<NurseryStation, float> NoPathUntil;

			public int Cursor;
		}

		private const float SearchSeconds = 2f;

		private const float NoPathSeconds = 10f;

		private const float WayCheckSeconds = 10f;

		private const float SearchAfterDropSeconds = 0.5f;

		private const float RetrySeconds = 30f;

		private const float RequestTimeoutSeconds = 20f;

		private const float RenewSeconds = 10f;

		private const float PauseCheckSeconds = 30f;

		private const float RememberFirstSeconds = 1f;

		private const float RememberMinSeconds = 2f;

		private const float RememberMaxSeconds = 5f;

		private const float RememberGiveUpSeconds = 60f;

		private const float NoWayMinSeconds = 5f;

		private const float NoWayMaxSeconds = 60f;

		private const int PathChecksPerSearch = 2;

		private const float MaxCenterShift = 4f;

		private const float EdgeMargin = 0.3f;

		private const float MinCutLength = 1.5f;

		private const float GapMargin = 0.5f;

		private const float PickRetryMinSeconds = 0.5f;

		private const float PickRetryMaxSeconds = 1.5f;

		private static readonly ConditionalWeakTable<BaseAI, State> s_states = new ConditionalWeakTable<BaseAI, State>();

		private static readonly List<NurseryStation> s_expired = new List<NurseryStation>();

		public static void ReleaseAll()
		{
			foreach (BaseAI instance in BaseAI.m_instances)
			{
				if (Object.op_Implicit((Object)(object)instance) && s_states.TryGetValue(instance, out var value) && value.Phase != Phase.Free)
				{
					Drop(instance, value);
				}
			}
		}

		[HarmonyPatch(typeof(BaseAI), "UpdateAI")]
		[HarmonyPostfix]
		private static void UpdateAIPostfix(BaseAI __instance, float dt, bool __result)
		{
			if (NurseryStation.All.Count == 0)
			{
				return;
			}
			State value = s_states.GetValue(__instance, Create);
			if (value.Species == null)
			{
				return;
			}
			if (!__result || !__instance.m_character.IsTamed())
			{
				if (value.Phase != Phase.Free)
				{
					Drop(__instance, value);
				}
				value.Owned = false;
				return;
			}
			if (!value.Owned)
			{
				value.Owned = true;
				TakeOver(__instance, value);
			}
			Maintain(__instance, value, dt);
		}

		[HarmonyPatch(typeof(BaseAI), "IdleMovement")]
		[HarmonyPrefix]
		private static bool IdleMovementPrefix(BaseAI __instance, float dt)
		{
			if (NurseryStation.All.Count == 0 || !s_states.TryGetValue(__instance, out var value) || value.Species == null || !value.Owned)
			{
				return true;
			}
			switch (value.Phase)
			{
			case Phase.Free:
				TickFree(__instance, value, dt);
				return true;
			case Phase.Requested:
				return true;
			default:
				Move(__instance, value, dt);
				return false;
			}
		}

		[HarmonyPatch(typeof(Tameable), "GetHoverText")]
		[HarmonyPostfix]
		private static void TameableHoverPostfix(Tameable __instance)
		{
			ShowStationConnection(__instance.m_nview);
		}

		[HarmonyPatch(typeof(Character), "GetHoverText")]
		[HarmonyPostfix]
		private static void CharacterHoverPostfix(Character __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Tameable>()))
			{
				ShowStationConnection(__instance.m_nview);
			}
		}

		private static void ShowStationConnection(ZNetView nview)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (NurseryStation.All.Count != 0 && Object.op_Implicit((Object)(object)nview) && nview.IsValid())
			{
				NurseryStation nurseryStation = NurseryStation.Of(nview.GetZDO().m_uid);
				if (Object.op_Implicit((Object)(object)nurseryStation))
				{
					nurseryStation.ShowConnection(nview.GetZDO().m_uid);
				}
			}
		}

		private static State Create(BaseAI ai)
		{
			return new State
			{
				Species = NurseryFood.FindYoung(((Component)ai).gameObject),
				SearchTimer = Random.Range(0f, 2f),
				RememberTimer = Random.Range(0f, 1f)
			};
		}

		private static void Maintain(BaseAI ai, State state, float dt)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			if (state.Phase != Phase.Free && (!Object.op_Implicit((Object)(object)state.Station) || !state.Station.IsValid))
			{
				Drop(ai, state);
			}
			switch (state.Phase)
			{
			case Phase.Requested:
				if (state.Station.LeaseOf(ai.m_nview.GetZDO().m_uid) == state.RequestId)
				{
					Confirm(ai, state);
					Remember(ai, state.Station);
					break;
				}
				state.RequestTimer -= dt;
				if (state.RequestTimer <= 0f)
				{
					if (Remembers(ai, state.Station) && !state.Station.InUse && !state.Station.HasFreePlace)
					{
						Forget(ai);
					}
					Drop(ai, state);
				}
				return;
			case Phase.Free:
				return;
			}
			if (state.Station.LeaseOf(ai.m_nview.GetZDO().m_uid) != state.RequestId)
			{
				Drop(ai, state);
				state.RememberTimer = 0f;
				return;
			}
			state.RenewTimer -= dt;
			if (state.RenewTimer <= 0f)
			{
				state.RenewTimer = 10f;
				Invoke(ai, state, "LeashMe_NurseryRenew");
				Remember(ai, state.Station);
			}
			state.SearchTimer -= dt;
			if (state.SearchTimer <= 0f)
			{
				state.SearchTimer = 10f;
				if (Utils.DistanceXZ(((Component)ai).transform.position, state.Center) > 2f * state.Species.MoveRadius && !ai.HavePath(state.Center))
				{
					NoWay(ai, state);
				}
			}
		}

		private static void Move(BaseAI ai, State state, float dt)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			if (!state.Paused && !state.Arrived && state.Station.InUse)
			{
				state.Paused = true;
				state.WaitPoint = ((Component)ai).transform.position;
				state.PauseTimer = Random.Range(0.5f, 1f) * 30f;
				ai.m_randomMoveUpdateTimer = 0f;
			}
			if (state.Paused)
			{
				state.PauseTimer -= dt;
				if (state.PauseTimer <= 0f)
				{
					state.PauseTimer = 30f;
					if (!state.Station.InUse)
					{
						state.Paused = false;
						ai.m_randomMoveUpdateTimer = 0f;
					}
				}
				if (state.Paused)
				{
					ai.RandomMovement(dt, state.WaitPoint, true);
					return;
				}
			}
			float moveRadius = state.Species.MoveRadius;
			float num = Utils.DistanceXZ(((Component)ai).transform.position, state.Center);
			if (state.Arrived && num > 2f * moveRadius)
			{
				state.Arrived = false;
			}
			if (!state.Arrived)
			{
				float num2 = moveRadius / 2f;
				if (num <= num2)
				{
					state.Arrived = true;
					state.PickTimer = 0f;
					ai.m_randomMoveUpdateTimer = 0f;
				}
				else if (ai.MoveTo(dt, state.Center, num2, num > 2f * moveRadius))
				{
					if (Utils.DistanceXZ(((Component)ai).transform.position, state.Center) <= num2 + 0.5f)
					{
						state.Arrived = true;
						state.PickTimer = 0f;
						ai.m_randomMoveUpdateTimer = 0f;
					}
					else
					{
						NoWay(ai, state);
					}
				}
				if (!state.Arrived)
				{
					return;
				}
			}
			if (ai.m_randomMoveUpdateTimer <= 0f)
			{
				state.PickTimer -= dt;
				if (state.PickTimer > 0f || !TryPickTarget(ai, state, moveRadius))
				{
					if (state.PickTimer <= 0f)
					{
						state.PickTimer = Random.Range(0.5f, 1.5f);
					}
					ai.m_reachedRandomMoveTarget = true;
					ai.StopMoving();
					return;
				}
				state.PickTimer = 0f;
			}
			float randomMoveRange = ai.m_randomMoveRange;
			try
			{
				ai.m_randomMoveRange = moveRadius;
				ai.RandomMovement(dt, state.Ground, false);
			}
			finally
			{
				ai.m_randomMoveRange = randomMoveRange;
			}
		}

		private static bool TryPickTarget(BaseAI ai, State state, float radius)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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)
			Pathfinding.instance.PokeArea(state.Ground, ai.m_pathAgentType);
			Vector3 val = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f) * Vector3.forward * Random.Range(0.7f * radius, radius);
			Vector3 val2 = state.Ground + val;
			if (!state.Station.TryGetGround(val2, state.Center.y, out var height) || !TryCutToEdge(ai, state, new Vector3(val2.x, height, val2.z), out var target) || !ai.IsValidRandomMovePoint(target))
			{
				return false;
			}
			ai.m_randomMoveTarget = target;
			ai.m_reachedRandomMoveTarget = false;
			float randomMoveInterval = ai.m_randomMoveInterval;
			ai.m_randomMoveUpdateTimer = Random.Range(randomMoveInterval, randomMoveInterval + randomMoveInterval / 2f);
			ai.m_lastFindPathTime = float.MinValue;
			return true;
		}

		private static bool TryCutToEdge(BaseAI ai, State state, Vector3 to, out Vector3 target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00c7: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			target = to;
			Vector3 val = to - state.Ground;
			val.y = 0f;
			float num = Utils.DistanceXZ(state.Center, state.Ground) + 0.5f;
			if (((Vector3)(ref val)).magnitude <= num)
			{
				return false;
			}
			AgentSettings settings = Pathfinding.instance.GetSettings(ai.m_pathAgentType);
			NavMeshQueryFilter val2 = default(NavMeshQueryFilter);
			((NavMeshQueryFilter)(ref val2)).agentTypeID = ((NavMeshBuildSettings)(ref settings.m_build)).agentTypeID;
			((NavMeshQueryFilter)(ref val2)).areaMask = settings.m_areaMask;
			NavMeshQueryFilter val3 = val2;
			Vector3 val4 = state.Ground + ((Vector3)(ref val)).normalized * num;
			val4.y = state.Center.y;
			NavMeshHit val5 = default(NavMeshHit);
			if (!NavMesh.SamplePosition(val4, ref val5, 1.5f, val3))
			{
				return false;
			}
			Vector3 position = ((NavMeshHit)(ref val5)).position;
			NavMeshHit val6 = default(NavMeshHit);
			if (!NavMesh.Raycast(position, to, ref val6, val3))
			{
				return true;
			}
			Vector3 val7 = ((NavMeshHit)(ref val6)).position - position;
			val7.y = 0f;
			float num2 = ((Vector3)(ref val7)).magnitude - 0.3f;
			if (num2 < 1.5f)
			{
				return false;
			}
			target = position + ((Vector3)(ref val7)).normalized * num2;
			target.y = ((NavMeshHit)(ref val6)).position.y;
			return state.Station.InTargetHeight(target.y);
		}

		private static bool TryGetCenter(BaseAI ai, NurseryStation station, out Vector3 center, out Vector3 ground)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			center = (ground = Vector3.zero);
			Pathfinding instance = Pathfinding.instance;
			if (!Object.op_Implicit((Object)(object)instance) || !station.TryGetTargetPoint(out ground))
			{
				return false;
			}
			instance.PokeArea(ground, ai.m_pathAgentType);
			center = ground;
			if (instance.SnapToNavMesh(ref center, true, instance.GetSettings(ai.m_pathAgentType)) && Utils.DistanceXZ(center, ground) <= 4f && Mathf.Abs(center.y - ground.y) <= 4f)
			{
				return station.InTargetHeight(center.y);
			}
			return false;
		}

		private static void TickFree(BaseAI ai, State state, float dt)
		{
			if (TickRemembered(ai, state, dt))
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)state.Retry))
			{
				state.RetryTimer -= dt;
				if (!(state.RetryTimer > 0f))
				{
					NurseryStation retry = state.Retry;
					state.Retry = null;
					if (retry.IsValid && retry.InUse)
					{
						state.Retry = retry;
						state.RetryTimer = 30f;
					}
					else if (retry.IsValid && Fits(ai, state, retry))
					{
						TryRequest(ai, state, retry);
					}
				}
			}
			else
			{
				state.SearchTimer -= dt;
				if (!(state.SearchTimer > 0f))
				{
					state.SearchTimer = 2f;
					Search(ai, state);
				}
			}
		}

		private static bool TickRemembered(BaseAI ai, State state, float dt)
		{
			if (Object.op_Implicit((Object)(object)state.Remembered) && state.Remembered.IsValid && !state.Remembered.InUse)
			{
				state.RememberFailTime += dt;
			}
			state.RememberTimer -= dt;
			if (state.RememberTimer <= 0f)
			{
				state.RememberTimer = Random.Range(2f, 5f);
				state.Remembered = FindRemembered(ai);
				NurseryStation remembered = state.Remembered;
				if (!Object.op_Implicit((Object)(object)remembered) || remembered.InUse)
				{
					state.RememberFailTime = 0f;
				}
				else if (remembered.Generation != ai.m_nview.GetZDO().GetInt(NurseryStation.MemberGenerationKey, 0))
				{
					Forget(ai);
					state.Remembered = null;
				}
				else if (state.RememberFailTime >= 60f)
				{
					Forget(ai);
					state.Remembered = null;
					state.RememberFailTime = 0f;
				}
				else if (remembered.Species == state.Species)
				{
					TryRequest(ai, state, remembered);
				}
			}
			if (Object.op_Implicit((Object)(object)state.Remembered))
			{
				return state.Remembered.IsValid;
			}
			return false;
		}

		private static void NoWay(BaseAI ai, State state)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			float num = Time.time - state.NoWayAt;
			if (state.NoWayAt >= 0f && num >= 5f && num <= 60f && !ai.HavePath(state.Center))
			{
				Forget(ai);
				state.NoWayAt = -1f;
			}
			else if (state.NoWayAt < 0f || num > 60f)
			{
				state.NoWayAt = Time.time;
			}
			Drop(ai, state);
		}

		private static NurseryStation FindRemembered(BaseAI ai)
		{
			int num = ai.m_nview.GetZDO().GetInt(NurseryStation.MemberKey, 0);
			if (num == 0)
			{
				return null;
			}
			foreach (NurseryStation item in NurseryStation.All)
			{
				if (item.IsValid && item.Number == num)
				{
					return item;
				}
			}
			return null;
		}

		private static bool Remembers(BaseAI ai, NurseryStation station)
		{
			int number = station.Number;
			if (number > 0)
			{
				return ai.m_nview.GetZDO().GetInt(NurseryStation.MemberKey, 0) == number;
			}
			return false;
		}

		private static void Remember(BaseAI ai, NurseryStation station)
		{
			int number = station.Number;
			int generation = station.Generation;
			ZDO zDO = ai.m_nview.GetZDO();
			if (number > 0 && (zDO.GetInt(NurseryStation.MemberKey, 0) != number || zDO.GetInt(NurseryStation.MemberGenerationKey, 0) != generation))
			{
				zDO.Set(NurseryStation.MemberKey, number, false);
				zDO.Set(NurseryStation.MemberGenerationKey, generation, false);
			}
		}

		private static void Forget(BaseAI ai)
		{
			ZDO zDO = ai.m_nview.GetZDO();
			if (zDO.GetInt(NurseryStation.MemberKey, 0) != 0)
			{
				zDO.Set(NurseryStation.MemberKey, 0, false);
				zDO.Set(NurseryStation.MemberGenerationKey, 0, false);
			}
		}

		private static void Search(BaseAI ai, State state)
		{
			//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)
			if (state.Cursor >= state.Round.Count)
			{
				state.Round.Clear();
				state.Cursor = 0;
				foreach (NurseryStation item in NurseryStation.All)
				{
					if (Fits(ai, state, item))
					{
						state.Round.Add(item);
					}
				}
				Vector3 position = ((Component)ai).transform.position;
				state.Round.Sort((NurseryStation a, NurseryStation b) => Utils.DistanceXZ(position, ((Component)a).transform.position).CompareTo(Utils.DistanceXZ(position, ((Component)b).transform.position)));
			}
			int num = 0;
			while (state.Cursor < state.Round.Count && num < 2)
			{
				NurseryStation nurseryStation = state.Round[state.Cursor++];
				if (!Object.op_Implicit((Object)(object)nurseryStation) || !nurseryStation.IsValid || !Fits(ai, state, nurseryStation) || NoPath(state, nurseryStation))
				{
					continue;
				}
				if (nurseryStation.InUse)
				{
					if (!Object.op_Implicit((Object)(object)state.Retry))
					{
						state.Retry = nurseryStation;
						state.RetryTimer = Random.Range(0.8f, 1.2f) * 30f;
					}
					continue;
				}
				num++;
				if (TryRequest(ai, state, nurseryStation))
				{
					state.Round.Clear();
					state.Cursor = 0;
					break;
				}
				SetNoPath(state, nurseryStation);
			}
		}

		private static bool NoPath(State state, NurseryStation station)
		{
			if (state.NoPathUntil != null && state.NoPathUntil.TryGetValue(station, out var value))
			{
				return Time.time < value;
			}
			return false;
		}

		private static void SetNoPath(State state, NurseryStation station)
		{
			if (state.NoPathUntil == null)
			{
				state.NoPathUntil = new Dictionary<NurseryStation, float>();
			}
			else
			{
				s_expired.Clear();
				foreach (KeyValuePair<NurseryStation, float> item in state.NoPathUntil)
				{
					if (!Object.op_Implicit((Object)(object)item.Key) || Time.time >= item.Value)
					{
						s_expired.Add(item.Key);
					}
				}
				foreach (NurseryStation item2 in s_expired)
				{
					state.NoPathUntil.Remove(item2);
				}
			}
			state.NoPathUntil[station] = Time.time + 10f;
		}

		private static bool Fits(BaseAI ai, State state, NurseryStation station)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (station.Species == state.Species && station.HasFreePlace)
			{
				return Utils.DistanceXZ(((Component)ai).transform.position, ((Component)station).transform.position) <= state.Species.PickupRadius;
			}
			return false;
		}

		private static bool TryRequest(BaseAI ai, State state, NurseryStation station)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetCenter(ai, station, out var center, out var ground) || !ai.HavePath(center))
			{
				return false;
			}
			state.Station = station;
			state.Center = center;
			state.Ground = ground;
			state.RequestId = NewRequestId();
			state.Phase = Phase.Requested;
			state.RequestTimer = 20f;
			state.Retry = null;
			Invoke(ai, state, "LeashMe_NurseryRequest");
			return true;
		}

		private static void TakeOver(BaseAI ai, State state)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			ZDOID uid = ai.m_nview.GetZDO().m_uid;
			NurseryStation nurseryStation = null;
			long requestId = 0L;
			float num = float.MaxValue;
			foreach (NurseryStation item in NurseryStation.All)
			{
				long num2 = (item.IsValid ? item.LeaseOf(uid) : 0);
				float num3 = Utils.DistanceXZ(((Component)ai).transform.position, ((Component)item).transform.position);
				if (num2 != 0L && num3 < num)
				{
					nurseryStation = item;
					requestId = num2;
					num = num3;
				}
			}
			if (Object.op_Implicit((Object)(object)nurseryStation) && TryGetCenter(ai, nurseryStation, out var center, out var ground))
			{
				state.Station = nurseryStation;
				state.Center = center;
				state.Ground = ground;
				state.RequestId = requestId;
				state.Phase = Phase.Requested;
				Confirm(ai, state);
				Remember(ai, state.Station);
				Invoke(ai, state, "LeashMe_NurseryRenew");
			}
		}

		private static void Confirm(BaseAI ai, State state)
		{
			state.RememberFailTime = 0f;
			state.SearchTimer = 10f;
			state.Phase = Phase.Confirmed;
			state.Arrived = false;
			state.Paused = false;
			state.RenewTimer = Random.Range(0.5f, 1f) * 10f;
			ai.m_randomMoveUpdateTimer = 0f;
		}

		private static void Drop(BaseAI ai, State state)
		{
			if (state.Phase == Phase.Confirmed)
			{
				ai.m_randomMoveUpdateTimer = 0f;
			}
			state.Phase = Phase.Free;
			state.Station = null;
			state.SearchTimer = Random.Range(0f, 0.5f);
			state.RequestId = 0L;
			state.Paused = false;
			state.Arrived = false;
		}

		private static void Invoke(BaseAI ai, State state, string rpc)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			state.Station.NetView.InvokeRPC(rpc, new object[3]
			{
				ai.m_nview.GetZDO().m_uid,
				state.RequestId,
				state.Station.Generation
			});
		}

		private static long NewRequestId()
		{
			long num;
			do
			{
				num = ((long)Random.Range(int.MinValue, int.MaxValue) << 32) ^ (uint)Random.Range(int.MinValue, int.MaxValue);
			}
			while (num == 0L);
			return num;
		}
	}
	[HarmonyPatch]
	internal static class NurseryContainerPatches
	{
		private static readonly object Filled = new object();

		private static readonly ConditionalWeakTable<Inventory, object> s_filled = new ConditionalWeakTable<Inventory, object>();

		private static bool s_loading;

		[HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage) })]
		[HarmonyPatch(typeof(Inventory), "Load", new Type[]
		{
			typeof(ZPackage),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static void LoadPrefix()
		{
			s_loading = true;
		}

		[HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage) })]
		[HarmonyPatch(typeof(Inventory), "Load", new Type[]
		{
			typeof(ZPackage),
			typeof(bool)
		})]
		[HarmonyFinalizer]
		private static void LoadFinalizer()
		{
			s_loading = false;
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(int),
			typeof(int),
			typeof(int),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static bool AddAmountPrefix(Inventory __instance, ItemData item, ref int amount, ref bool __result)
		{
			if (s_loading || !IsNursery(__instance))
			{
				return true;
			}
			int num = Allowed(__instance, item);
			if (num <= 0)
			{
				__result = false;
				return false;
			}
			amount = Mathf.Min(amount, num);
			return true;
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
		[HarmonyPrefix]
		private static bool AddItemPrefix(Inventory __instance, ItemData item, ref bool __result)
		{
			return WholeItemPrefix(__instance, item, ref __result);
		}

		[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
		{
			typeof(ItemData),
			typeof(Vector2i)
		})]
		[HarmonyPrefix]
		private static bool AddItemAtPrefix(Inventory __instance, ItemData item, ref bool __result)
		{
			return WholeItemPrefix(__instance, item, ref __result);
		}

		private static bool WholeItemPrefix(Inventory inventory, ItemData item, ref bool result)
		{
			//IL_004b: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (s_loading || !IsNursery(inventory))
			{
				return true;
			}
			int num = Allowed(inventory, item);
			if (num >= item.m_stack)
			{
				return true;
			}
			if (num > 0)
			{
				Vector2i val = (Vector2i)((inventory.m_inventory.Count > 0) ? inventory.m_inventory[0].m_gridPos : new Vector2i(0, 0));
				inventory.AddItem(item, num, val.x, val.y, false);
			}
			result = false;
			return false;
		}

		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		[HarmonyPrefix]
		private static bool DropItemPrefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!IsNursery(__instance.m_inventory) && !IsNursery(fromInventory))
			{
				return true;
			}
			ItemData itemAt = __instance.m_inventory.GetItemAt(pos.x, pos.y);
			if (itemAt == null || itemAt == item || item.m_stack != amount || (!(itemAt.m_shared.m_name != item.m_shared.m_name) && (item.m_shared.m_maxQuality <= 1 || itemAt.m_quality == item.m_quality) && itemAt.m_shared.m_maxStackSize != 1))
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPatch(typeof(Inventory), "Changed")]
		[HarmonyPostfix]
		private static void ChangedPostfix(Inventory __instance)
		{
			if (!IsNursery(__instance))
			{
				return;
			}
			object value;
			bool num = s_filled.TryGetValue(__instance, out value);
			bool flag = __instance.m_inventory.Count > 0;
			if (num == flag)
			{
				return;
			}
			if (flag)
			{
				s_filled.Add(__instance, Filled);
			}
			else
			{
				s_filled.Remove(__instance);
			}
			if (!s_loading && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				NurseryFood.Species species = (flag ? NurseryFood.Find(__instance.m_inventory[0]) : null);
				if (!flag || species != null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, flag ? Localization.instance.Localize("$leashme_nursery_now", new string[1] { Localization.instance.Localize(species.YoungName) }) : "$leashme_nursery_none", 0, (Sprite)null, false);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGrid), "UpdateGui")]
		[HarmonyPostfix]
		private static void UpdateGuiPostfix(InventoryGrid __instance)
		{
			Inventory inventory = __instance.m_inventory;
			if (inventory != null && IsNursery(inventory) && inventory.m_inventory.Count != 0)
			{
				ItemData val = inventory.m_inventory[0];
				NurseryFood.Species species = NurseryFood.Find(val);
				InventoryElement val2 = ((species != null) ? __instance.GetElement(val.m_gridPos.x, val.m_gridPos.y, inventory.GetWidth()) : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.m_amount.text = $"{val.m_stack}/{species.Limit}";
				}
			}
		}

		[HarmonyPatch(typeof(Container), "GetHoverText")]
		[HarmonyPostfix]
		private static void GetHoverTextPostfix(Container __instance, ref string __result)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetStation(__instance, out var station) || (__instance.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false)))
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			station.ShowAreas((Object.op_Implicit((Object)(object)localPlayer) && ((Character)localPlayer).TakeInput() && ZInput.GetKeyDown((KeyCode)110, true)) ? 15f : 0.5f);
			string text = station.DisplayName;
			if (__instance.m_inventory.NrOfItems() == 0)
			{
				text += Localization.instance.Localize(" ( $piece_container_empty )");
			}
			NurseryFood.Species species = station.Species;
			if (species != null)
			{
				string text2 = Localization.instance.Localize(species.YoungName);
				if (text2.Length > 0)
				{
					text2 = char.ToUpper(text2[0]) + text2.Substring(1);
				}
				text += $"\n{text2}: {station.Occupied}/{station.Capacity}";
			}
			text += Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open $msg_stackall_hover");
			if (species != null)
			{
				text += Localization.instance.Localize((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "\n[<color=yellow><b>$KEY_AltKeys + $KEY_Use</b></color>] $leashme_nursery_show" : "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $leashme_nursery_show");
				if (!ZInput.IsGamepadActive())
				{
					text += Localization.instance.Localize("\n[<color=yellow><b>N</b></color>] $leashme_nursery_areas");
				}
			}
			__result = text;
		}

		[HarmonyPatch(typeof(Container), "Interact")]
		[HarmonyPrefix]
		private static bool InteractPrefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!alt || !TryGetStation(__instance, out var station))
			{
				return true;
			}
			__result = false;
			if (hold || (__instance.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false)))
			{
				return false;
			}
			if (!__instance.CheckAccess(Game.instance.GetPlayerProfile().GetPlayerID()))
			{
				((Character)character).Message((MessageType)2, "$msg_cantopen", 0, (Sprite)null, false);
				return false;
			}
			if (station.Species != null)
			{
				station.ShowConnections();
			}
			return false;
		}

		private static bool TryGetStation(Container container, out NurseryStation station)
		{
			station = null;
			if (container.m_name == "$leashme_nursery")
			{
				return ((Component)container).TryGetComponent<NurseryStation>(ref station);
			}
			return false;
		}

		private static bool IsNursery(Inventory inventory)
		{
			return inventory.m_name == "$leashme_nursery";
		}

		private static int Allowed(Inventory inventory, ItemData item)
		{
			if (inventory.m_inventory.Count == 0)
			{
				return NurseryFood.Find(item)?.Limit ?? 0;
			}
			ItemData val = inventory.m_inventory[0];
			NurseryFood.Species species = NurseryFood.Find(val);
			if (species == null || val.m_shared.m_name != item.m_shared.m_name)
			{
				return 0;
			}
			return species.Limit - val.m_stack;
		}
	}
	internal static class NurseryFood
	{
		internal sealed class Species
		{
			public readonly string AdultPrefab;

			public readonly string YoungName;

			public readonly string StationName;

			public readonly int Limit;

			public readonly float MoveRadius;

			public readonly float PickupRadius;

			public readonly string[] FoodPrefabs;

			private float m_breedFreeRadius = -1f;

			public float BreedFreeRadius
			{
				get
				{
					if (m_breedFreeRadius < 0f && Object.op_Implicit((Object)(object)ZNetScene.instance))
					{
						GameObject prefab = ZNetScene.instance.GetPrefab(AdultPrefab);
						Procreation val = default(Procreation);
						m_breedFreeRadius = ((Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Procreation>(ref val)) ? (val.m_totalCheckRange + MoveRadius) : 0f);
					}
					return Mathf.Max(0f, m_breedFreeRadius);
				}
			}

			public Species(string adultPrefab, string youngName, int limit, float moveRadius, float pickupRadius, params string[] foodPrefabs)
			{
				AdultPrefab = adultPrefab;
				YoungName = youngName;
				StationName = youngName.Replace("_young_", "_station_");
				Limit = limit;
				MoveRadius = moveRadius;
				PickupRadius = pickupRadius;
				FoodPrefabs = foodPrefabs;
			}
		}

		private static readonly Species[] All = new Species[6]
		{
			new Species("Boar", "$leashme_nursery_young_boar", 20, 5f, 30f, "Blueberries", "Carrot", "Onion", "Raspberry", "Mushroom", "Turnip"),
			new Species("Wolf", "$leashme_nursery_young_wolf", 20, 5f, 30f, "RawMeat", "DeerMeat", "LoxMeat", "NeckTail", "FishRaw", "ChickenMeat", "Sausages"),
			new Species("Lox", "$leashme_nursery_young_lox", 10, 10f, 45f, "Barley", "Cloudberry", "Flax"),
			new Species("Hen", "$leashme_nursery_young_hen", 20, 5f, 30f, "CarrotSeeds", "TurnipSeeds", "OnionSeeds", "BeechSeeds", "BirchSeeds", "Dandelion"),
			new Species("Asksvin", "$leashme_nursery_young_asksvin", 10, 10f, 35f, "MushroomSmokePuff", "Vineberry", "Fiddleheadfern"),
			new Species("Moose", "$leashme_nursery_young_moose", 10, 10f, 35f, "Lingonberry")
		};

		private static Dictionary<string, Species> s_byItemName;

		private static Dictionary<string, GameObject> s_prefabByItemName;

		public static Species FindYoung(GameObject prefab)
		{
			Growup val = default(Growup);
			if (!Object.op_Implicit((Object)(object)prefab) || !prefab.TryGetComponent<Growup>(ref val))
			{
				return null;
			}
			GameObject val2 = val.m_grownPrefab;
			if (val.m_altGrownPrefabs != null && val.m_altGrownPrefabs.Count > 0)
			{
				val2 = val.m_altGrownPrefabs[0].m_prefab;
				foreach (GrownEntry altGrownPrefab in val.m_altGrownPrefabs)
				{
					if ((Object)(object)altGrownPrefab.m_prefab != (Object)(object)val2)
					{
						return null;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val2) || Object.op_Implicit((Object)(object)val2.GetComponent<Growup>()))
			{
				return null;
			}
			string prefabName = Utils.GetPrefabName(val2);
			Species[] all = All;
			foreach (Species species in all)
			{
				if (species.AdultPrefab == prefabName)
				{
					return species;
				}
			}
			return null;
		}

		public static Species Find(ItemData item)
		{
			Resolve();
			if (!s_byItemName.TryGetValue(item.m_shared.m_name, out var value))
			{
				return null;
			}
			return value;
		}

		public static GameObject GetPrefab(ItemData item)
		{
			Resolve();
			if (!s_prefabByItemName.TryGetValue(item.m_shared.m_name, out var value))
			{
				return null;
			}
			return value;
		}

		private static void Resolve()
		{
			if (s_byItemName != null)
			{
				return;
			}
			s_byItemName = new Dictionary<string, Species>();
			s_prefabByItemName = new Dictionary<string, GameObject>();
			Species[] all = All;
			foreach (Species species in all)
			{
				string[] foodPrefabs = species.FoodPrefabs;
				foreach (string text in foodPrefabs)
				{
					GameObject prefab = PrefabManager.Instance.GetPrefab(text);
					ItemDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null);
					if (!Object.op_Implicit((Object)(object)val))
					{
						Logger.LogWarning((object)("Nursery food " + text + " not found; it is not accepted."));
						continue;
					}
					s_byItemName[val.m_itemData.m_shared.m_name] = species;
					s_prefabByItemName[val.m_itemData.m_shared.m_name] = prefab;
				}
			}
		}
	}
	internal class NurseryFoodVisual : MonoBehaviour
	{
		private Inventory m_inventory;

		private Transform m_anchor;

		private GameObject m_visual;

		private GameObject m_shownPrefab;

		private void Start()
		{
			Container component = ((Component)this).GetComponent<Container>();
			m_inventory = (Object.op_Implicit((Object)(object)component) ? component.GetInventory() : null);
			m_anchor = ((Component)this).transform.Find("FoodAnchor");
			if (m_inventory != null && Object.op_Implicit((Object)(object)m_anchor))
			{
				Inventory inventory = m_inventory;
				inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(Refresh));
				Refresh();
			}
		}

		private void OnDestroy()
		{
			if (m_inventory != null)
			{
				Inventory inventory = m_inventory;
				inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(Refresh));
			}
		}

		private void Refresh()
		{
			GameObject val = ((m_inventory.m_inventory.Count > 0) ? NurseryFood.GetPrefab(m_inventory.m_inventory[0]) : null);
			if (!((Object)(object)val == (Object)(object)m_shownPrefab))
			{
				if (Object.op_Implicit((Object)(object)m_visual))
				{
					Object.Destroy((Object)(object)m_visual);
				}
				m_shownPrefab = val;
				m_visual = (Object.op_Implicit((Object)(object)val) ? Build(val) : null);
			}
		}

		private GameObject Build(GameObject prefab)
		{
			//IL_0005: 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_001c: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0169: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_00b5: 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_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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("FoodVisual")
			{
				layer = ((Component)this).gameObject.layer
			};
			val.transform.SetParent(m_anchor, false);
			Transform transform = prefab.transform;
			Matrix4x4 val2 = Matrix4x4.Scale(transform.localScale) * transform.worldToLocalMatrix;
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val3 in componentsInChildren)
			{
				MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
				if (((Renderer)val3).enabled && Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh) && IsActive(((Component)val3).transform, transform))
				{
					Matrix4x4 val4 = val2 * ((Component)val3).transform.localToWorldMatrix;
					GameObject val5 = new GameObject(((Object)val3).name)
					{
						layer = val.layer
					};
					val5.transform.SetParent(val.transform, false);
					val5.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val4)).GetColumn(3));
					val5.transform.localRotation = ((Matrix4x4)(ref val4)).rotation;
					val5.transform.localScale = ((Matrix4x4)(ref val4)).lossyScale;
					val5.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
					MeshRenderer obj = val5.AddComponent<MeshRenderer>();
					((Renderer)obj).sharedMaterials = ((Renderer)val3).sharedMaterials;
					((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1;
				}
			}
			Bounds val6 = NurseryPiece.LocalBounds(m_anchor, val);
			val.transform.localPosition = new Vector3(0f - ((Bounds)(ref val6)).center.x, 0f - ((Bounds)(ref val6)).min.y, 0f - ((Bounds)(ref val6)).center.z);
			return val;
		}

		private static bool IsActive(Transform t, Transform root)
		{
			while (Object.op_Implicit((Object)(object)t) && (Object)(object)t != (Object)(object)root)
			{
				if (!((Component)t).gameObject.activeSelf)
				{
					return false;
				}
				t = t.parent;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class NurseryNumbers
	{
		public static readonly int NumberKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryNumber");

		private const string RequestRpc = "LeashMe_NurseryNumberRequest";

		private static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("LeashMe_Nursery");

		private static HashSet<int> s_used;

		private static Dictionary<ZDOID, int> s_assigned;

		[HarmonyPatch(typeof(ZNet), "Awake")]
		[HarmonyPostfix]
		private static void ZNetAwakePostfix()
		{
			s_used = null;
			s_assigned = null;
			ZRoutedRpc.instance.Register<ZDOID>("LeashMe_NurseryNumberRequest", (Action<long, ZDOID>)RPC_Request);
		}

		public static void Request(ZDOID station)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "LeashMe_NurseryNumberRequest", new object[1] { station });
		}

		private static void RPC_Request(long sender, ZDOID station)
		{
			//IL_001e: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer())
			{
				ZDO zDO = ZDOMan.instance.GetZDO(station);
				if (zDO != null && zDO.GetPrefab() == PrefabHash && zDO.GetInt(NumberKey, 0) == 0)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(zDO.GetOwner(), station, "LeashMe_NurseryNumber", new object[1] { Assign(station) });
				}
			}
		}

		private static int Assign(ZDOID station)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if (s_used == null)
			{
				s_used = new HashSet<int>();
				s_assigned = new Dictionary<ZDOID, int>();
				foreach (ZDO value2 in ZDOMan.instance.m_objectsByID.Values)
				{
					int num = ((value2.GetPrefab() == PrefabHash) ? value2.GetInt(NumberKey, 0) : 0);
					if (num > 0)
					{
						s_used.Add(num);
					}
				}
			}
			if (s_assigned.TryGetValue(station, out var value))
			{
				return value;
			}
			for (value = 1; s_used.Contains(value); value++)
			{
			}
			s_used.Add(value);
			s_assigned[station] = value;
			return value;
		}
	}
	internal static class NurseryPiece
	{
		public const string PrefabName = "LeashMe_Nursery";

		public const string ContainerName = "$leashme_nursery";

		public const string FoodAnchorName = "FoodAnchor";

		private const string BasePrefabName = "iron_wall_1x1";

		private const string FloorPrefabName = "wood_floor_1x1";

		private const string ChestPrefabName = "piece_chest_wood";

		private const string IconName = "buildmenu_icon_nursery_256";

		private const float IconTilt = 15f;

		private const float IconYaw = 20f;

		private const int GrateParts = 5;

		private static readonly string[] States = new string[3] { "New", "Worn", "Broken" };

		public static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable += AddPiece;
		}

		private static void AddPiece()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			PrefabManager.OnVanillaPrefabsAvailable -= AddPiece;
			GameObject prefab = PrefabManager.Instance.GetPrefab("wood_floor_1x1");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				Logger.LogError((object)"wood_floor_1x1 not found; nursery not added.");
				return;
			}
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_chest_wood");
			Container val = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponent<Container>() : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Logger.LogError((object)"piece_chest_wood not found; nursery not added.");
				return;
			}
			PieceConfig val2 = new PieceConfig();
			val2.Name = "$leashme_nursery";
			val2.Description = "$leashme_nursery_desc";
			val2.PieceTable = PieceTables.Hammer;
			val2.CraftingStation = "forge";
			val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("RoundLog", 1, 0, true),
				new RequirementConfig("Iron", 5, 0, true)
			};
			PieceConfig val3 = val2;
			Sprite val4 = EmbeddedSprite.Load("buildmenu_icon_nursery_256.png");
			if (Object.op_Implicit((Object)(object)val4))
			{
				val3.Icon = val4;
			}
			CustomPiece val5 = new CustomPiece("LeashMe_Nursery", "iron_wall_1x1", val3);
			if (!Object.op_Implicit((Object)(object)val5.PiecePrefab))
			{
				Logger.LogError((object)"iron_wall_1x1 not found; nursery not added.");
				return;
			}
			val5.Piece.m_category = (PieceCategory)0;
			val5.Piece.m_usage = (UsageTagFlags)1;
			if (!BuildCube(val5.PiecePrefab, prefab))
			{
				Logger.LogError((object)"iron_wall_1x1 or wood_floor_1x1 visuals not found; nursery not added.");
				return;
			}
			AddContainer(val5.PiecePrefab, val);
			val5.PiecePrefab.AddComponent<NurseryFoodVisual>();
			val5.PiecePrefab.AddComponent<NurseryStation>();
			PieceManager.Instance.AddPiece(val5);
		}

		private static void AddContainer(GameObject prefab, Container chest)
		{
			//IL_0045: 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)
			Container obj = prefab.AddComponent<Container>();
			obj.m_name = "$leashme_nursery";
			obj.m_bkg = chest.m_bkg;
			obj.m_width = 1;
			obj.m_height = 1;
			obj.m_openEffects = chest.m_openEffects;
			obj.m_closeEffects = chest.m_closeEffects;
			obj.m_privacy = chest.m_privacy;
			obj.m_checkGuardStone = chest.m_checkGuardStone;
			obj.m_autoDestroyEmpty = false;
		}

		private static bool BuildCube(GameObject prefab, GameObject floor)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: 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)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			Transform root = prefab.transform;
			WearNTear component = prefab.GetComponent<WearNTear>();
			BoxCollider component2 = prefab.GetComponent<BoxCollider>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || States.Any((string s) => !Object.op_Implicit((Object)(object)root.Find(s)) || !Object.op_Implicit((Object)(object)floor.transform.Find(s))))
			{
				return false;
			}
			int layer = prefab.layer;
			GameObject[] array = (GameObject[])(object)new GameObject[States.Length];
			float num = -0.5f;
			for (int num2 = 0; num2 < States.Length; num2++)
			{
				GameObject gameObject = ((Component)root.Find(States[num2])).gameObject;
				GameObject gameObject2 = ((Component)floor.transform.Find(States[num2])).gameObject;
				GameObject val = new GameObject(States[num2])
				{
					layer = layer
				};
				val.transform.SetParent(root, false);
				AddPart(root, val.transform, gameObject, Quaternion.identity, Vector3.forward);
				AddPart(root, val.transform, gameObject, Quaternion.Euler(0f, 180f, 0f), Vector3.back);
				AddPart(root, val.transform, gameObject, Quaternion.Euler(0f, 90f, 0f), Vector3.right);
				AddPart(root, val.transform, gameObject, Quaternion.Euler(0f, -90f, 0f), Vector3.left);
				AddPart(root, val.transform, gameObject, Quaternion.Euler(90f, 0f, 0f), Vector3.up);
				GameObject part = AddPart(root, val.transform, gameObject2, Quaternion.identity, Vector3.down);
				if (num2 == 0)
				{
					Bounds val2 = LocalBounds(root, part);
					num = ((Bounds)(ref val2)).max.y;
				}
				val.SetActive(gameObject.activeSelf);
				array[num2] = val;
			}
			foreach (string item in States.Concat(new string[1] { "Destruction" }))
			{
				Transform val3 = root.Find(item);
				if (Object.op_Implicit((Object)(object)val3))
				{
					Object.DestroyImmediate((Object)(object)((Component)val3).gameObject);
				}
			}
			component.m_health *= 5f;
			component.m_new = array[0];
			component.m_worn = array[1];
			component.m_broken = array[2];
			component.m_fragmentRoots = null;
			component2.center = Vector3.zero;
			component2.size = Vector3.one;
			ReplaceSnapPoints(prefab);
			GameObject val4 = new GameObject("FoodAnchor")
			{
				layer = layer
			};
			val4.transform.SetParent(root, false);
			val4.transform.localPosition = new Vector3(0f, num, 0f);
			return true;
		}

		private static GameObject AddPart(Transform root, Transform cube, GameObject source, Quaternion rotation, Vector3 face)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(source, cube, false);
			((Object)val).name = ((Object)source).name;
			val.SetActive(true);
			LODGroup[] componentsInChildren = val.GetComponentsInChildren<LODGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			foreach (Transform item in (from t in val.GetComponentsInChildren<Transform>(true)
				where ((Object)t).name == "lod"
				select t).ToList())
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
			Transform[] componentsInChildren2 = val.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Component)componentsInChildren2[i]).gameObject.layer = ((Component)cube).gameObject.layer;
			}
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = rotation;
			Bounds val2 = LocalBounds(root, val);
			float num = Vector3.Dot(((Bounds)(ref val2)).extents, new Vector3(Mathf.Abs(face.x), Mathf.Abs(face.y), Mathf.Abs(face.z)));
			val.transform.localPosition = -((Bounds)(ref val2)).center + face * (0.5f - num);
			return val;
		}

		public static Bounds LocalBounds(Transform root, GameObject part)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_00a2: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			Bounds result = default(Bounds);
			bool flag = true;
			MeshFilter[] componentsInChildren = part.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val.sharedMesh))
				{
					continue;
				}
				Matrix4x4 val2 = root.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
				Bounds bounds = val.sharedMesh.bounds;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f));
					Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3);
					if (flag)
					{
						((Bounds)(ref result))..ctor(val4, Vector3.zero);
						flag = false;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val4);
					}
				}
			}
			return result;
		}

		private static void ReplaceSnapPoints(GameObject prefab)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform item in (from t in prefab.GetComponentsInChildren<Transform>(true)
				where ((Component)t).CompareTag("snappoint")
				select t).ToList())
			{
				Object.DestroyImmediate((Object)(object)((Component)item).gameObject);
			}
			for (int num = 0; num < 8; num++)
			{
				bool flag = (num & 4) != 0;
				GameObject val = new GameObject(string.Format("$hud_snappoint_{0} {1}", flag ? "top" : "bottom", (num & 3) + 1))
				{
					layer = prefab.layer,
					tag = "snappoint"
				};
				val.transform.SetParent(prefab.transform, false);
				val.transform.localPosition = new Vector3(((num & 1) == 0) ? 0.5f : (-0.5f), flag ? 0.5f : (-0.5f), ((num & 2) == 0) ? 0.5f : (-0.5f));
				val.SetActive(false);
			}
		}
	}
	[BepInPlugin("de.evabs.valheim.leashme.nursery", "LeashMe Nursery", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class NurseryPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "de.evabs.valheim.leashme.nursery";

		public const string PluginName = "LeashMe Nursery";

		public const string PluginVersion = "0.1.0";

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		private void Awake()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			AddTranslations();
			NurseryPiece.Register();
			new Harmony("de.evabs.valheim.leashme.nursery").PatchAll(typeof(NurseryContainerPatches).Assembly);
		}

		private static void AddTranslations()
		{
			CustomLocalization localization = Localization;
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "leashme_nursery", "Nursery Beacon" },
				{ "leashme_nursery_desc", "Fill with adult animal food to attract youngs of that species." },
				{ "leashme_nursery_now", "Nursery now attracts $1" },
				{ "leashme_nursery_none", "Nursery no longer attracts animals" },
				{ "leashme_nursery_show", "Show animals" },
				{ "leashme_nursery_areas", "Show areas (15 s)" },
				{ "leashme_nursery_lost", "$1 $2 are no longer attracted to this nursery" },
				{ "leashme_nursery_young_boar", "piglets" },
				{ "leashme_nursery_young_wolf", "wolf cubs" },
				{ "leashme_nursery_young_lox", "lox calves" },
				{ "leashme_nursery_young_hen", "chicks" },
				{ "leashme_nursery_young_asksvin", "asksvin hatchlings" },
				{ "leashme_nursery_young_moose", "moose calves" },
				{ "leashme_nursery_station_boar", "Boar Nursery" },
				{ "leashme_nursery_station_wolf", "Wolf Nursery" },
				{ "leashme_nursery_station_lox", "Lox Nursery" },
				{ "leashme_nursery_station_hen", "Chicken Nursery" },
				{ "leashme_nursery_station_asksvin", "Asksvin Nursery" },
				{ "leashme_nursery_station_moose", "Moose Nursery" }
			});
			CustomLocalization localization2 = Localization;
			text = "German";
			localization2.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "leashme_nursery", "Jungtier-Sammelplatz" },
				{ "leashme_nursery_desc", "Mit Futter für erwachsene Tiere füllen, um Jungtiere dieser Art anzulocken." },
				{ "leashme_nursery_now", "Der Sammelplatz lockt jetzt $1 an" },
				{ "leashme_nursery_none", "Der Sammelplatz lockt keine Tiere mehr an" },
				{ "leashme_nursery_show", "Tiere zeigen" },
				{ "leashme_nursery_areas", "Bereiche zeigen (15 s)" },
				{ "leashme_nursery_lost", "$1 $2 werden nicht mehr von diesem Sammelplatz angelockt" },
				{ "leashme_nursery_young_boar", "Ferkel" },
				{ "leashme_nursery_young_wolf", "Wolfsjunge" },
				{ "leashme_nursery_young_lox", "Loxkälber" },
				{ "leashme_nursery_young_hen", "Küken" },
				{ "leashme_nursery_young_asksvin", "Asksvin-Jungtiere" },
				{ "leashme_nursery_young_moose", "Elchkälber" },
				{ "leashme_nursery_station_boar", "Wildschwein-Sammelplatz" },
				{ "leashme_nursery_station_wolf", "Wolf-Sammelplatz" },
				{ "leashme_nursery_station_lox", "Lox-Sammelplatz" },
				{ "leashme_nursery_station_hen", "Hühner-Sammelplatz" },
				{ "leashme_nursery_station_asksvin", "Asksvin-Sammelplatz" },
				{ "leashme_nursery_station_moose", "Elch-Sammelplatz" }
			});
		}
	}
	internal class NurseryStation : MonoBehaviour
	{
		internal struct Lease
		{
			public ZDOID Animal;

			public long RequestId;

			public double Expiry;

			public int Grant;
		}

		public const string RequestRpc = "LeashMe_NurseryRequest";

		public const string RenewRpc = "LeashMe_NurseryRenew";

		public const string NumberRpc = "LeashMe_NurseryNumber";

		private const float NumberRetrySeconds = 10f;

		public const float LeaseSeconds = 30f;

		private const float RenewWriteSeconds = 5f;

		private const float PriorityWindowSeconds = 60f;

		private const float MaxTargetDrop = 6f;

		private static readonly int LeasesKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryLeases");

		private static readonly int GenerationKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryGen");

		public static readonly int MemberKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryMember");

		public static readonly int MemberGenerationKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryMemberGen");

		private static int s_groundMask;

		public static readonly List<NurseryStation> All = new List<NurseryStation>();

		private ZNetView m_nview;

		private Container m_container;

		private Transform m_anchor;

		private uint m_cacheRevision = uint.MaxValue;

		private double m_cacheValidUntil;

		private readonly List<Lease> m_leases = new List<Lease>();

		private int m_generation;

		private bool m_inUse;

		private NurseryFood.Species m_species;

		private int m_capacity;

		private readonly Dictionary<ZDOID, long> m_renewals = new Dictionary<ZDOID, long>();

		private float m_renewWriteTimer;

		private float m_numberTimer;

		private bool m_windowChecked;

		private float m_windowStart = -1f;

		private int m_reserved;

		private int m_windowGeneration;

		private readonly HashSet<ZDOID> m_freeShare = new HashSet<ZDOID>();

		private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[16];

		private const string AreaSourcePrefab = "piece_workbench";

		public const float AreaHoverSeconds = 0.5f;

		public const float AreaKeySeconds = 15f;

		private CircleProjector m_pickupArea;

		private CircleProjector m_breedArea;

		private CircleProjector m_moveArea;

		private float m_areasUntil;

		private static bool s_areaSourceMissing;

		private const float ConnectionsSeconds = 10f;

		private const float ConnectionHoverSeconds = 0.5f;

		private static GameObject s_beamPrefab;

		private static bool s_beamSearched;

		private static readonly Dictionary<ZDOID, Character> s_wanted = new Dictionary<ZDOID, Character>();

		private static readonly List<ZDOID> s_removed = new List<ZDOID>();

		private float m_connectionsUntil;

		private readonly Dictionary<ZDOID, float> m_hoverUntil = new Dictionary<ZDOID, float>();

		private readonly Dictionary<ZDOID, GameObject> m_beams = new Dictionary<ZDOID, GameObject>();

		public int Number
		{
			get
			{
				if (!IsValid)
				{
					return 0;
				}
				return m_nview.GetZDO().GetInt(NurseryNumbers.NumberKey, 0);
			}
		}

		public string DisplayName
		{
			get
			{
				NurseryFood.Species species = Species;
				return Localization.instance.Localize((species != null) ? species.StationName : "$leashme_nursery");
			}
		}

		public bool IsValid
		{
			get
			{
				if (Object.op_Implicit((Object)(object)m_nview))
				{
					return m_nview.IsValid();
				}
				return false;
			}
		}

		public ZNetView NetView => m_nview;

		public NurseryFood.Species Species
		{
			get
			{
				Refresh();
				return m_species;
			}
		}

		public bool InUse
		{
			get
			{
				Refresh();
				return m_inUse;
			}
		}

		public int Generation
		{
			get
			{
				Refresh();
				return m_generation;
			}
		}

		public int Occupied
		{
			get
			{
				Refresh();
				return m_leases.Count;
			}
		}

		public int Capacity
		{
			get
			{
				Refresh();
				return m_capacity;
			}
		}

		public bool HasFreePlace => Capacity > Occupied;

		private Vector3 Floor
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)m_anchor))
				{
					return ((Component)this).transform.position;
				}
				return m_anchor.position;
			}
		}

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.GetZDO() != null)
			{
				m_container = ((Component)this).GetComponent<Container>();
				m_anchor = ((Component)this).transform.Find("FoodAnchor");
				m_nview.Register<ZDOID, long, int>("LeashMe_NurseryRequest", (Action<long, ZDOID, long, int>)RPC_Request);
				m_nview.Register<ZDOID, long, int>("LeashMe_NurseryRenew", (Action<long, ZDOID, long, int>)RPC_Renew);
				m_nview.Register<int>("LeashMe_NurseryNumber", (Action<long, int>)RPC_SetNumber);
				All.Add(this);
			}
		}

		public static NurseryStation Of(ZDOID animal)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			foreach (NurseryStation item in All)
			{
				if (item.IsValid && item.LeaseOf(animal) != 0L)
				{
					return item;
				}
			}
			return null;
		}

		private void UpdateNumber()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (m_nview.IsValid() && m_nview.IsOwner() && Number == 0)
			{
				m_numberTimer -= Time.deltaTime;
				if (!(m_numberTimer > 0f))
				{
					m_numberTimer = 10f;
					NurseryNumbers.Request(m_nview.GetZDO().m_uid);
				}
			}
		}

		private void RPC_SetNumber(long sender, int number)
		{
			if (m_nview.IsValid() && m_nview.IsOwner() && Number == 0 && number > 0)
			{
				m_nview.GetZDO().Set(NurseryNumbers.NumberKey, number, false);
			}
		}

		private void Start()
		{
			Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInventory() : null);
			if (val != null)
			{
				val.m_onChanged = (Action)Delegate.Combine(val.m_onChanged, new Action(OnInventoryChanged));
			}
		}

		private void OnDestroy()
		{
			if (All.Remove(this) && All.Count == 0)
			{
				NurseryAnimals.ReleaseAll();
			}
			Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInventory() : null);
			if (val != null)
			{
				val.m_onChanged = (Action)Delegate.Remove(val.m_onChanged, new Action(OnInventoryChanged));
			}
			foreach (GameObject value in m_beams.Values)
			{
				Object.Destroy((Object)(object)value);
			}
		}

		private void UpdateGeneration()
		{
			if (m_nview.IsValid() && m_nview.IsOwner() && m_nview.GetZDO().GetInt(GenerationKey, 0) == 0)
			{
				m_nview.GetZDO().Set(GenerationKey, NewGeneration(0), false);
			}
		}

		private static int NewGeneration(int current)
		{
			int num;
			do
			{
				num = Random.Range(1, int.MaxValue);
			}
			while (num == current);
			return num;
		}

		private void Update()
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			UpdateNumber();
			UpdateGeneration();
			ClearStaleInUse();
			if (m_beams.Count > 0 || m_connectionsUntil > 0f || m_hoverUntil.Count > 0)
			{
				UpdateBeams();
			}
			if (!m_windowChecked && SessionId() != 0L)
			{
				m_windowChecked = true;
				m_reserved = ((Number > 0 && m_nview.IsValid()) ? StoredCount() : 0);
				if (m_reserved > 0)
				{
					m_windowStart = Time.time;
					m_windowGeneration = m_nview.GetZDO().GetInt(GenerationKey, 0);
				}
			}
			if (m_renewals.Count == 0)
			{
				return;
			}
			if (!m_nview.IsValid() || !m_nview.IsOwner())
			{
				m_renewals.Clear();
				return;
			}
			m_renewWriteTimer -= Time.deltaTime;
			if (m_renewWriteTimer > 0f)
			{
				return;
			}
			List<Lease> list = ReadValid();
			double expiry = Now() + 30.0;
			for (int i = 0; i < list.Count; i++)
			{
				Lease value = list[i];
				if (m_renewals.TryGetValue(value.Animal, out var value2) && value2 == value.RequestId)
				{
					value.Expiry = expiry;
					list[i] = value;
				}
			}
			m_renewals.Clear();
			Write(list, ReadNextGrant());
		}

		public long LeaseOf(ZDOID animal)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Refresh();
			foreach (Lease lease in m_leases)
			{
				if (lease.Animal == animal)
				{
					return lease.RequestId;
				}
			}
			return 0L;
		}

		public bool TryGetTargetPoint(out Vector3 point)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			int num = Physics.RaycastNonAlloc(Floor + Vector3.up * 0.05f, Vector3.down, s_hits, 6.05f, GroundMask(), (QueryTriggerInteraction)1);
			float num2 = float.MaxValue;
			point = Vector3.zero;
			for (int i = 0; i < num; i++)
			{
				if (((RaycastHit)(ref s_hits[i])).distance < num2 && !((Component)((RaycastHit)(ref s_hits[i])).collider).transform.IsChildOf(((Component)this).transform))
				{
					num2 = ((RaycastHit)(ref s_hits[i])).distance;
					point = ((RaycastHit)(ref s_hits[i])).point;
				}
			}
			return num2 < float.MaxValue;
		}

		public bool TryGetGround(Vector3 position, float centerHeight, out float height)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			float y = Floor.y;
			int num = Physics.RaycastNonAlloc(new Vector3(position.x, y + 6f, position.z), Vector3.down, s_hits, 12f, GroundMask(), (QueryTriggerInteraction)1);
			float num2 = float.MaxValue;
			height = 0f;
			for (int i = 0; i < num; i++)
			{
				float num3 = Mathf.Abs(((RaycastHit)(ref s_hits[i])).point.y - centerHeight);
				if (num3 < num2 && !((Component)((RaycastHit)(ref s_hits[i])).collider).transform.IsChildOf(((Component)this).transform))
				{
					num2 = num3;
					height = ((RaycastHit)(ref s_hits[i])).point.y;
				}
			}
			return num2 < float.MaxValue;
		}

		public bool InTargetHeight(float y)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Abs(y - Floor.y) <= 6f;
		}

		private static int GroundMask()
		{
			if (s_groundMask == 0)
			{
				s_groundMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "terrain", "piece", "vehicle" });
			}
			return s_groundMask;
		}

		public void ShowAreas(float seconds)
		{
			if (Species == null)
			{
				HideAreas();
				return;
			}
			m_areasUntil = Mathf.Max(m_areasUntil, Time.time + seconds);
			UpdateAreas();
		}

		private void UpdateAreas()
		{
			NurseryFood.Species species = Species;
			if (species == null || !CreateAreas())
			{
				HideAreas();
				return;
			}
			SetArea(m_pickupArea, species.PickupRadius);
			float breedFreeRadius = species.BreedFreeRadius;
			if (breedFreeRadius > 0f)
			{
				SetArea(m_breedArea, breedFreeRadius);
			}
			else
			{
				((Component)m_breedArea).gameObject.SetActive(false);
			}
			SetArea(m_moveArea, species.MoveRadius);
			((MonoBehaviour)this).CancelInvoke("HideAreas");
			((MonoBehaviour)this).Invoke("HideAreas", m_areasUntil - Time.time);
		}

		private void HideAreas()
		{
			m_areasUntil = 0f;
			((MonoBehaviour)this).CancelInvoke("HideAreas");
			if (Object.op_Implicit((Object)(object)m_pickupArea))
			{
				((Component)m_pickupArea).gameObject.SetActive(false);
				((Component)m_breedArea).gameObject.SetActive(false);
				((Component)m_moveArea).gameObject.SetActive(false);
			}
		}

		private bool CreateAreas()
		{
			if (Object.op_Implicit((Object)(object)m_pickupArea))
			{
				return true;
			}
			GameObject val = ((!s_areaSourceMissing && Object.op_Implicit((Object)(object)ZNetScene.instance)) ? ZNetScene.instance.GetPrefab("piece_workbench") : null);
			CraftingStation val3 = default(CraftingStation);
			CircleProjector val2 = ((Object.op_Implicit((Object)(object)val) && val.TryGetComponent<CraftingStation>(ref val3) && Object.op_Implicit((Object)(object)val3.m_areaMarker)) ? val3.m_areaMarker.GetComponent<CircleProjector>() : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				if (!s_areaSourceMissing)
				{
					s_areaSourceMissing = true;
					Logger.LogWarning((object)"Nursery area circle: no area marker at piece_workbench; areas are not shown.");
				}
				return false;
			}
			m_pickupArea = CreateArea(val2);
			m_breedArea = CreateArea(val2);
			m_moveArea = CreateArea(val2);
			return true;
		}

		private CircleProjector CreateArea(CircleProjector source)
		{
			//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)
			CircleProjector component = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Component)this).transform.position, Quaternion.identity, ((Component)this).transform).GetComponent<CircleProjector>();
			((Component)component).gameObject.SetActive(false);
			ParticleSystem[] componentsInChildren = ((Component)component).GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).gameObject != (Object)(object)((Component)component).gameObject)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			return component;
		}

		private static void SetArea(CircleProjector area, float radius)
		{
			if (area.m_radius != radius)
			{
				float num = area.m_radius / (float)area.m_nrOfSegments;
				area.m_radius = radius;
				area.m_nrOfSegments = Mathf.Max(8, Mathf.RoundToInt(radius / num));
			}
			((Component)area).gameObject.SetActive(true);
		}

		public void ShowConnections()
		{
			if (BeamPrefab())
			{
				m_connectionsUntil = Time.time + 10f;
			}
		}

		public void ShowConnection(ZDOID animal)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (BeamPrefab())
			{
				m_hoverUntil[animal] = Time.time + 0.5f;
			}
		}

		private static bool BeamPrefab()
		{
			if (!s_beamSearched && Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				s_beamSearched = true;
				StationExtension val = default(StationExtension);
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<StationExtension>(ref val) && Object.op_Implicit((Object)(object)val.m_connectionPrefab))
					{
						s_beamPrefab = val.m_connectionPrefab;
						break;
					}
				}
				if (!Object.op_Implicit((Object)(object)s_beamPrefab))
				{
					Logger.LogWarning((object)"Nursery connection beam: no station extension with a connection prefab; beams are not shown.");
				}
			}
			return Object.op_Implicit((Object)(object)s_beamPrefab);
		}

		private void UpdateBeams()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: 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_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: 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_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			bool flag = time < m_connectionsUntil;
			if (!flag)
			{
				m_connectionsUntil = 0f;
			}
			s_removed.Clear();
			foreach (KeyValuePair<ZDOID, float> item in m_hoverUntil)
			{
				if (item.Value <= time)
				{
					s_removed.Add(item.Key);
				}
			}
			foreach (ZDOID item2 in s_removed)
			{
				m_hoverUntil.Remove(item2);
			}
			Refresh();
			s_wanted.Clear();
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				Character value = default(Character);
				foreach (Lease lease in m_leases)
				{
					GameObject val = ((flag || m_hoverUntil.ContainsKey(lease.Animal)) ? ZNetScene.instance.FindInstance(lease.Animal) : null);
					if (Object.op_Implicit((Object)(object)val) && val.TryGetComponent<Character>(ref value))
					{
						s_wanted[lease.Animal] = value;
					}
				}
			}
			s_removed.Clear();
			foreach (KeyValuePair<ZDOID, GameObject> beam in m_beams)
			{
				if (!s_wanted.ContainsKey(beam.Key))
				{
					s_removed.Add(beam.Key);
				}
			}
			foreach (ZDOID item3 in s_removed)
			{
				Object.Destroy((Object)(object)m_beams[item3]);
				m_beams.Remove(item3);
			}
			Vector3 position = ((Component)this).transform.position;
			foreach (KeyValuePair<ZDOID, Character> item4 in s_wanted)
			{
				if (!m_beams.TryGetValue(item4.Key, out var value2))
				{
					value2 = Object.Instantiate<GameObject>(s_beamPrefab, position, Quaternion.identity);
					m_beams[item4.Key] = value2;
				}
				Vector3 val2 = item4.Value.GetCenterPoint() - position;
				value2.transform.SetPositionAndRotation(position, (((Vector3)(ref val2)).sqrMagnitude > 0f) ? Quaternion.LookRotation(val2) : Quaternion.identity);
				value2.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val2)).magnitude);
			}
		}

		private void RPC_Request(long sender, ZDOID animal, long requestId, int generation)
		{
			//IL_0002: 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)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!CheckRequest(sender, animal, generation, out var zdo) || m_container.IsInUse())
			{
				return;
			}
			List<Lease> list = ReadValid();
			int num = ReadNextGrant();
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].Animal == animal)
				{
					Lease value = list[i];
					value.RequestId = requestId;
					list[i] = value;
					Write(list, num);
					return;
				}
			}
			int num2 = CurrentCapacity();
			bool flag = InPriorityWindow() && (m_freeShare.Contains(animal) || !Remembers(zdo));
			if (list.Count < num2 && (!flag || FreeShareHeld(list) < num2 - m_reserved))
			{
				if (flag)
				{
					m_freeShare.Add(animal);
				}
				list.Add(new Lease
				{
					Animal = animal,
					RequestId = requestId,
					Expiry = Now() + 30.0,
					Grant = num
				});
				Write(list, num + 1);
			}
		}

		private void RPC_Renew(long sender, ZDOID animal, long requestId, int generation)
		{
			//IL_0002: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (!CheckRequest(sender, animal, generation, out var _))
			{
				return;
			}
			foreach (Lease item in ReadValid())
			{
				if (item.Animal == animal && item.RequestId == requestId)
				{
					if (m_renewals.Count == 0)
					{
						m_renewWriteTimer = 5f;
					}
					m_renewals[animal] = requestId;
					break;
				}
			}
		}

		private bool CheckRequest(long sender, ZDOID animal, int generation, out ZDO zdo)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			zdo = null;
			if (!m_nview.IsOwner() || SessionId() == 0L || generation != m_nview.GetZDO().GetInt(GenerationKey, 0))
			{
				return false;
			}
			zdo = ZDOMan.instance.GetZDO(animal);
			if (zdo == null || zdo.GetOwner() != sender || !zdo.GetBool(ZDOVars.s_tamed, false))
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab());
			NurseryFood.Species species = StoredSpecies();
			if (species != null)
			{
				return NurseryFood.FindYoung(prefab) == species;
			}
			return false;
		}

		private bool InPriorityWindow()
		{
			if (m_windowStart >= 0f && Time.time - m_windowStart < 60f)
			{
				return m_nview.GetZDO().GetInt(GenerationKey, 0) == m_windowGeneration;
			}
			return false;
		}

		private int FreeShareHeld(List<Lease> leases)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (Lease lease in leases)
			{
				if (m_freeShare.Contains(lease.Animal))
				{
					num++;
				}
			}
			return num;
		}

		private int StoredCount()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			byte[] byteArray = m_nview.GetZDO().GetByteArray(LeasesKey, (byte[])null);
			if (byteArray == null)
			{
				return 0;
			}
			ZPackage val = new ZPackage(byteArray);
			val.ReadLong();
			if (val.ReadInt() != m_nview.GetZDO().GetInt(GenerationKey, 0))
			{
				return 0;
			}
			val.ReadInt();
			return val.ReadInt();
		}

		private bool Remembers(ZDO animal)
		{
			if (animal.GetInt(MemberKey, 0) == Number)
			{
				return animal.GetInt(MemberGenerationKey, 0) == m_nview.GetZDO().GetInt(GenerationKey, 0);
			}
			return false;
		}

		private void OnInventoryChanged()
		{
			m_cacheRevision = uint.MaxValue;
			if (m_areasUntil > Time.time)
			{
				UpdateAreas();
			}
			if (!m_nview.IsValid() || !m_nview.IsOwner() || SessionId() == 0L)
			{
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			if (m_container.GetInventory().m_inventory.Count == 0)
			{
				if (zDO.GetByteArray(LeasesKey, (byte[])null) != null)
				{
					zDO.RemoveByteArray(LeasesKey);
					zDO.Set(GenerationKey, NewGeneration(zDO.GetInt(GenerationKey, 0)), false);
					m_renewals.Clear();
				}
				return;
			}
			List<Lease> list = ReadValid();
			int num = CurrentCapacity();
			if (list.Count > num)
			{
				int count = list.Count - num;
				list.Sort((Lease a, Lease b) => a.Grant.CompareTo(b.Grant));
				list.RemoveRange(num, count);
				Write(list, ReadNextGrant());
				NurseryFood.Species species = StoredSpecies();
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && species != null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$leashme_nursery_lost", new string[2]
					{
						count.ToString(),
						Localization.instance.Localize(species.YoungName)
					}), 0, (Sprite)null, false);
				}
			}
		}

		private bool IsChestOpen()
		{
			return m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1;
		}

		private void ClearStaleInUse()
		{
			if (m_nview.IsValid() && m_nview.IsOwner() && !m_container.IsInUse() && IsChestOpen())
			{
				m_nview.GetZDO().Set(ZDOVars.s_inUse, 0, false);
			}
		}

		private NurseryFood.Species StoredSpecies()
		{
			Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInventory() : null);
			if (val == null || val.m_inventory.Count <= 0)
			{
				return null;
			}
			return NurseryFood.Find(val.m_inventory[0]);
		}

		private int CurrentCapacity()
		{
			Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInvento