Decompiled source of Offspring Portal v1.2.0

OffspringPortal.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using OffspringPortal.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("OffspringPortal")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Automatically teleports juvenile animals from breeding pens to configured grow-up pens.")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+12e3506d23ba3e111aeeb745594ae197341def4b")]
[assembly: AssemblyProduct("OffspringPortal")]
[assembly: AssemblyTitle("OffspringPortal")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OffspringPortal
{
	public static class AdultPortalRouter
	{
		public static bool IsAdultRoutingMaturingPortal(OPTeleportWorld portal)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)portal == (Object)null)
			{
				return false;
			}
			ZNetView component = ((Component)portal).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val == null)
			{
				return false;
			}
			PortalRecord portalRecord = DestinationRegistry.Get(val.m_uid);
			if (portalRecord != null)
			{
				if (portalRecord.Role == PortalRole.Maturing)
				{
					return portalRecord.AdultDestination != AdultDestination.None;
				}
				return false;
			}
			if (PortalRoleCatalog.FromZdo(val) == PortalRole.Maturing)
			{
				return PortalRoleCatalog.GetAdultDestination(val) != AdultDestination.None;
			}
			return false;
		}

		public static bool TryRoute(OPTeleportWorld portal, Character character, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: 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_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)portal == (Object)null || (Object)(object)character == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				return false;
			}
			if (!SpeciesHelper.IsEligibleAdult(character))
			{
				return false;
			}
			ZNetView component = ((Component)portal).GetComponent<ZNetView>();
			PortalRecord portalRecord = (((Object)(object)component != (Object)null) ? DestinationRegistry.Get(component.GetZDO()?.m_uid ?? ZDOID.None) : null);
			if (portalRecord == null || portalRecord.Role != PortalRole.Maturing || portalRecord.AdultDestination == AdultDestination.None)
			{
				return false;
			}
			int instanceID = ((Object)character).GetInstanceID();
			float time = Time.time;
			if (cooldowns.TryGetValue(instanceID, out var value) && time < value)
			{
				return false;
			}
			string adultSpeciesKey = SpeciesHelper.GetAdultSpeciesKey(character);
			if (!SpeciesHelper.SpeciesKeyMatches(adultSpeciesKey, portalRecord.DeclaredSpeciesKey))
			{
				return false;
			}
			ZNetView nview = character.GetNview();
			ZDOID val = (ZDOID)(((??)((nview == null) ? ((ZDOID?)null) : nview.GetZDO()?.m_uid)) ?? ZDOID.None);
			ZDOID val2 = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None);
			if (val == ZDOID.None || val2 == ZDOID.None)
			{
				return false;
			}
			if (ZNet.instance.IsServer())
			{
				return TryRouteOnServer(portal, character, adultSpeciesKey, portalRecord, val, val2, cooldowns, ref lastNoDestinationMessageTime, time, instanceID);
			}
			if (!RoutingRpc.CanSendRequests())
			{
				return false;
			}
			RoutingRpc.RequestAdultRoute(val, val2, adultSpeciesKey);
			cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value;
			return false;
		}

		public static bool ExecuteApprovedRoute(ZDOID characterId, ZDOID sourcePortalId, PortalRecord destination, Character character = null, OPTeleportWorld sourcePortal = null)
		{
			//IL_0003: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			if (character == null)
			{
				character = ResolveCharacter(characterId);
			}
			if (sourcePortal == null)
			{
				sourcePortal = ResolvePortal(sourcePortalId);
			}
			if ((Object)(object)character == (Object)null || (Object)(object)sourcePortal == (Object)null || destination == null)
			{
				return false;
			}
			PortalRecord portalRecord = DestinationRegistry.Get(sourcePortalId);
			if (portalRecord == null || portalRecord.Role != PortalRole.Maturing)
			{
				return false;
			}
			string adultSpeciesKey = SpeciesHelper.GetAdultSpeciesKey(character);
			if (!SpeciesHelper.SpeciesKeyMatches(adultSpeciesKey, portalRecord.DeclaredSpeciesKey))
			{
				return false;
			}
			if (!JuvenileTeleporter.TryExecuteApproved(character, destination, sourcePortal))
			{
				return false;
			}
			OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesKey.GetDisplayName(adultSpeciesKey)} adult to {portalRecord.AdultDestination} portal at {destination.Position}.");
			PlayPortalActivation(sourcePortal);
			return true;
		}

		private static bool TryRouteOnServer(OPTeleportWorld portal, Character character, string speciesKey, PortalRecord source, ZDOID characterId, ZDOID sourcePortalId, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime, float now, int bodyId)
		{
			//IL_0048: 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)
			PortalRecord destination;
			switch (source.AdultDestination)
			{
			case AdultDestination.Farm:
				if (!DestinationRegistry.TryResolveFarmDestination(speciesKey, out destination))
				{
					string message = "No Farm portal exists.";
					return WarnMissingDestination(now, ref lastNoDestinationMessageTime, message);
				}
				break;
			case AdultDestination.Cull:
				if (!DestinationRegistry.TryResolveCullDestination(out destination))
				{
					string message = "No Cull portal exists.";
					return WarnMissingDestination(now, ref lastNoDestinationMessageTime, message);
				}
				break;
			default:
				return false;
			}
			if (ExecuteApprovedRoute(characterId, sourcePortalId, destination, character, portal))
			{
				cooldowns[bodyId] = now + ModConfig.TeleportCooldownSec.Value;
				return true;
			}
			OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesKey.GetDisplayName(speciesKey) + " adult."));
			return false;
		}

		private static bool WarnMissingDestination(float now, ref float lastMessageTime, string message)
		{
			if (now - lastMessageTime <= 5f)
			{
				return false;
			}
			lastMessageTime = now;
			OffspringPortalPlugin.Log.LogWarning((object)message);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false);
			}
			return false;
		}

		private static Character ResolveCharacter(ZDOID characterId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(characterId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<Character>();
		}

		private static OPTeleportWorld ResolvePortal(ZDOID portalId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(portalId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<OPTeleportWorld>();
		}

		private static void PlayPortalActivation(OPTeleportWorld portal)
		{
			portal?.PlayActivationEffect();
		}
	}
	public sealed class BreedableSpeciesInfo
	{
		public string Key;

		public string DisplayName;

		public bool IsEggLayer;

		public bool IsDualPurposeEgg;

		public string EggCollectorKey;

		public string EggPrefabName;

		public string AdultPrefabName;

		public string HatchlingPrefabName;
	}
	public static class BreedableSpeciesRegistry
	{
		private static readonly Dictionary<string, BreedableSpeciesInfo> RegisteredSpecies = new Dictionary<string, BreedableSpeciesInfo>(StringComparer.OrdinalIgnoreCase);

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

		public static void Register(BreedableSpeciesInfo info)
		{
			if (info != null && !string.IsNullOrWhiteSpace(info.Key))
			{
				info.Key = SpeciesKey.Canonicalize(info.Key);
				if (string.IsNullOrEmpty(info.DisplayName))
				{
					info.DisplayName = SpeciesKey.GetDisplayName(info.Key);
				}
				if (info.IsDualPurposeEgg)
				{
					info.EggCollectorKey = SpeciesKey.BuildEggCollectorKey(info.Key);
				}
				RegisteredSpecies[info.Key] = info;
			}
		}

		public static bool TryGet(string key, out BreedableSpeciesInfo info)
		{
			if (RegisteredSpecies.TryGetValue(key, out info))
			{
				return true;
			}
			if (SpeciesKey.IsEggCollectorKey(key))
			{
				string key2 = key.Substring("Egg:".Length);
				return RegisteredSpecies.TryGetValue(key2, out info);
			}
			return false;
		}

		public static bool TryGetByEggPrefab(string eggPrefabName, out BreedableSpeciesInfo info)
		{
			info = null;
			string value = SpeciesKey.Normalize(eggPrefabName);
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			foreach (BreedableSpeciesInfo value2 in RegisteredSpecies.Values)
			{
				if (value2.IsEggLayer && !string.IsNullOrEmpty(value2.EggPrefabName) && value2.EggPrefabName.Equals(value, StringComparison.OrdinalIgnoreCase))
				{
					info = value2;
					return true;
				}
			}
			return false;
		}

		public static bool HasDualPurposeEggLayers()
		{
			return RegisteredSpecies.Values.Any((BreedableSpeciesInfo species) => species.IsDualPurposeEgg);
		}

		public static IReadOnlyList<string> GetMaturingOptionKeys()
		{
			List<string> list = RegisteredSpecies.Values.Select((BreedableSpeciesInfo species) => species.Key).Distinct<string>(StringComparer.OrdinalIgnoreCase).OrderBy<string, string>((string key) => SpeciesKey.GetDisplayName(key), StringComparer.OrdinalIgnoreCase)
				.ToList();
			list.Add("All");
			return list;
		}

		public static IReadOnlyList<string> GetEggCollectorOptionKeys()
		{
			return (from species in RegisteredSpecies.Values
				where species.IsDualPurposeEgg && !string.IsNullOrEmpty(species.EggCollectorKey)
				select species.EggCollectorKey).Distinct<string>(StringComparer.OrdinalIgnoreCase).OrderBy<string, string>((string key) => SpeciesKey.GetEggCollectorDisplayName(key), StringComparer.OrdinalIgnoreCase).ToList();
		}

		public static IReadOnlyList<string> GetMaturingOptionKeysWithFallback()
		{
			if (RegisteredSpecies.Count == 0)
			{
				return SpeciesCatalog.LegacyDestinationOptionKeys;
			}
			return GetMaturingOptionKeys();
		}

		public static IReadOnlyList<string> GetDestinationOptionKeysWithFallback()
		{
			return GetMaturingOptionKeysWithFallback();
		}

		public static void DiscoverInRange(Vector3 center, float range)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			float num = range * range;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer())
				{
					Vector3 val = ((Component)allCharacter).transform.position - center;
					if (!(((Vector3)(ref val)).sqrMagnitude > num) && (SpeciesDiscovery.TryDiscoverFromCharacter(allCharacter, out var info) || SpeciesDiscovery.TryDiscoverFallback(allCharacter, out info)))
					{
						Register(info);
					}
				}
			}
		}

		public static void RefreshFromAllBreeders()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			RegisteredSpecies.Clear();
			float discoveryScanRange = ModConfig.GetDiscoveryScanRange();
			foreach (PortalRecord breederPortal in DestinationRegistry.GetBreederPortals())
			{
				DiscoverInRange(breederPortal.Position, discoveryScanRange);
			}
		}
	}
	public static class BreedingCapData
	{
		public static int GetCapLimit(SpeciesType species)
		{
			return species switch
			{
				SpeciesType.Boar => 5, 
				SpeciesType.Wolf => 4, 
				SpeciesType.Lox => 4, 
				SpeciesType.Chicken => 10, 
				SpeciesType.Asksvin => 10, 
				SpeciesType.Moose => 4, 
				_ => 0, 
			};
		}

		public static float GetCapRadius(SpeciesType species)
		{
			switch (species)
			{
			case SpeciesType.Boar:
			case SpeciesType.Wolf:
			case SpeciesType.Chicken:
			case SpeciesType.Asksvin:
				return 10f;
			case SpeciesType.Lox:
			case SpeciesType.Moose:
				return 20f;
			default:
				return 0f;
			}
		}
	}
	public sealed class PortalRecord
	{
		public ZDOID Id;

		public Vector3 Position;

		public PortalRole Role;

		public SpeciesType DeclaredSpecies;

		public string DeclaredSpeciesKey;

		public AdultDestination AdultDestination;
	}
	public static class DestinationRegistry
	{
		private static readonly Dictionary<ZDOID, PortalRecord> Portals = new Dictionary<ZDOID, PortalRecord>();

		private static readonly Dictionary<string, int> MaturingRoundRobinIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, int> FarmRoundRobinIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private static int cullRoundRobinIndex;

		private static int eggCollectorRoundRobinIndex;

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

		public static void RegisterOrUpdate(ZDOID id, Vector3 position, PortalRole role, SpeciesType declaredSpecies, AdultDestination adultDestination)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			string declaredSpeciesKey = ((declaredSpecies == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(declaredSpecies));
			RegisterOrUpdate(id, position, role, declaredSpeciesKey, adultDestination);
		}

		public static void RegisterOrUpdate(ZDOID id, Vector3 position, PortalRole role, string declaredSpeciesKey, AdultDestination adultDestination)
		{
			//IL_0005: 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_002a: 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_0016: 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)
			if (!Portals.TryGetValue(id, out var value))
			{
				value = new PortalRecord
				{
					Id = id
				};
				Portals[id] = value;
			}
			value.Position = position;
			value.Role = role;
			value.DeclaredSpeciesKey = NormalizeDeclaredSpeciesKey(role, declaredSpeciesKey);
			value.DeclaredSpecies = SpeciesCatalog.FromStorageValue(value.DeclaredSpeciesKey);
			value.AdultDestination = adultDestination;
		}

		public static void Remove(ZDOID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Portals.Remove(id);
		}

		public static PortalRecord Get(ZDOID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Portals.TryGetValue(id, out var value);
			return value;
		}

		public static void RefreshPortalPosition(PortalRecord record)
		{
			//IL_0011: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			if (record != null && ZDOMan.instance != null)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(record.Id);
				if (zDO != null)
				{
					record.Position = zDO.GetPosition();
				}
			}
		}

		public static bool TryResolveMaturingDestination(SpeciesType juvenileSpecies, out PortalRecord destination)
		{
			return TryResolveMaturingDestination((juvenileSpecies == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(juvenileSpecies), out destination);
		}

		public static bool TryResolveMaturingDestination(string speciesKey, out PortalRecord destination)
		{
			return TryResolveDestination(speciesKey, PortalRole.Maturing, MaturingRoundRobinIndex, out destination);
		}

		public static bool TryResolveFarmDestination(SpeciesType adultSpecies, out PortalRecord destination)
		{
			return TryResolveFarmDestination((adultSpecies == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(adultSpecies), out destination);
		}

		public static bool TryResolveFarmDestination(string speciesKey, out PortalRecord destination)
		{
			return TryResolveDestination(speciesKey, PortalRole.Farm, FarmRoundRobinIndex, out destination);
		}

		public static bool TryResolveCullDestination(out PortalRecord destination)
		{
			destination = null;
			List<PortalRecord> list = (from p in Portals.Values
				where p.Role == PortalRole.Cull
				orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString()
				select p).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			destination = list[cullRoundRobinIndex % list.Count];
			cullRoundRobinIndex++;
			RefreshPortalPosition(destination);
			return true;
		}

		public static bool TryResolveEggCollectorDestination(string eggCollectorKey, out PortalRecord destination)
		{
			destination = null;
			if (string.IsNullOrWhiteSpace(eggCollectorKey))
			{
				return false;
			}
			string normalizedEggKey = SpeciesKey.BuildEggCollectorKey(eggCollectorKey);
			string speciesKey = (SpeciesKey.IsEggCollectorKey(normalizedEggKey) ? normalizedEggKey.Substring("Egg:".Length) : SpeciesKey.Canonicalize(eggCollectorKey));
			List<PortalRecord> list = (from p in Portals.Values
				where p.Role == PortalRole.EggCollector && PortalAcceptsEggCollector(p.DeclaredSpeciesKey, normalizedEggKey, speciesKey)
				orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString()
				select p).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			destination = list[eggCollectorRoundRobinIndex % list.Count];
			eggCollectorRoundRobinIndex++;
			RefreshPortalPosition(destination);
			return true;
		}

		public static bool HasCullReceiver()
		{
			return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Cull);
		}

		public static bool HasEggCollector()
		{
			return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.EggCollector);
		}

		public static bool HasFarmReceiver(SpeciesType maturingReceives)
		{
			return HasFarmReceiver((maturingReceives == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(maturingReceives));
		}

		public static bool HasFarmReceiver(string maturingReceivesKey)
		{
			if (!string.IsNullOrEmpty(maturingReceivesKey) && !maturingReceivesKey.Equals("All", StringComparison.OrdinalIgnoreCase) && TryResolveFarmDestination(maturingReceivesKey, out var destination))
			{
				return true;
			}
			if (TryResolveFarmDestination("All", out destination))
			{
				return true;
			}
			if (maturingReceivesKey != null && maturingReceivesKey.Equals("All", StringComparison.OrdinalIgnoreCase))
			{
				return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Farm);
			}
			return false;
		}

		public static IEnumerable<PortalRecord> GetBreederPortals()
		{
			return Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Breeder);
		}

		public static IEnumerable<PortalRecord> GetAll()
		{
			return Portals.Values;
		}

		public static void RefreshCapWarnings()
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableCapWarning.Value || ZDOMan.instance == null)
			{
				return;
			}
			foreach (PortalRecord destination in Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Maturing && !"All".Equals(p.DeclaredSpeciesKey, StringComparison.OrdinalIgnoreCase)))
			{
				SpeciesType species = destination.DeclaredSpecies;
				if (species != SpeciesType.None)
				{
					bool flag = GetBreederPortals().Any((PortalRecord source) => Vector3.Distance(source.Position, destination.Position) <= BreedingCapData.GetCapRadius(species));
					ZDO zDO = ZDOMan.instance.GetZDO(destination.Id);
					if (zDO != null)
					{
						zDO.Set("op_cap_warning", flag);
					}
				}
			}
		}

		private static bool TryResolveDestination(string speciesKey, PortalRole requiredRole, Dictionary<string, int> roundRobinIndex, out PortalRecord destination)
		{
			destination = null;
			if (string.IsNullOrWhiteSpace(speciesKey))
			{
				return false;
			}
			List<PortalRecord> list = (from p in Portals.Values
				where p.Role == requiredRole && !SpeciesKey.IsAll(p.DeclaredSpeciesKey) && SpeciesKey.PortalAcceptsSpecies(p.DeclaredSpeciesKey, speciesKey)
				orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString()
				select p).ToList();
			if (list.Count > 0)
			{
				destination = PickRoundRobin(speciesKey, list, roundRobinIndex);
				RefreshPortalPosition(destination);
				return destination != null;
			}
			List<PortalRecord> list2 = (from p in Portals.Values
				where p.Role == requiredRole && "All".Equals(p.DeclaredSpeciesKey, StringComparison.OrdinalIgnoreCase)
				orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString()
				select p).ToList();
			if (list2.Count > 0)
			{
				destination = PickRoundRobin("All", list2, roundRobinIndex);
				RefreshPortalPosition(destination);
				return destination != null;
			}
			return false;
		}

		private static string NormalizeDeclaredSpeciesKey(PortalRole role, string declaredSpeciesKey)
		{
			if (role == PortalRole.EggCollector)
			{
				return SpeciesKey.BuildEggCollectorKey(declaredSpeciesKey);
			}
			return declaredSpeciesKey ?? string.Empty;
		}

		private static bool PortalAcceptsEggCollector(string portalSpeciesKey, string normalizedEggKey, string speciesKey)
		{
			if (string.IsNullOrWhiteSpace(portalSpeciesKey))
			{
				return false;
			}
			if (SpeciesKey.PortalAcceptsEgg(portalSpeciesKey, normalizedEggKey))
			{
				return true;
			}
			if (SpeciesKey.PortalAcceptsSpecies(portalSpeciesKey, speciesKey))
			{
				return true;
			}
			return SpeciesKey.Canonicalize(portalSpeciesKey).Equals(speciesKey, StringComparison.OrdinalIgnoreCase);
		}

		private static PortalRecord PickRoundRobin(string key, List<PortalRecord> candidates, Dictionary<string, int> roundRobinIndex)
		{
			if (candidates.Count == 0)
			{
				return null;
			}
			if (!roundRobinIndex.TryGetValue(key, out var value))
			{
				value = 0;
			}
			PortalRecord result = candidates[value % candidates.Count];
			roundRobinIndex[key] = value + 1;
			return result;
		}
	}
	public static class EggPortalRouter
	{
		public static bool TryRoute(OPTeleportWorld portal, ItemDrop egg, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime)
		{
			//IL_00ef: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_0166: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)portal == (Object)null || (Object)(object)egg == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				return false;
			}
			if ((Object)(object)((Component)egg).GetComponent<EggGrow>() == (Object)null)
			{
				return false;
			}
			if (!JuvenilePortalRouter.IsBreederPortal(portal))
			{
				return false;
			}
			ZNetView component = ((Component)egg).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val != null && val.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value)
			{
				return false;
			}
			int instanceID = ((Object)egg).GetInstanceID();
			float time = Time.time;
			if (!SpeciesDiscovery.TryGetEggSpeciesInfo(egg, out var info))
			{
				if (time - lastNoDestinationMessageTime > 5f)
				{
					lastNoDestinationMessageTime = time;
					string text = SpeciesKey.Normalize(((Object)egg).name);
					OffspringPortalPlugin.Log.LogWarning((object)("Breeder portal could not classify egg '" + text + "' for routing (missing EggGrow chain or species not discovered)."));
				}
				return false;
			}
			if (cooldowns.TryGetValue(instanceID, out var value) && time < value)
			{
				return false;
			}
			ZDOID val2 = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None);
			ZNetView component2 = ((Component)portal).GetComponent<ZNetView>();
			ZDOID val3 = (ZDOID)(((??)((component2 == null) ? ((ZDOID?)null) : component2.GetZDO()?.m_uid)) ?? ZDOID.None);
			if (val2 == ZDOID.None || val3 == ZDOID.None)
			{
				return false;
			}
			if (ZNet.instance.IsServer())
			{
				return TryRouteOnServer(portal, egg, info, val2, val3, cooldowns, ref lastNoDestinationMessageTime, time, instanceID);
			}
			if (!RoutingRpc.CanSendRequests())
			{
				return false;
			}
			RoutingRpc.RequestEggRoute(val2, val3, info.Key, info.IsDualPurposeEgg, info.EggCollectorKey);
			cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value;
			return false;
		}

		public static bool ExecuteApprovedRoute(ZDOID eggId, ZDOID sourcePortalId, PortalRecord destination, ItemDrop egg = null, OPTeleportWorld sourcePortal = null)
		{
			//IL_0003: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			if (egg == null)
			{
				egg = ResolveEgg(eggId);
			}
			if (sourcePortal == null)
			{
				sourcePortal = ResolvePortal(sourcePortalId);
			}
			if ((Object)(object)egg == (Object)null || (Object)(object)sourcePortal == (Object)null || destination == null)
			{
				return false;
			}
			if (!JuvenilePortalRouter.IsBreederPortal(sourcePortal))
			{
				return false;
			}
			if (!EggTeleporter.TryExecuteApproved(egg, destination, sourcePortal))
			{
				return false;
			}
			if (SpeciesDiscovery.TryGetEggSpeciesInfo(egg, out var info))
			{
				string arg = ((destination.Role == PortalRole.EggCollector) ? SpeciesKey.GetEggCollectorDisplayName(info.EggCollectorKey) : "maturing portal");
				OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {info.DisplayName} egg to {arg} at {destination.Position}.");
			}
			PlayPortalActivation(sourcePortal);
			return true;
		}

		private static bool TryRouteOnServer(OPTeleportWorld portal, ItemDrop egg, BreedableSpeciesInfo speciesInfo, ZDOID eggId, ZDOID sourcePortalId, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime, float now, int bodyId)
		{
			//IL_004a: 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)
			if (!EggRoutingResolver.TryResolveDestination(speciesInfo, out var destination))
			{
				if (now - lastNoDestinationMessageTime > 5f)
				{
					lastNoDestinationMessageTime = now;
					string eggRoutingFailureMessage = GetEggRoutingFailureMessage(speciesInfo);
					OffspringPortalPlugin.Log.LogWarning((object)eggRoutingFailureMessage);
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer != (Object)null)
					{
						((Character)localPlayer).Message((MessageType)2, eggRoutingFailureMessage, 0, (Sprite)null, false);
					}
				}
				return false;
			}
			if (ExecuteApprovedRoute(eggId, sourcePortalId, destination, egg, portal))
			{
				cooldowns[bodyId] = now + ModConfig.TeleportCooldownSec.Value;
				return true;
			}
			return false;
		}

		private static string GetEggRoutingFailureMessage(BreedableSpeciesInfo speciesInfo)
		{
			if (speciesInfo.IsDualPurposeEgg && EggRoutingResolver.IsHenEgg(speciesInfo))
			{
				if (DestinationRegistry.HasEggCollector())
				{
					return EggRoutingResolver.GetHenRoutingFailureMessage();
				}
				return "No Egg Collector or Maturing portal registered for Hen eggs.";
			}
			if (speciesInfo.IsDualPurposeEgg)
			{
				string eggCollectorDisplayName = SpeciesKey.GetEggCollectorDisplayName(speciesInfo.EggCollectorKey);
				return "No egg collector for " + eggCollectorDisplayName + " and no maturing fallback registered.";
			}
			return "No maturing portal registered for " + speciesInfo.DisplayName + " eggs.";
		}

		private static ItemDrop ResolveEgg(ZDOID eggId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(eggId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<ItemDrop>();
		}

		private static OPTeleportWorld ResolvePortal(ZDOID portalId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(portalId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<OPTeleportWorld>();
		}

		private static void PlayPortalActivation(OPTeleportWorld portal)
		{
			portal?.PlayActivationEffect();
		}
	}
	public static class EggRecipeHelper
	{
		private static readonly string[] KnownDualPurposeEggPrefabs = new string[1] { "Egg" };

		public static bool IsUsedInRecipe(SharedData shared)
		{
			if (shared == null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			string name = shared.m_name;
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if ((Object)(object)recipe == (Object)null || !recipe.m_enabled || recipe.m_resources == null)
				{
					continue;
				}
				Requirement[] resources = recipe.m_resources;
				foreach (Requirement val in resources)
				{
					if (!((Object)(object)val?.m_resItem == (Object)null))
					{
						SharedData val2 = val.m_resItem.m_itemData?.m_shared;
						if (val2 != null && val2.m_name == name)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		public static bool IsUsedInRecipe(ItemDrop itemDrop)
		{
			if ((Object)(object)itemDrop == (Object)null)
			{
				return false;
			}
			if (IsKnownDualPurposeEggPrefab(((Object)itemDrop).name))
			{
				return true;
			}
			return IsUsedInRecipe(itemDrop.m_itemData?.m_shared);
		}

		private static bool IsKnownDualPurposeEggPrefab(string prefabName)
		{
			string text = SpeciesKey.Normalize(prefabName);
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] knownDualPurposeEggPrefabs = KnownDualPurposeEggPrefabs;
			foreach (string value in knownDualPurposeEggPrefabs)
			{
				if (text.Equals(value, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class EggRoutingResolver
	{
		private static readonly string[] HenEggCollectorLookupKeys = new string[4] { "Egg:Chicken", "Chicken", "Hen", "Egg:Hen" };

		public static bool IsHenEgg(BreedableSpeciesInfo speciesInfo)
		{
			if (speciesInfo == null)
			{
				return false;
			}
			return SpeciesKey.Canonicalize(speciesInfo.Key).Equals(SpeciesCatalog.ToStorageValue(SpeciesType.Chicken), StringComparison.OrdinalIgnoreCase);
		}

		public static bool TryResolveDestination(BreedableSpeciesInfo speciesInfo, out PortalRecord destination)
		{
			destination = null;
			if (speciesInfo == null)
			{
				return false;
			}
			if (speciesInfo.IsDualPurposeEgg && IsHenEgg(speciesInfo))
			{
				if (TryResolveHenEggCollector(out destination))
				{
					return true;
				}
				if (DestinationRegistry.HasEggCollector())
				{
					return false;
				}
				return DestinationRegistry.TryResolveMaturingDestination(speciesInfo.Key, out destination);
			}
			if (speciesInfo.IsDualPurposeEgg)
			{
				if (DestinationRegistry.TryResolveEggCollectorDestination(speciesInfo.EggCollectorKey, out destination) || DestinationRegistry.TryResolveMaturingDestination(speciesInfo.Key, out destination))
				{
					return destination != null;
				}
				return false;
			}
			return DestinationRegistry.TryResolveMaturingDestination(speciesInfo.Key, out destination);
		}

		public static string GetHenRoutingFailureMessage()
		{
			return "Hen egg not routed: an Egg Collector portal exists but none are configured for Hen eggs.";
		}

		private static bool TryResolveHenEggCollector(out PortalRecord destination)
		{
			string[] henEggCollectorLookupKeys = HenEggCollectorLookupKeys;
			for (int i = 0; i < henEggCollectorLookupKeys.Length; i++)
			{
				if (DestinationRegistry.TryResolveEggCollectorDestination(henEggCollectorLookupKeys[i], out destination))
				{
					return true;
				}
			}
			destination = null;
			return false;
		}
	}
	public static class EggTeleporter
	{
		public static bool TryTeleport(ItemDrop egg, PortalRecord destination, OPTeleportWorld sourcePortal)
		{
			return TryExecuteApproved(egg, destination, sourcePortal);
		}

		public static bool TryExecuteApproved(ItemDrop egg, PortalRecord destination, OPTeleportWorld sourcePortal)
		{
			//IL_001e: 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_0029: 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_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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)egg == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null)
			{
				return false;
			}
			DestinationRegistry.RefreshPortalPosition(destination);
			Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal);
			Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, sourcePortal);
			ZNetView component = ((Component)egg).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || component.GetZDO() == null)
			{
				return false;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
				if (!component.IsOwner() && !ZNet.instance.IsServer())
				{
					return false;
				}
			}
			Vector3 position = exitPosition + exitRotation * Vector3.right * Random.Range(-0.15f, 0.15f);
			((Component)egg).transform.position = position;
			((Component)egg).transform.rotation = exitRotation;
			ZDO zDO = component.GetZDO();
			if (zDO != null)
			{
				zDO.SetPosition(position);
				zDO.SetRotation(exitRotation);
				zDO.Set("op_transported", true);
			}
			Rigidbody component2 = ((Component)egg).GetComponent<Rigidbody>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.linearVelocity = Vector3.zero;
				component2.angularVelocity = Vector3.zero;
			}
			return true;
		}
	}
	public static class JuvenileFollow
	{
		internal const string LetsGoPluginGuid = "hardwire99.letsgo";

		public static bool TryCommand(Character character, Player player, bool showMessage)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!ModConfig.EnableFollowCommand.Value || IsLetsGoLoaded())
			{
				return false;
			}
			if (!SpeciesHelper.IsEligibleJuvenile(character) || !character.IsTamed())
			{
				return false;
			}
			ZNetView nview = character.GetNview();
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			JuvenileGroundSnapper.EnsureAttached(character);
			JuvenileFollowController.EnsureAttached(character);
			if (ZNet.instance.IsServer())
			{
				return ApplyFollowToggle(character, player, showMessage);
			}
			JuvenileFollowRpc.RequestToggle(nview.GetZDO().m_uid, ((Character)player).GetZDOID(), showMessage);
			return true;
		}

		public static bool ApplyFollowToggle(Character character, Player player, bool showMessage)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)character).GetComponent<AnimalAI>() != (Object)null)
			{
				return ApplyAnimalFollowToggle(character, player, showMessage);
			}
			MonsterAI component = ((Component)character).GetComponent<MonsterAI>();
			if ((Object)(object)component != (Object)null)
			{
				Tameable component2 = ((Component)character).GetComponent<Tameable>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.m_commandable = true;
				}
				ApplyMonsterFollowToggle(character, component, player, showMessage);
				return true;
			}
			return false;
		}

		internal static bool IsLetsGoLoaded()
		{
			return Chainloader.PluginInfos.ContainsKey("hardwire99.letsgo");
		}

		public static bool IsFollowing(Character character)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			MonsterAI component = ((Component)character).GetComponent<MonsterAI>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.GetFollowTarget() != (Object)null)
			{
				return true;
			}
			ZDO zdo = character.GetZdo();
			if (zdo != null)
			{
				return zdo.GetZDOID("op_follow_target") != ZDOID.None;
			}
			return false;
		}

		private static void ApplyMonsterFollowToggle(Character character, MonsterAI monsterAi, Player player, bool showMessage)
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && !component.IsOwner())
			{
				component.ClaimOwnership();
			}
			string hoverName = character.GetHoverName();
			if ((Object)(object)monsterAi.GetFollowTarget() != (Object)null)
			{
				monsterAi.SetFollowTarget((GameObject)null);
				((BaseAI)monsterAi).SetPatrolPoint();
				if ((Object)(object)component != (Object)null && component.IsOwner())
				{
					ZDO zDO = component.GetZDO();
					if (zDO != null)
					{
						zDO.Set(ZDOVars.s_follow, string.Empty);
					}
				}
				if (showMessage)
				{
					((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamestay"), 0, (Sprite)null, false);
				}
				return;
			}
			((BaseAI)monsterAi).ResetPatrolPoint();
			monsterAi.SetFollowTarget(((Component)player).gameObject);
			if ((Object)(object)component != (Object)null && component.IsOwner())
			{
				ZDO zDO2 = component.GetZDO();
				if (zDO2 != null)
				{
					zDO2.Set(ZDOVars.s_follow, player.GetPlayerName());
				}
			}
			if (showMessage)
			{
				((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null, false);
			}
		}

		public static bool ApplyAnimalFollowToggle(Character character, Player player, bool showMessage)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0094: 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)
			ZNetView nview = character.GetNview();
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			if (!nview.IsOwner())
			{
				nview.ClaimOwnership();
			}
			ZDO zdo = character.GetZdo();
			if (zdo == null)
			{
				return false;
			}
			ZDOID zDOID = ((Character)player).GetZDOID();
			ZDOID zDOID2 = zdo.GetZDOID("op_follow_target");
			string hoverName = character.GetHoverName();
			if (zDOID2 == zDOID)
			{
				zdo.Set("op_follow_target", ZDOID.None);
				if (showMessage)
				{
					((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamestay"), 0, (Sprite)null, false);
				}
			}
			else
			{
				zdo.Set("op_follow_target", zDOID);
				if (showMessage)
				{
					((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null, false);
				}
			}
			return true;
		}
	}
	public sealed class JuvenileFollowController : MonoBehaviour
	{
		public static bool TryApplyAnimalFollow(AnimalAI animalAi, float dt)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_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_00b4: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableFollowCommand.Value || (Object)(object)animalAi == (Object)null)
			{
				return false;
			}
			Character component = ((Component)animalAi).GetComponent<Character>();
			ZNetView component2 = ((Component)animalAi).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.IsValid())
			{
				return false;
			}
			if (!component2.IsOwner())
			{
				return false;
			}
			if (!SpeciesHelper.IsEligibleJuvenile(component) || !component.IsTamed())
			{
				return false;
			}
			ZDO zdo = component.GetZdo();
			if (zdo == null)
			{
				return false;
			}
			ZDOID zDOID = zdo.GetZDOID("op_follow_target");
			if (zDOID == ZDOID.None)
			{
				return false;
			}
			Player val = ResolvePlayer(zDOID);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Vector3 val2 = ((Component)val).transform.position - ((Component)component).transform.position;
			val2.y = 0f;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			if (magnitude < 2f)
			{
				((BaseAI)animalAi).StopMoving();
				return true;
			}
			((BaseAI)animalAi).MoveTowards(val2 / magnitude, magnitude > 10f);
			return true;
		}

		public static void EnsureAttached(Character character)
		{
			if (!((Object)(object)character == (Object)null) && !((Object)(object)((Component)character).GetComponent<AnimalAI>() == (Object)null) && (Object)(object)((Component)character).GetComponent<JuvenileFollowController>() == (Object)null)
			{
				((Component)character).gameObject.AddComponent<JuvenileFollowController>();
			}
		}

		private static Player ResolvePlayer(ZDOID followId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(followId) : null);
			Player val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Player>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				ZNetView val3 = ((Character)(object)allPlayer)?.GetNview();
				if ((Object)(object)val3 != (Object)null)
				{
					ZDO zDO = val3.GetZDO();
					if (zDO != null && zDO.m_uid == followId)
					{
						return allPlayer;
					}
				}
			}
			return null;
		}
	}
	public static class JuvenileFollowDisplay
	{
		public static void ApplyFollowHover(Character character, ref string hoverText)
		{
			if (ModConfig.EnableFollowCommand.Value && !JuvenileFollow.IsLetsGoLoaded() && !((Object)(object)character == (Object)null) && SpeciesHelper.IsEligibleJuvenile(character) && character.IsTamed() && (!((Object)(object)((Component)character).GetComponent<MonsterAI>() == (Object)null) || !((Object)(object)((Component)character).GetComponent<AnimalAI>() == (Object)null)))
			{
				string text = (JuvenileFollow.IsFollowing(character) ? "$hud_tamestay" : "$hud_tamefollow");
				string newValue = Localization.instance.Localize(text);
				string text2 = Localization.instance.Localize("$hud_pet");
				if (!string.IsNullOrEmpty(hoverText) && hoverText.Contains(text2))
				{
					hoverText = hoverText.Replace(text2, newValue);
				}
				else if (!string.IsNullOrEmpty(hoverText))
				{
					hoverText += Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] " + text);
				}
				else
				{
					hoverText = Localization.instance.Localize(character.GetHoverName() + "\n[<color=yellow><b>$KEY_Use</b></color>] " + text);
				}
			}
		}
	}
	public static class JuvenileFollowRpc
	{
		private const string RpcToggleFollow = "OffspringPortal_ToggleJuvenileFollow";

		private const string RpcExecuteToggleFollow = "OffspringPortal_ExecuteJuvenileFollow";

		private static bool registered;

		public static void Register()
		{
			if (!registered && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc instance = ZRoutedRpc.instance;
				instance.Register<ZDOID, ZDOID, bool>("OffspringPortal_ToggleJuvenileFollow", (Action<long, ZDOID, ZDOID, bool>)OnToggleFollowRpc);
				instance.Register<ZDOID, ZDOID, bool>("OffspringPortal_ExecuteJuvenileFollow", (Action<long, ZDOID, ZDOID, bool>)OnExecuteToggleFollowRpc);
				registered = true;
			}
		}

		public static void RequestToggle(ZDOID creatureId, ZDOID playerId, bool showMessage)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc.instance.InvokeRoutedRPC("OffspringPortal_ToggleJuvenileFollow", new object[3] { creatureId, playerId, showMessage });
		}

		private static void OnToggleFollowRpc(long sender, ZDOID creatureId, ZDOID playerId, bool showMessage)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (ZNet.instance.IsServer())
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "OffspringPortal_ExecuteJuvenileFollow", new object[3] { creatureId, playerId, showMessage });
			}
		}

		private static void OnExecuteToggleFollowRpc(long sender, ZDOID creatureId, ZDOID playerId, bool showMessage)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ApplyToggle(creatureId, playerId, showMessage, sender);
		}

		private static void ApplyToggle(ZDOID creatureId, ZDOID playerId, bool showMessage, long sender)
		{
			//IL_0000: 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)
			Character val = ResolveCreature(creatureId);
			Player val2 = ResolveRequestingPlayer(sender, playerId);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && SpeciesHelper.IsEligibleJuvenile(val) && val.IsTamed())
			{
				JuvenileGroundSnapper.EnsureAttached(val);
				JuvenileFollowController.EnsureAttached(val);
				JuvenileFollow.ApplyFollowToggle(val, val2, showMessage);
			}
		}

		private static Character ResolveCreature(ZDOID creatureId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(creatureId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<Character>();
		}

		private static Player ResolveRequestingPlayer(long sender, ZDOID playerId)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Player player = Player.GetPlayer(sender);
			if ((Object)(object)player != (Object)null)
			{
				return player;
			}
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(playerId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<Player>();
		}
	}
	public sealed class JuvenileGroundSnapper : MonoBehaviour
	{
		private Character character;

		private ZNetView nview;

		private float nextCheckTime;

		private void Awake()
		{
			character = ((Component)this).GetComponent<Character>();
			nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void Start()
		{
			TrySnapToGround(force: true);
		}

		private void LateUpdate()
		{
			if (!(Time.time < nextCheckTime) && !((Object)(object)character == (Object)null) && !((Object)(object)nview == (Object)null) && nview.IsValid() && ZNet.instance.IsServer() && nview.IsOwner() && SpeciesHelper.IsEligibleJuvenile(character))
			{
				nextCheckTime = Time.time + 1f;
				TrySnapToGround(force: false);
			}
		}

		public static void EnsureAttached(Character character)
		{
			if (!((Object)(object)character == (Object)null) && SpeciesHelper.IsEligibleJuvenile(character))
			{
				JuvenileGroundSnapper juvenileGroundSnapper = ((Component)character).GetComponent<JuvenileGroundSnapper>();
				if ((Object)(object)juvenileGroundSnapper == (Object)null)
				{
					juvenileGroundSnapper = ((Component)character).gameObject.AddComponent<JuvenileGroundSnapper>();
				}
				juvenileGroundSnapper.TrySnapToGround(force: true);
			}
		}

		private void TrySnapToGround(bool force)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			if (JuvenilePlacement.TryGetFloorPosition(((Component)this).transform.position, out var grounded))
			{
				float num = ((Component)this).transform.position.y - grounded.y;
				if (force || !(num < 0.35f))
				{
					JuvenilePlacement.ApplyPosition(character, grounded, ((Component)this).transform.rotation);
				}
			}
		}
	}
	public static class JuvenileInteractHelper
	{
		private static readonly int InteractMask = LayerMask.GetMask(new string[10] { "item", "piece", "piece_nonsolid", "Default", "static_solid", "Default_small", "character", "character_net", "terrain", "vehicle" });

		public static Character FindJuvenileUnderCrosshair(Player player, float maxDistance = 6f)
		{
			return FindTamedCharacterUnderCrosshair(player, maxDistance, juvenilesOnly: true);
		}

		public static Character FindTamedCharacterUnderCrosshair(Player player, float maxDistance, bool juvenilesOnly)
		{
			//IL_0022: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null)
			{
				return null;
			}
			Vector3 position = ((Component)GameCamera.instance).transform.position;
			Vector3 forward = ((Component)GameCamera.instance).transform.forward;
			Vector3 position2 = ((Character)player).m_eye.position;
			RaycastHit[] source = Physics.RaycastAll(position, forward, 50f, InteractMask);
			Character result = null;
			float num = maxDistance;
			foreach (RaycastHit item in source.OrderBy((RaycastHit h) => ((RaycastHit)(ref h)).distance))
			{
				RaycastHit current = item;
				if ((Object)(object)((RaycastHit)(ref current)).collider == (Object)null || ((Object)(object)((RaycastHit)(ref current)).collider.attachedRigidbody != (Object)null && (Object)(object)((Component)((RaycastHit)(ref current)).collider.attachedRigidbody).gameObject == (Object)(object)((Component)player).gameObject))
				{
					continue;
				}
				Character val = (((Object)(object)((RaycastHit)(ref current)).collider.attachedRigidbody != (Object)null) ? ((Component)((RaycastHit)(ref current)).collider.attachedRigidbody).GetComponent<Character>() : ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Character>());
				if (!((Object)(object)val == (Object)null) && !val.IsPlayer() && val.IsTamed() && (!juvenilesOnly || SpeciesHelper.IsEligibleJuvenile(val)) && (juvenilesOnly || !((Object)(object)((Component)val).GetComponent<Tameable>() == (Object)null)))
				{
					float num2 = Vector3.Distance(position2, ((RaycastHit)(ref current)).point);
					if (num2 <= num)
					{
						result = val;
						num = num2;
					}
				}
			}
			return result;
		}
	}
	public static class JuvenilePlacement
	{
		private static readonly int FloorMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "piece", "piece_nonsolid", "terrain", "water" });

		public static bool TryGetFloorPosition(Vector3 position, out Vector3 grounded)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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)
			grounded = position;
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			float num = Mathf.Max(position.y + 30f, 128f);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(position.x, num, position.z);
			float solidHeight = default(float);
			if (!ZoneSystem.instance.GetGroundHeight(val, ref solidHeight))
			{
				solidHeight = ZoneSystem.instance.GetSolidHeight(position);
			}
			if (position.y - solidHeight > 2f)
			{
				grounded.y = solidHeight + 0.2f;
				return true;
			}
			float num2 = solidHeight + 0.2f;
			RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, num + 100f, FloorMask);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val2 = array[i];
				if (!(((RaycastHit)(ref val2)).point.y > position.y + 1f) && !(((RaycastHit)(ref val2)).point.y < solidHeight - 1f) && ((RaycastHit)(ref val2)).point.y > num2)
				{
					num2 = ((RaycastHit)(ref val2)).point.y + 0.15f;
				}
			}
			grounded.y = num2;
			return true;
		}

		public static void ApplyPosition(Character character, Vector3 position, Quaternion rotation)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)character == (Object)null))
			{
				((Component)character).transform.position = position;
				((Component)character).transform.rotation = rotation;
				Rigidbody component = ((Component)character).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null)
				{
					component.linearVelocity = Vector3.zero;
					component.angularVelocity = Vector3.zero;
				}
				character.SetLookDir(position, 0f);
				ZNetView nview = character.GetNview();
				ZDO val = ((nview != null) ? nview.GetZDO() : null);
				if (val != null)
				{
					val.SetPosition(position);
					val.SetRotation(rotation);
				}
			}
		}
	}
	public static class JuvenilePortalRouter
	{
		public static bool IsBreederPortal(OPTeleportWorld portal)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)portal == (Object)null)
			{
				return false;
			}
			ZNetView component = ((Component)portal).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val == null)
			{
				return false;
			}
			PortalRecord portalRecord = DestinationRegistry.Get(val.m_uid);
			if (portalRecord != null)
			{
				return portalRecord.Role == PortalRole.Breeder;
			}
			return PortalRoleCatalog.FromZdo(val) == PortalRole.Breeder;
		}

		public static bool TryRoute(OPTeleportWorld portal, Character character, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: 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)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)portal == (Object)null || (Object)(object)character == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				return false;
			}
			if (!SpeciesHelper.IsEligibleJuvenile(character))
			{
				return false;
			}
			int instanceID = ((Object)character).GetInstanceID();
			float time = Time.time;
			if (cooldowns.TryGetValue(instanceID, out var value) && time < value)
			{
				return false;
			}
			ZDO zdo = character.GetZdo();
			if (zdo != null && zdo.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value)
			{
				return false;
			}
			if (!IsBreederPortal(portal))
			{
				return false;
			}
			string juvenileSpeciesKey = SpeciesHelper.GetJuvenileSpeciesKey(character);
			if (string.IsNullOrEmpty(juvenileSpeciesKey))
			{
				return false;
			}
			ZNetView nview = character.GetNview();
			ZDOID val = (ZDOID)(((??)((nview == null) ? ((ZDOID?)null) : nview.GetZDO()?.m_uid)) ?? ZDOID.None);
			ZNetView component = ((Component)portal).GetComponent<ZNetView>();
			ZDOID val2 = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None);
			if (val == ZDOID.None || val2 == ZDOID.None)
			{
				return false;
			}
			if (ZNet.instance.IsServer())
			{
				return TryRouteOnServer(portal, character, juvenileSpeciesKey, val, val2, cooldowns, ref lastNoDestinationMessageTime, time, instanceID);
			}
			if (!RoutingRpc.CanSendRequests())
			{
				return false;
			}
			RoutingRpc.RequestJuvenileRoute(val, val2, juvenileSpeciesKey);
			cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value;
			return false;
		}

		public static bool ExecuteApprovedRoute(ZDOID characterId, ZDOID sourcePortalId, PortalRecord destination, Character character = null, OPTeleportWorld sourcePortal = null)
		{
			//IL_0003: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (character == null)
			{
				character = ResolveCharacter(characterId);
			}
			if (sourcePortal == null)
			{
				sourcePortal = ResolvePortal(sourcePortalId);
			}
			if (destination == null)
			{
				return false;
			}
			if ((Object)(object)character != (Object)null && (Object)(object)sourcePortal != (Object)null)
			{
				if (!SpeciesHelper.IsEligibleJuvenile(character) || !IsBreederPortal(sourcePortal))
				{
					return false;
				}
				string juvenileSpeciesKey = SpeciesHelper.GetJuvenileSpeciesKey(character);
				if (JuvenileTeleporter.TryExecuteApproved(character, destination, sourcePortal))
				{
					OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesKey.GetDisplayName(juvenileSpeciesKey)} juvenile to maturing portal at {destination.Position}.");
					PlayPortalActivation(sourcePortal);
					return true;
				}
			}
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && JuvenileTeleporter.TryMoveZdo(characterId, destination, sourcePortalId))
			{
				OffspringPortalPlugin.Log.LogInfo((object)$"Teleported juvenile via ZDO to maturing portal at {destination.Position}.");
				PlayPortalActivation(sourcePortal);
				return true;
			}
			return false;
		}

		private static bool TryRouteOnServer(OPTeleportWorld portal, Character character, string speciesKey, ZDOID characterId, ZDOID sourcePortalId, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime, float now, int bodyId)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!DestinationRegistry.TryResolveMaturingDestination(speciesKey, out var destination))
			{
				if (now - lastNoDestinationMessageTime > 5f)
				{
					lastNoDestinationMessageTime = now;
					string displayName = SpeciesKey.GetDisplayName(speciesKey);
					OffspringPortalPlugin.Log.LogWarning((object)("No maturing portal registered for " + displayName + "."));
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer != (Object)null)
					{
						((Character)localPlayer).Message((MessageType)2, "No maturing portal registered for " + displayName + ".", 0, (Sprite)null, false);
					}
				}
				return false;
			}
			if (ExecuteApprovedRoute(characterId, sourcePortalId, destination, character, portal))
			{
				cooldowns[bodyId] = now + ModConfig.TeleportCooldownSec.Value;
				return true;
			}
			OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesKey.GetDisplayName(speciesKey) + " juvenile."));
			return false;
		}

		private static Character ResolveCharacter(ZDOID characterId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(characterId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<Character>();
		}

		private static OPTeleportWorld ResolvePortal(ZDOID portalId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(portalId) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<OPTeleportWorld>();
		}

		private static void PlayPortalActivation(OPTeleportWorld portal)
		{
			portal?.PlayActivationEffect();
		}
	}
	public static class JuvenileTeleporter
	{
		public static bool TryTeleport(Character juvenile, PortalRecord destination, OPTeleportWorld sourcePortal)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null)
			{
				return false;
			}
			if (!ZNet.instance.IsServer() && !CanExecuteLocally(juvenile))
			{
				return false;
			}
			DestinationRegistry.RefreshPortalPosition(destination);
			Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal);
			if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(exitPosition))
			{
				return TryExecuteApproved(juvenile, destination, sourcePortal);
			}
			if (TryExecuteApproved(juvenile, destination, sourcePortal, allowStoredHeight: true))
			{
				OffspringPortalPlugin.Log.LogInfo((object)$"Cross-zone teleport of {SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile))} to {exitPosition}.");
				return true;
			}
			OffspringPortalPlugin.Log.LogInfo((object)("Deferring teleport of " + SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile)) + " until pen zone loads."));
			if (ZNet.instance.IsServer())
			{
				return OffspringPortalRuntime.Instance.TryQueueDistantTeleport(juvenile, destination, sourcePortal);
			}
			return false;
		}

		public static bool TryTeleportNow(Character juvenile, PortalRecord destination, OPTeleportWorld sourcePortal, bool allowStoredHeight = false)
		{
			return TryExecuteApproved(juvenile, destination, sourcePortal, allowStoredHeight);
		}

		public static bool TryExecuteApproved(Character juvenile, PortalRecord destination, OPTeleportWorld sourcePortal, bool allowStoredHeight = false)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			if ((Object)(object)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null)
			{
				return false;
			}
			ZNetView nview = juvenile.GetNview();
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			if (!nview.IsOwner())
			{
				nview.ClaimOwnership();
				if (!nview.IsOwner() && !ZNet.instance.IsServer())
				{
					return false;
				}
			}
			Tameable component = ((Component)juvenile).GetComponent<Tameable>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_unsummonDistance = 0f;
			}
			DestinationRegistry.RefreshPortalPosition(destination);
			Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal);
			Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, sourcePortal);
			if (!TryPlaceCharacter(juvenile, exitPosition, exitRotation, allowStoredHeight))
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					((Character)localPlayer).Message((MessageType)2, "Could not place " + SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile)) + " at destination.", 0, (Sprite)null, false);
				}
				return false;
			}
			JuvenileGroundSnapper.EnsureAttached(juvenile);
			JuvenileFollowController.EnsureAttached(juvenile);
			ZDO zDO = nview.GetZDO();
			if (zDO != null)
			{
				zDO.Set("op_transported", true);
			}
			return true;
		}

		public static bool TryMoveZdo(ZDOID characterId, PortalRecord destination, ZDOID sourcePortalId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			if (!ZNet.instance.IsServer() || characterId == ZDOID.None || destination == null || ZDOMan.instance == null)
			{
				return false;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(characterId);
			if (zDO == null)
			{
				return false;
			}
			if (zDO.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value)
			{
				return false;
			}
			zDO.SetOwner(ZDOMan.GetSessionID());
			OPTeleportWorld fallbackPortal = null;
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(sourcePortalId) : null);
			if ((Object)(object)val != (Object)null)
			{
				fallbackPortal = val.GetComponent<OPTeleportWorld>();
			}
			Vector3 position = PortalPlacement.GetExitPosition(destination.Id, fallbackPortal);
			Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, fallbackPortal);
			if (JuvenilePlacement.TryGetFloorPosition(position, out var grounded))
			{
				position = grounded;
			}
			zDO.SetPosition(position);
			zDO.SetRotation(exitRotation);
			zDO.Set("op_transported", true);
			return true;
		}

		public static Vector3 ResolveDestinationPosition(PortalRecord destination, OPTeleportWorld sourcePortal)
		{
			//IL_0001: 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)
			return PortalPlacement.GetExitPosition(destination.Id, sourcePortal);
		}

		public static Quaternion ResolveDestinationRotation(PortalRecord destination, OPTeleportWorld sourcePortal)
		{
			//IL_0001: 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)
			return PortalPlacement.GetExitRotation(destination.Id, sourcePortal);
		}

		private static bool CanExecuteLocally(Character juvenile)
		{
			ZNetView val = juvenile?.GetNview();
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return val.IsOwner();
			}
			return false;
		}

		private static bool TryPlaceCharacter(Character character, Vector3 destination, Quaternion rotation, bool allowStoredHeight)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_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_0011: 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_0026: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			Vector3 val = rotation * Vector3.right;
			for (int i = 0; i < 5; i++)
			{
				if (JuvenilePlacement.TryGetFloorPosition(destination + val * Random.Range(-0.2f, 0.2f), out var grounded))
				{
					JuvenilePlacement.ApplyPosition(character, grounded, rotation);
					JuvenileGroundSnapper.EnsureAttached(character);
					return true;
				}
			}
			if (!allowStoredHeight)
			{
				return false;
			}
			if (JuvenilePlacement.TryGetFloorPosition(destination, out var grounded2))
			{
				JuvenilePlacement.ApplyPosition(character, grounded2, rotation);
				return true;
			}
			return false;
		}
	}
	public static class MateDrawController
	{
		public static bool TryApplyMonsterMateDraw(MonsterAI monsterAi, float dt)
		{
			//IL_0032: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			if (!ModConfig.EnableMateDraw.Value || (Object)(object)monsterAi == (Object)null)
			{
				return false;
			}
			Character component = ((Component)monsterAi).GetComponent<Character>();
			if (!CanApplyMateDraw(component, out var partner, out var stopDistance))
			{
				return false;
			}
			Vector3 val = ((Component)partner).transform.position - ((Component)component).transform.position;
			val.y = 0f;
			float magnitude = ((Vector3)(ref val)).magnitude;
			Procreation component2 = ((Component)component).GetComponent<Procreation>();
			if (ShouldYieldBreedingToVanilla(component, component2, magnitude, stopDistance))
			{
				return false;
			}
			bool flag = magnitude > 10f;
			Traverse.Create((object)monsterAi).Method("MoveTo", new object[4]
			{
				dt,
				((Component)partner).transform.position,
				0f,
				flag
			}).GetValue();
			return true;
		}

		public static bool TryApplyAnimalMateDraw(AnimalAI animalAi, float dt)
		{
			//IL_0032: 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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			if (!ModConfig.EnableMateDraw.Value || (Object)(object)animalAi == (Object)null)
			{
				return false;
			}
			Character component = ((Component)animalAi).GetComponent<Character>();
			if (!CanApplyMateDraw(component, out var partner, out var stopDistance))
			{
				return false;
			}
			Vector3 val = ((Component)partner).transform.position - ((Component)component).transform.position;
			val.y = 0f;
			float magnitude = ((Vector3)(ref val)).magnitude;
			Procreation component2 = ((Component)component).GetComponent<Procreation>();
			if (ShouldYieldBreedingToVanilla(component, component2, magnitude, stopDistance))
			{
				return false;
			}
			((BaseAI)animalAi).MoveTowards(val / magnitude, magnitude > 10f);
			return true;
		}

		public static void SetMateDrawTarget(Character character, Character partner)
		{
			//IL_006b: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || (Object)(object)partner == (Object)null)
			{
				return;
			}
			ZNetView nview = character.GetNview();
			ZDO zdo = character.GetZdo();
			if (!((Object)(object)nview == (Object)null) && zdo != null)
			{
				if (!nview.IsOwner())
				{
					nview.ClaimOwnership();
				}
				ZNetView nview2 = partner.GetNview();
				zdo.Set("op_mate_draw_target", (ZDOID)(((??)((nview2 == null) ? ((ZDOID?)null) : nview2.GetZDO()?.m_uid)) ?? ZDOID.None));
			}
		}

		public static void ClearMateDraw(Character character)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = character?.GetZdo();
			if (val != null && !(val.GetZDOID("op_mate_draw_target") == ZDOID.None))
			{
				val.Set("op_mate_draw_target", ZDOID.None);
			}
		}

		private static bool CanApplyMateDraw(Character character, out Character partner, out float stopDistance)
		{
			//IL_008b: 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_0090: 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)
			//IL_0092: 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)
			partner = null;
			stopDistance = ModConfig.MateDrawStopDistance.Value;
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			ZNetView nview = character.GetNview();
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
			{
				return false;
			}
			if (!ProcreationHelper.IsMateDrawEligible(character))
			{
				ClearMateDraw(character);
				return false;
			}
			Procreation component = ((Component)character).GetComponent<Procreation>();
			if ((Object)(object)component == (Object)null)
			{
				ClearMateDraw(character);
				return false;
			}
			if (ProcreationHelper.HasMateInBreedingRange(character, component))
			{
				ClearMateDraw(character);
				return false;
			}
			ZDO zdo = character.GetZdo();
			ZDOID val = ((zdo != null) ? zdo.GetZDOID("op_mate_draw_target") : ZDOID.None);
			if (val == ZDOID.None)
			{
				return false;
			}
			partner = ResolveCharacter(val);
			if ((Object)(object)partner == (Object)null || !ProcreationHelper.IsMateDrawEligible(partner))
			{
				ClearMateDraw(character);
				return false;
			}
			if (!SpeciesHelper.SpeciesKeyMatches(SpeciesHelper.GetAdultSpeciesKey(character), SpeciesHelper.GetAdultSpeciesKey(partner)))
			{
				ClearMateDraw(character);
				return false;
			}
			stopDistance = ProcreationHelper.GetStopDistance(component);
			return true;
		}

		private static bool ShouldYieldBreedingToVanilla(Character character, Procreation procreation, float distance, float stopDistance)
		{
			if ((Object)(object)procreation != (Object)null && distance <= procreation.m_partnerCheckRange)
			{
				ClearMateDraw(character);
				return true;
			}
			if (distance <= stopDistance)
			{
				ClearMateDraw(character);
				return true;
			}
			return false;
		}

		private static Character ResolveCharacter(ZDOID characterId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.FindInstance(characterId) : null);
			if ((Object)(object)val != (Object)null)
			{
				Character component = val.GetComponent<Character>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				ZNetView val2 = allCharacter?.GetNview();
				if ((Object)(object)val2 != (Object)null)
				{
					ZDO zDO = val2.GetZDO();
					if (zDO != null && zDO.m_uid == characterId)
					{
						return allCharacter;
					}
				}
			}
			return null;
		}
	}
	public static class MateDrawScanner
	{
		public static void ScanPortal(OPTeleportWorld portal, Vector3 center)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableMateDraw.Value || (Object)(object)portal == (Object)null || !PortalScanHelper.ShouldScanPortal(portal) || !JuvenilePortalRouter.IsBreederPortal(portal))
			{
				return;
			}
			float value = ModConfig.MateDrawRange.Value;
			float num = value * value;
			List<Character> list = new List<Character>();
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer())
				{
					Vector3 val = ((Component)allCharacter).transform.position - center;
					if (((Vector3)(ref val)).sqrMagnitude > num)
					{
						MateDrawController.ClearMateDraw(allCharacter);
					}
					else if (!ProcreationHelper.IsMateDrawEligible(allCharacter))
					{
						MateDrawController.ClearMateDraw(allCharacter);
					}
					else
					{
						list.Add(allCharacter);
					}
				}
			}
			AssignMateTargets(list, value);
		}

		private static void AssignMateTargets(List<Character> eligible, float drawRange)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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)
			float num = drawRange * drawRange;
			foreach (Character item in eligible)
			{
				Procreation component = ((Component)item).GetComponent<Procreation>();
				if ((Object)(object)component == (Object)null)
				{
					MateDrawController.ClearMateDraw(item);
					continue;
				}
				if (ProcreationHelper.HasMateInBreedingRange(item, component))
				{
					MateDrawController.ClearMateDraw(item);
					continue;
				}
				string adultSpeciesKey = SpeciesHelper.GetAdultSpeciesKey(item);
				float partnerCheckRange = component.m_partnerCheckRange;
				float num2 = partnerCheckRange * partnerCheckRange;
				Character val = null;
				float num3 = float.MaxValue;
				Vector3 position = ((Component)item).transform.position;
				foreach (Character item2 in eligible)
				{
					if (!((Object)(object)item2 == (Object)(object)item) && SpeciesHelper.SpeciesKeyMatches(SpeciesHelper.GetAdultSpeciesKey(item2), adultSpeciesKey))
					{
						Vector3 val2 = ((Component)item2).transform.position - position;
						float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
						if (!(sqrMagnitude <= num2) && !(sqrMagnitude > num) && sqrMagnitude < num3)
						{
							num3 = sqrMagnitude;
							val = item2;
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					MateDrawController.ClearMateDraw(item);
				}
				else
				{
					MateDrawController.SetMateDrawTarget(item, val);
				}
			}
		}
	}
	public static class ModConfig
	{
		public static ConfigEntry<float> TeleportCooldownSec;

		public static ConfigEntry<float> BreederScanRange;

		public static ConfigEntry<float> BreederScanIntervalSec;

		public static ConfigEntry<float> DistantTeleportTimeoutSec;

		public static ConfigEntry<bool> AllowRetransport;

		public static ConfigEntry<bool> EnableFollowCommand;

		public static ConfigEntry<bool> EnableCapWarning;

		public static ConfigEntry<float> MaturingAdultScanIntervalSec;

		public static ConfigEntry<float> DiscoveryScanRange;

		public static ConfigEntry<bool> EnableMateDraw;

		public static ConfigEntry<float> MateDrawRange;

		public static ConfigEntry<float> MateDrawIntervalSec;

		public static ConfigEntry<float> MateDrawStopDistance;

		public static void Bind(ConfigFile config)
		{
			TeleportCooldownSec = config.Bind<float>("General", "TeleportCooldownSec", 2f, "Seconds between successive teleports at the same source portal.");
			BreederScanRange = config.Bind<float>("General", "BreederScanRange", 10f, "Breeder portals automatically teleport tamed juveniles within this radius (meters).");
			BreederScanIntervalSec = config.Bind<float>("General", "BreederScanIntervalSec", 0.5f, "How often breeder portals scan for nearby juveniles.");
			DistantTeleportTimeoutSec = config.Bind<float>("General", "DistantTeleportTimeoutSec", 15f, "How long to wait for a distant pen zone to load before giving up.");
			AllowRetransport = config.Bind<bool>("General", "AllowRetransport", false, "If true, a juvenile can use the portal more than once.");
			EnableFollowCommand = config.Bind<bool>("General", "EnableFollowCommand", true, "Press E on tamed juveniles to toggle follow/stay (Boar, Wolf, Lox, Hen, Asksvin, Moose).");
			EnableCapWarning = config.Bind<bool>("General", "EnableCapWarning", true, "Show warning when a maturing portal is within species cap radius of a breeder portal.");
			MaturingAdultScanIntervalSec = config.Bind<float>("General", "MaturingAdultScanIntervalSec", 30f, "How often maturing portals scan for nearby adults to forward to cull pens.");
			DiscoveryScanRange = config.Bind<float>("Breeding", "DiscoveryScanRange", 0f, "Radius for discovering breedable species at breeder portals (0 = max of breeder scan and mate draw range).");
			EnableMateDraw = config.Bind<bool>("Breeding", "EnableMateDraw", true, "Draw fed, ready-to-breed adults toward each other within breeder portal range.");
			MateDrawRange = config.Bind<float>("Breeding", "MateDrawRange", 15f, "How far apart mates can be before breeder portals nudge them together (meters).");
			MateDrawIntervalSec = config.Bind<float>("Breeding", "MateDrawIntervalSec", 1.5f, "How often breeder portals scan for mate-draw pairing.");
			MateDrawStopDistance = config.Bind<float>("Breeding", "MateDrawStopDistance", 2.5f, "How close mates move before stopping (should be within vanilla breeding range).");
		}

		public static float GetDiscoveryScanRange()
		{
			if (DiscoveryScanRange.Value > 0f)
			{
				return DiscoveryScanRange.Value;
			}
			float value = BreederScanRange.Value;
			if (!EnableMateDraw.Value)
			{
				return value;
			}
			return Mathf.Max(value, MateDrawRange.Value);
		}
	}
	internal static class OffspringPortalLocalization
	{
		internal static void Register()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "piece_offspring_portal", "Offspring Portal" },
				{ "piece_offspring_portal_description", "Routes tamed juveniles and breedable eggs between configured breeding pens." }
			});
		}
	}
	public static class OffspringPortalPrefabs
	{
		private static bool pieceRegistered;

		private static bool retryScheduled;

		public static GameObject Prefab { get; private set; }

		public static bool Registered { get; private set; }

		public static void Initialize()
		{
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefab;
			PrefabManager.OnPrefabsRegistered += RegisterPrefab;
			PieceManager.OnPiecesRegistered += RegisterPiece;
			PrefabManager.OnPrefabsRegistered += RegisterPiece;
		}

		public static void EnsureRegistered()
		{
			RegisterPrefab();
		}

		public static void EnsurePieceRegistered()
		{
			RegisterPiece();
		}

		private static void RegisterPrefab()
		{
			if (Registered)
			{
				return;
			}
			try
			{
				GameObject val = PrefabManager.Instance.CreateClonedPrefab("offspring_portal", "portal_wood");
				if ((Object)(object)val == (Object)null)
				{
					ScheduleRegisterRetry();
					return;
				}
				ConfigureClone(val);
				EnsureRuntimeTriggers(ConvertFromVanillaPortal(val));
				PrefabManager.Instance.AddPrefab(val);
				Prefab = val;
				Registered = true;
				retryScheduled = false;
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefab;
				PrefabManager.OnPrefabsRegistered -= RegisterPrefab;
				OffspringPortalPlugin.Log.LogInfo((object)"Registered offspring_portal prefab (cloned from portal_wood).");
				RegisterPiece();
			}
			catch (Exception arg)
			{
				OffspringPortalPlugin.Log.LogError((object)$"Failed to register offspring_portal prefab: {arg}");
				ScheduleRegisterRetry();
			}
		}

		private static void ScheduleRegisterRetry()
		{
			if (!retryScheduled && !Registered)
			{
				retryScheduled = true;
				((MonoBehaviour)OffspringPortalRuntime.Instance).StartCoroutine(RetryRegisterPrefab());
			}
		}

		private static IEnumerator RetryRegisterPrefab()
		{
			for (int i = 0; i < 600; i++)
			{
				if (Registered)
				{
					break;
				}
				RegisterPrefab();
				if (Registered)
				{
					yield break;
				}
				yield return null;
			}
			retryScheduled = false;
			if (!Registered)
			{
				OffspringPortalPlugin.Log.LogError((object)"Could not register offspring_portal: portal_wood was unavailable after waiting for ZNetScene.");
			}
		}

		internal static bool TryValidateVanillaPortalPrefab(out string message)
		{
			message = null;
			if (!TryResolveVanillaPortalWood(out var vanilla))
			{
				message = "portal_wood was not found in ZNetScene at registration time. Offspring Portal cannot clone the vanilla wood portal.";
				return false;
			}
			if ((Object)(object)vanilla.GetComponent<TeleportWorld>() == (Object)null)
			{
				message = "portal_wood exists but has no TeleportWorld component.";
				return false;
			}
			return true;
		}

		internal static bool TryResolveVanillaPortalWood(out GameObject vanilla)
		{
			vanilla = null;
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				vanilla = ZNetScene.instance.GetPrefab("portal_wood");
			}
			return (Object)(object)vanilla != (Object)null;
		}

		private static void RegisterPiece()
		{
			if (pieceRegistered || !Registered || (Object)(object)Prefab == (Object)null)
			{
				return;
			}
			try
			{
				ApplyRecipe(Prefab);
				ApplyHammerIcon(Prefab);
				PieceManager.Instance.RegisterPieceInPieceTable(Prefab, "Hammer", (string)null);
				pieceRegistered = true;
				PieceManager.OnPiecesRegistered -= RegisterPiece;
				OffspringPortalPlugin.Log.LogInfo((object)"Registered offspring_portal in Hammer piece table.");
			}
			catch (Exception ex)
			{
				OffspringPortalPlugin.Log.LogWarning((object)("Deferring offspring_portal piece registration: " + ex.Message));
			}
		}

		private static void ApplyRecipe(GameObject clone)
		{
			Piece component = clone.GetComponent<Piece>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null))
			{
				component.m_resources = (Requirement[])(object)new Requirement[3]
				{
					CreateRequirement("FineWood", 20),
					CreateRequirement("GreydwarfEye", 10),
					CreateRequirement("SurtlingCore", 2)
				};
			}
		}

		private static void ConfigureClone(GameObject clone)
		{
			//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)
			clone.transform.localScale = Vector3.one * 0.5f;
			Piece component = clone.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "$piece_offspring_portal";
				component.m_description = "$piece_offspring_portal_description";
			}
		}

		internal static OPTeleportWorld ConvertFromVanillaPortal(GameObject gameObject)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Transform proximityRoot = null;
			float exitDistance = 1f;
			float hoverOffset = 0f;
			EffectList connectedVfx = null;
			MeshRenderer model = null;
			Color colorUnconnected = Color.white;
			Color colorTargetfound = Color.white;
			TeleportWorld component = gameObject.GetComponent<TeleportWorld>();
			if ((Object)(object)component != (Object)null)
			{
				proximityRoot = component.m_proximityRoot;
				exitDistance = component.m_exitDistance;
				hoverOffset = component.m_hoverOffset;
				connectedVfx = component.m_connected;
				model = component.m_model;
				colorUnconnected = component.m_colorUnconnected;
				colorTargetfound = component.m_colorTargetfound;
				DestroyPo