Decompiled source of Offspring Portal v0.2.9

OffspringPortal.dll

Decompiled 2 days 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
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("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+7c1d2c20f20282a1313ac0e61abf2255741dfadf")]
[assembly: AssemblyProduct("OffspringPortal")]
[assembly: AssemblyTitle("OffspringPortal")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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(TeleportWorld 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(TeleportWorld portal, Character character, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime)
		{
			//IL_0058: 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_0148: 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;
			}
			if (!ZNet.instance.IsServer())
			{
				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;
			}
			SpeciesType adultSpecies = SpeciesHelper.GetAdultSpecies(character);
			if (!SpeciesHelper.SpeciesMatches(adultSpecies, portalRecord.DeclaredSpecies))
			{
				return false;
			}
			PortalRecord destination;
			switch (portalRecord.AdultDestination)
			{
			case AdultDestination.Farm:
				if (!DestinationRegistry.TryResolveFarmDestination(adultSpecies, out destination))
				{
					string message = "No Farm portal exists.";
					return WarnMissingDestination(time, ref lastNoDestinationMessageTime, message);
				}
				break;
			case AdultDestination.Cull:
				if (!DestinationRegistry.TryResolveCullDestination(out destination))
				{
					string message = "No Cull portal exists.";
					return WarnMissingDestination(time, ref lastNoDestinationMessageTime, message);
				}
				break;
			default:
				return false;
			}
			if (!JuvenileTeleporter.TryTeleport(character, destination, portal))
			{
				OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesCatalog.GetDisplayName(adultSpecies) + " adult."));
				return false;
			}
			OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesCatalog.GetDisplayName(adultSpecies)} adult to {portalRecord.AdultDestination} portal at {destination.Position}.");
			cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value;
			PlayPortalActivation(portal);
			return true;
		}

		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);
			}
			return false;
		}

		private static void PlayPortalActivation(TeleportWorld portal)
		{
			//IL_001b: 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 (portal?.m_connected != null)
			{
				portal.m_connected.Create(((Component)portal).transform.position, ((Component)portal).transform.rotation, ((Component)portal).transform, 1f, -1);
			}
		}
	}
	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, 
				_ => 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:
				return 20f;
			default:
				return 0f;
			}
		}
	}
	public sealed class PortalRecord
	{
		public ZDOID Id;

		public Vector3 Position;

		public PortalRole Role;

		public SpeciesType DeclaredSpecies;

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

		private static readonly Dictionary<SpeciesType, int> MaturingRoundRobinIndex = new Dictionary<SpeciesType, int>();

		private static readonly Dictionary<SpeciesType, int> FarmRoundRobinIndex = new Dictionary<SpeciesType, int>();

		private static int cullRoundRobinIndex;

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

		public static void RegisterOrUpdate(ZDOID id, Vector3 position, PortalRole role, SpeciesType declaredSpecies, 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.DeclaredSpecies = declaredSpecies;
			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_000a: 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)
			if (record != 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 TryResolveDestination(juvenileSpecies, PortalRole.Maturing, MaturingRoundRobinIndex, out destination);
		}

		public static bool TryResolveFarmDestination(SpeciesType adultSpecies, out PortalRecord destination)
		{
			return TryResolveDestination(adultSpecies, 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 HasCullReceiver()
		{
			return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Cull);
		}

		public static bool HasFarmReceiver(SpeciesType maturingReceives)
		{
			if (maturingReceives != SpeciesType.None && maturingReceives != SpeciesType.All && TryResolveFarmDestination(maturingReceives, out var destination))
			{
				return true;
			}
			if (TryResolveFarmDestination(SpeciesType.All, out destination))
			{
				return true;
			}
			if (maturingReceives == SpeciesType.All)
			{
				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_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.EnableCapWarning.Value)
			{
				return;
			}
			foreach (PortalRecord destination in Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Maturing && p.DeclaredSpecies != SpeciesType.All))
			{
				bool flag = GetBreederPortals().Any((PortalRecord source) => Vector3.Distance(source.Position, destination.Position) <= BreedingCapData.GetCapRadius(destination.DeclaredSpecies));
				ZDO zDO = ZDOMan.instance.GetZDO(destination.Id);
				if (zDO != null)
				{
					zDO.Set("op_cap_warning", flag);
				}
			}
		}

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

		private static PortalRecord PickRoundRobin(SpeciesType key, List<PortalRecord> candidates, Dictionary<SpeciesType, 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 JuvenileFollow
	{
		public static bool TryCommand(Character character, Player player, bool showMessage)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!SpeciesHelper.IsEligibleJuvenile(character) || !character.IsTamed())
			{
				return false;
			}
			ZNetView nview = character.GetNview();
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			MonsterAI component = ((Component)character).GetComponent<MonsterAI>();
			Tameable component2 = ((Component)character).GetComponent<Tameable>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)component != (Object)null)
			{
				component2.m_commandable = true;
				if (ZNet.instance.IsServer())
				{
					ApplyMonsterFollowToggle(component2, component, player, showMessage);
					return true;
				}
				component2.Command((Humanoid)(object)player, showMessage);
				return true;
			}
			if ((Object)(object)((Component)character).GetComponent<AnimalAI>() == (Object)null)
			{
				return false;
			}
			JuvenileFollowController.EnsureAttached(character);
			JuvenileFollowRpcHandler.EnsureAttached(character);
			if (ZNet.instance.IsServer())
			{
				return ApplyAnimalFollowToggle(character, player, showMessage);
			}
			((Component)character).GetComponent<JuvenileFollowRpcHandler>()?.RequestToggle(player, showMessage);
			return true;
		}

		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(Tameable tameable, MonsterAI monsterAi, Player player, bool showMessage)
		{
			ZNetView component = ((Component)tameable).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && !component.IsOwner())
			{
				component.ClaimOwnership();
			}
			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, tameable.GetHoverName() + " " + Localization.instance.Localize("$hud_tamestay"), 0, (Sprite)null);
				}
				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, tameable.GetHoverName() + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null);
			}
		}

		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_0093: 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);
				}
			}
			else
			{
				zdo.Set("op_follow_target", zDOID);
				if (showMessage)
				{
					((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null);
				}
			}
			return true;
		}
	}
	public sealed class JuvenileFollowController : MonoBehaviour
	{
		public static bool TryApplyAnimalFollow(AnimalAI animalAi, float dt)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0090: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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 (!ZNet.instance.IsServer() || !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 && !((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 sealed class JuvenileFollowRpcHandler : MonoBehaviour
	{
		private const string ToggleFollowRpc = "op_toggle_follow";

		private ZNetView nview;

		private bool registered;

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

		private void Start()
		{
			TryRegister();
		}

		private void TryRegister()
		{
			if (!registered && !((Object)(object)nview == (Object)null) && nview.IsValid())
			{
				nview.Register<ZDOID, bool>("op_toggle_follow", (Action<long, ZDOID, bool>)RPC_ToggleFollow);
				registered = true;
			}
		}

		public void RequestToggle(Player player, bool showMessage)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			TryRegister();
			if (!((Object)(object)nview == (Object)null) && nview.IsValid() && !((Object)(object)player == (Object)null))
			{
				nview.InvokeRPC("op_toggle_follow", new object[2]
				{
					((Character)player).GetZDOID(),
					showMessage
				});
			}
		}

		private void RPC_ToggleFollow(long sender, ZDOID playerId, bool showMessage)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (ZNet.instance.IsServer())
			{
				Character component = ((Component)this).GetComponent<Character>();
				object obj = Player.GetPlayer(sender);
				if (obj == null)
				{
					GameObject obj2 = ZNetScene.instance.FindInstance(playerId);
					obj = ((obj2 != null) ? obj2.GetComponent<Player>() : null);
				}
				Player val = (Player)obj;
				if (!((Object)(object)component == (Object)null) && !((Object)(object)val == (Object)null))
				{
					JuvenileFollow.ApplyAnimalFollowToggle(component, val, showMessage);
				}
			}
		}

		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<JuvenileFollowRpcHandler>() == (Object)null)
			{
				((Component)character).gameObject.AddComponent<JuvenileFollowRpcHandler>();
			}
		}
	}
	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(TeleportWorld 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(TeleportWorld portal, Character character, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime)
		{
			//IL_0136: 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;
			}
			if (!ZNet.instance.IsServer())
			{
				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;
			}
			SpeciesType juvenileSpecies = SpeciesHelper.GetJuvenileSpecies(character);
			if (!DestinationRegistry.TryResolveMaturingDestination(juvenileSpecies, out var destination))
			{
				if (time - lastNoDestinationMessageTime > 5f)
				{
					lastNoDestinationMessageTime = time;
					OffspringPortalPlugin.Log.LogWarning((object)("No maturing portal registered for " + SpeciesCatalog.GetDisplayName(juvenileSpecies) + "."));
					Player localPlayer = Player.m_localPlayer;
					if ((Object)(object)localPlayer != (Object)null)
					{
						((Character)localPlayer).Message((MessageType)2, "No maturing portal registered for " + SpeciesCatalog.GetDisplayName(juvenileSpecies) + ".", 0, (Sprite)null);
					}
				}
				return false;
			}
			if (!JuvenileTeleporter.TryTeleport(character, destination, portal))
			{
				OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesCatalog.GetDisplayName(juvenileSpecies) + " juvenile."));
				return false;
			}
			OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesCatalog.GetDisplayName(juvenileSpecies)} juvenile to maturing portal at {destination.Position}.");
			cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value;
			PlayPortalActivation(portal);
			return true;
		}

		private static void PlayPortalActivation(TeleportWorld portal)
		{
			//IL_001b: 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 (portal?.m_connected != null)
			{
				portal.m_connected.Create(((Component)portal).transform.position, ((Component)portal).transform.rotation, ((Component)portal).transform, 1f, -1);
			}
		}
	}
	public static class JuvenileTeleporter
	{
		public static bool TryTeleport(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null || !ZNet.instance.IsServer())
			{
				return false;
			}
			DestinationRegistry.RefreshPortalPosition(destination);
			Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal);
			if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(exitPosition))
			{
				return TryTeleportNow(juvenile, destination, sourcePortal);
			}
			if (TryTeleportNow(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."));
			return OffspringPortalRuntime.Instance.TryQueueDistantTeleport(juvenile, destination, sourcePortal);
		}

		public static bool TryTeleportNow(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal, bool allowStoredHeight = false)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null)
			{
				return false;
			}
			if (!ZNet.instance.IsServer())
			{
				return false;
			}
			ZNetView nview = juvenile.GetNview();
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return false;
			}
			nview.ClaimOwnership();
			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);
				}
				return false;
			}
			JuvenileGroundSnapper.EnsureAttached(juvenile);
			JuvenileFollowController.EnsureAttached(juvenile);
			JuvenileFollowRpcHandler.EnsureAttached(juvenile);
			ZDO zDO = nview.GetZDO();
			if (zDO != null)
			{
				zDO.Set("op_transported", true);
			}
			return true;
		}

		public static Vector3 ResolveDestinationPosition(PortalRecord destination, TeleportWorld 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, TeleportWorld 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 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 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 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).");
			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.");
		}
	}
	public class OffspringPortalMarker : MonoBehaviour
	{
		private TeleportWorld teleportWorld;

		private void Awake()
		{
			teleportWorld = ((Component)this).GetComponent<TeleportWorld>();
		}

		private void Start()
		{
			if ((Object)(object)teleportWorld != (Object)null && !((Behaviour)teleportWorld).enabled)
			{
				((MonoBehaviour)this).StartCoroutine(InitializeTeleportWorldWhenReady());
			}
		}

		private IEnumerator InitializeTeleportWorldWhenReady()
		{
			ZNetView nview = ((Component)this).GetComponent<ZNetView>();
			for (int i = 0; i < 30; i++)
			{
				if ((Object)(object)nview != (Object)null && nview.GetZDO() != null)
				{
					break;
				}
				yield return null;
			}
			if (!((Object)(object)teleportWorld == (Object)null) && !((Object)(object)nview == (Object)null) && nview.GetZDO() != null && !((Behaviour)teleportWorld).enabled)
			{
				OffspringPortalInitializer.CompleteTeleportWorldAwake(teleportWorld, nview);
			}
		}
	}
	internal static class OffspringPortalInitializer
	{
		internal static void CompleteTeleportWorldAwake(TeleportWorld portal, ZNetView nview)
		{
			if (!((Behaviour)portal).enabled)
			{
				Traverse.Create((object)portal).Field<ZNetView>("m_nview").Value = nview;
				Traverse.Create((object)portal).Field<bool>("m_hadTarget").Value = (bool)AccessTools.Method(typeof(TeleportWorld), "HaveTarget", (Type[])null, (Type[])null).Invoke(portal, null);
				nview.Register<string, string>("RPC_SetTag", (Action<long, string, string>)delegate(long sender, string tag, string target)
				{
					AccessTools.Method(typeof(TeleportWorld), "RPC_SetTag", (Type[])null, (Type[])null).Invoke(portal, new object[3] { sender, tag, target });
				});
				nview.Register<ZDOID>("RPC_SetConnected", (Action<long, ZDOID>)delegate(long sender, ZDOID targetId)
				{
					//IL_002d: Unknown result type (might be due to invalid IL or missing references)
					AccessTools.Method(typeof(TeleportWorld), "RPC_SetConnected", (Type[])null, (Type[])null).Invoke(portal, new object[2] { sender, targetId });
				});
				((Behaviour)portal).enabled = true;
				((MonoBehaviour)portal).InvokeRepeating("UpdatePortal", 0.5f, 0.5f);
			}
		}
	}
	public static class OffspringPortalPrefabs
	{
		private static bool pieceRegistered;

		public static GameObject Prefab { get; private set; }

		public static bool Registered { get; private set; }

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

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

		private static void RegisterPrefab()
		{
			if (!Registered)
			{
				GameObject val = PrefabManager.Instance.CreateClonedPrefab("offspring_portal", "portal_wood");
				if ((Object)(object)val == (Object)null)
				{
					OffspringPortalPlugin.Log.LogError((object)"Failed to clone portal_wood via Jotunn.");
					return;
				}
				ConfigureClone(val);
				EnsureRuntimeTriggers(val.GetComponent<TeleportWorld>());
				PrefabManager.Instance.AddPrefab(val);
				Prefab = val;
				Registered = true;
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefab;
				OffspringPortalPlugin.Log.LogInfo((object)"Registered offspring_portal prefab.");
				RegisterPiece();
			}
		}

		private static void RegisterPiece()
		{
			if (pieceRegistered || !Registered || (Object)(object)Prefab == (Object)null)
			{
				return;
			}
			try
			{
				ApplyRecipe(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;
			TeleportWorld component = clone.GetComponent<TeleportWorld>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_exitDistance = 1f;
			}
			EnsureRuntimeTriggers(component);
			if ((Object)(object)clone.GetComponent<OffspringPortalMarker>() == (Object)null)
			{
				clone.AddComponent<OffspringPortalMarker>();
			}
			Piece component2 = clone.GetComponent<Piece>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_name = "$piece_offspring_portal";
				component2.m_description = "$piece_offspring_portal_description";
			}
		}

		public static void EnsureRuntimeTriggers(TeleportWorld teleportWorld)
		{
			if ((Object)(object)teleportWorld == (Object)null)
			{
				return;
			}
			TeleportWorldTrigger[] componentsInChildren = ((Component)teleportWorld).GetComponentsInChildren<TeleportWorldTrigger>(true);
			foreach (TeleportWorldTrigger obj in componentsInChildren)
			{
				GameObject gameObject = ((Component)obj).gameObject;
				((Behaviour)obj).enabled = false;
				if ((Object)(object)gameObject.GetComponent<OffspringPortalTrigger>() == (Object)null)
				{
					gameObject.AddComponent<OffspringPortalTrigger>();
				}
			}
			if ((Object)(object)teleportWorld.m_proximityRoot == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren2 = ((Component)teleportWorld.m_proximityRoot).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren2)
			{
				if (val.isTrigger && !((Object)(object)((Component)val).GetComponent<OffspringPortalTrigger>() != (Object)null))
				{
					((Component)val).gameObject.AddComponent<OffspringPortalTrigger>();
				}
			}
			if ((Object)(object)((Component)teleportWorld).GetComponent<OffspringPortalScanner>() == (Object)null)
			{
				((Component)teleportWorld).gameObject.AddComponent<OffspringPortalScanner>();
			}
		}

		private static Requirement CreateRequirement(string itemName, int amount)
		{
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			ObjectDB instance = ObjectDB.instance;
			GameObject val = ((instance != null) ? instance.GetItemPrefab(itemName) : null);
			return new Requirement
			{
				m_resItem = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null),
				m_amount = amount,
				m_amountPerLevel = 0,
				m_recover = true
			};
		}

		public static bool IsOffspringPortal(TeleportWorld portal)
		{
			if ((Object)(object)portal == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)portal).GetComponent<OffspringPortalMarker>() != (Object)null)
			{
				return true;
			}
			if (IsOffspringPiece(((Component)portal).gameObject))
			{
				return true;
			}
			ZNetView component = ((Component)portal).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || component.GetZDO() == null)
			{
				return false;
			}
			ZDO zDO = component.GetZDO();
			if (zDO.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal"))
			{
				return true;
			}
			return !string.IsNullOrEmpty(zDO.GetString("op_portal_role", string.Empty));
		}

		public static bool IsOffspringPortal(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			if ((Object)(object)gameObject.GetComponent<OffspringPortalMarker>() != (Object)null)
			{
				return true;
			}
			if (IsOffspringPiece(gameObject))
			{
				return true;
			}
			return IsOffspringPortal(gameObject.GetComponent<TeleportWorld>());
		}

		public static void EnsureIdentity(TeleportWorld portal)
		{
			if (!((Object)(object)portal == (Object)null) && IsOffspringPiece(((Component)portal).gameObject) && (Object)(object)((Component)portal).GetComponent<OffspringPortalMarker>() == (Object)null)
			{
				((Component)portal).gameObject.AddComponent<OffspringPortalMarker>();
			}
		}

		private static bool IsOffspringPiece(GameObject gameObject)
		{
			Piece component = gameObject.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				return component.m_name == "$piece_offspring_portal";
			}
			return false;
		}
	}
	public sealed class OffspringPortalRuntime : MonoBehaviour
	{
		private static OffspringPortalRuntime instance;

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

		public static OffspringPortalRuntime Instance
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Expected O, but got Unknown
				if ((Object)(object)instance == (Object)null)
				{
					GameObject val = new GameObject("OffspringPortal_Runtime");
					Object.DontDestroyOnLoad((Object)val);
					instance = val.AddComponent<OffspringPortalRuntime>();
				}
				return instance;
			}
		}

		public bool TryQueueDistantTeleport(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = juvenile?.GetNview();
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return false;
			}
			ZDOID uid = val.GetZDO().m_uid;
			if (pendingTeleports.Contains(uid))
			{
				return false;
			}
			pendingTeleports.Add(uid);
			((MonoBehaviour)this).StartCoroutine(DeferredTeleport(juvenile, destination, sourcePortal, uid));
			return true;
		}

		private IEnumerator DeferredTeleport(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal, ZDOID juvenileId)
		{
			//IL_0023: 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)
			float timeout = ModConfig.DistantTeleportTimeoutSec.Value;
			float elapsed = 0f;
			Vector3 targetPos = JuvenileTeleporter.ResolveDestinationPosition(destination, sourcePortal);
			while (elapsed < timeout)
			{
				if ((Object)(object)juvenile == (Object)null)
				{
					pendingTeleports.Remove(juvenileId);
					yield break;
				}
				if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(targetPos) && JuvenileTeleporter.TryTeleportNow(juvenile, destination, sourcePortal))
				{
					pendingTeleports.Remove(juvenileId);
					yield break;
				}
				elapsed += 0.25f;
				yield return (object)new WaitForSeconds(0.25f);
			}
			if ((Object)(object)juvenile != (Object)null && JuvenileTeleporter.TryTeleportNow(juvenile, destination, sourcePortal, allowStoredHeight: true))
			{
				pendingTeleports.Remove(juvenileId);
				yield break;
			}
			pendingTeleports.Remove(juvenileId);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)2, "Could not reach distant pen for " + SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile)) + ".", 0, (Sprite)null);
			}
		}
	}
	public class OffspringPortalScanner : MonoBehaviour
	{
		private TeleportWorld portal;

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

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

		private float lastNoJuvenileDestinationMessageTime;

		private float lastNoAdultDestinationMessageTime;

		private void Start()
		{
			portal = ((Component)this).GetComponent<TeleportWorld>();
			float value = ModConfig.BreederScanIntervalSec.Value;
			((MonoBehaviour)this).InvokeRepeating("ScanForJuveniles", value, value);
			float value2 = ModConfig.MaturingAdultScanIntervalSec.Value;
			((MonoBehaviour)this).InvokeRepeating("ScanForAdults", value2, value2);
		}

		private void ScanForJuveniles()
		{
			if (ZNet.instance.IsServer() && !((Object)(object)portal == (Object)null) && OffspringPortalPrefabs.IsOffspringPortal(portal) && JuvenilePortalRouter.IsBreederPortal(portal))
			{
				ScanNearbyCharacters((Character character, Dictionary<int, float> cooldowns) => JuvenilePortalRouter.TryRoute(portal, character, cooldowns, ref lastNoJuvenileDestinationMessageTime), juvenileCooldowns);
			}
		}

		private void ScanForAdults()
		{
			if (ZNet.instance.IsServer() && !((Object)(object)portal == (Object)null) && OffspringPortalPrefabs.IsOffspringPortal(portal) && AdultPortalRouter.IsAdultRoutingMaturingPortal(portal))
			{
				ScanNearbyCharacters((Character character, Dictionary<int, float> cooldowns) => AdultPortalRouter.TryRoute(portal, character, cooldowns, ref lastNoAdultDestinationMessageTime), adultCooldowns);
			}
		}

		private void ScanNearbyCharacters(Func<Character, Dictionary<int, float>, bool> tryRoute, Dictionary<int, float> cooldowns)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//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_007a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (((Object)(object)portal.m_proximityRoot != (Object)null) ? portal.m_proximityRoot.position : ((Component)portal).transform.position);
			float value = ModConfig.BreederScanRange.Value;
			float num = value * value;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer())
				{
					Vector3 val2 = ((Component)allCharacter).transform.position - val;
					if (!(((Vector3)(ref val2)).sqrMagnitude > num))
					{
						tryRoute(allCharacter, cooldowns);
					}
				}
			}
		}
	}
	public class OffspringPortalTrigger : MonoBehaviour
	{
		private TeleportWorld portal;

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

		private float lastNoDestinationMessageTime;

		private void Awake()
		{
			portal = ((Component)this).GetComponentInParent<TeleportWorld>();
		}

		private void OnTriggerEnter(Collider other)
		{
			if ((Object)(object)portal == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				return;
			}
			Character character = GetCharacter(other);
			Player val = (Player)(object)((character is Player) ? character : null);
			if (val != null)
			{
				if ((Object)(object)val == (Object)(object)Player.m_localPlayer)
				{
					((Character)val).Message((MessageType)2, "Offspring portals route juveniles only. Use a standard portal to travel.", 0, (Sprite)null);
				}
			}
			else
			{
				TryRouteJuvenile(other);
			}
		}

		private void OnTriggerStay(Collider other)
		{
			if (!(GetCharacter(other) is Player))
			{
				TryRouteJuvenile(other);
			}
		}

		private void TryRouteJuvenile(Collider other)
		{
			if (!((Object)(object)portal == (Object)null) && OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				Character character = GetCharacter(other);
				if (!((Object)(object)character == (Object)null))
				{
					JuvenilePortalRouter.TryRoute(portal, character, cooldowns, ref lastNoDestinationMessageTime);
				}
			}
		}

		private static Character GetCharacter(Collider other)
		{
			Character component = ((Component)other).GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			if ((Object)(object)other.attachedRigidbody != (Object)null)
			{
				component = ((Component)other.attachedRigidbody).GetComponent<Character>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			return ((Component)other).GetComponentInParent<Character>();
		}
	}
	[BepInPlugin("offspringportal.mod", "Offspring Portal", "0.2.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class OffspringPortalPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "offspringportal.mod";

		public const string PluginName = "Offspring Portal";

		public const string PluginVersion = "0.2.9";

		internal static ManualLogSource Log;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			OffspringPortalPrefabs.Initialize();
			_ = OffspringPortalRuntime.Instance;
			harmony = new Harmony("offspringportal.mod");
			harmony.PatchAll(typeof(OffspringPortalPlugin).Assembly);
			XPortalCompat.TryApply(harmony);
			Log.LogInfo((object)"Offspring Portal 0.2.9 loaded.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	public static class PortalDisplayHelper
	{
		public const string UnnamedDisplay = "(No Name)";

		public const int MaxNameLength = 32;

		public static string SanitizeName(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return string.Empty;
			}
			name = name.Trim();
			if (name.Length > 32)
			{
				return name.Substring(0, 32);
			}
			return name;
		}

		public static string GetDisplayName(ZDO zdo)
		{
			if (zdo == null)
			{
				return "(No Name)";
			}
			string text = SanitizeName(zdo.GetString("op_portal_name", string.Empty));
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
			return "(No Name)";
		}

		public static string GetDetailLine(PortalRole role, SpeciesType species, AdultDestination adultDestination)
		{
			switch (role)
			{
			case PortalRole.Maturing:
			{
				string text = "Receives: " + SpeciesCatalog.GetDisplayName(species) + " juveniles";
				if (adultDestination != AdultDestination.None)
				{
					text = text + "\nDestination: " + PortalRoleCatalog.GetDisplayName(adultDestination);
				}
				return text;
			}
			case PortalRole.Farm:
				return "Receives: " + SpeciesCatalog.GetDisplayName(species) + " adults";
			case PortalRole.Cull:
				return "Role: Cull yard";
			default:
				return "Role: Breeder";
			}
		}

		public static string GetHoverText(ZDO zdo, PortalRole role, SpeciesType species, AdultDestination adultDestination, bool capWarning)
		{
			string displayName = GetDisplayName(zdo);
			string detailLine = GetDetailLine(role, species, adultDestination);
			string text = BuildWarnings(role, species, adultDestination, capWarning);
			return Localization.instance.Localize("Name: " + displayName + "\n" + detailLine + text + "\n[<color=yellow><b>$KEY_Use</b></color>] Configure");
		}

		private static string BuildWarnings(PortalRole role, SpeciesType species, AdultDestination adultDestination, bool capWarning)
		{
			string text = string.Empty;
			if (capWarning)
			{
				text += "\n<color=yellow>Warning: maturing pen is within breeding cap radius of a breeder portal.</color>";
			}
			if (role == PortalRole.Maturing && adultDestination != AdultDestination.None && ((adultDestination == AdultDestination.Cull) ? (!DestinationRegistry.HasCullReceiver()) : (!DestinationRegistry.HasFarmReceiver(species))))
			{
				string displayName = PortalRoleCatalog.GetDisplayName(adultDestination);
				text = text + "\n<color=yellow>Warning: No " + displayName + " portal exists. Adults will not be teleported.</color>";
			}
			return text;
		}
	}
	public static class PortalHelper
	{
		public static bool TryGetPortal(TeleportWorld portal, out ZDOID id, out Vector3 position, out SpeciesType species)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			id = ZDOID.None;
			position = Vector3.zero;
			species = SpeciesType.None;
			if ((Object)(object)portal == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				return false;
			}
			ZNetView component = ((Component)portal).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val == null)
			{
				return false;
			}
			id = val.m_uid;
			position = val.GetPosition();
			species = SpeciesCatalog.FromStorageValue(val.GetString("op_declared_species", string.Empty));
			return true;
		}

		public static void SyncRegistryFromPortal(TeleportWorld portal)
		{
			ZNetView obj = ((portal != null) ? ((Component)portal).GetComponent<ZNetView>() : null);
			ZDO val = ((obj != null) ? obj.GetZDO() : null);
			if (val != null && OffspringPortalPrefabs.IsOffspringPortal(portal))
			{
				SyncRegistryFromZdo(val);
				PortalTravelGuard.ClearTravelBindings(val);
				DestinationRegistry.RefreshCapWarnings();
			}
		}

		public static void SyncRegistryFromZdo(ZDO zdo)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (zdo != null && zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal"))
			{
				PortalRole role = PortalRoleCatalog.FromZdo(zdo);
				SpeciesType declaredSpecies = SpeciesCatalog.FromStorageValue(zdo.GetString("op_declared_species", string.Empty));
				AdultDestination adultDestination = PortalRoleCatalog.GetAdultDestination(zdo);
				DestinationRegistry.RegisterOrUpdate(zdo.m_uid, zdo.GetPosition(), role, declaredSpecies, adultDestination);
			}
		}

		public static void RebuildRegistryFromWorld()
		{
			DestinationRegistry.Clear();
			RebuildRegistryFromLoadedPortals();
			RebuildRegistryFromAllPortalZdos();
			DestinationRegistry.RefreshCapWarnings();
			LogRegistryState("rebuilt");
		}

		private static void LogRegistryState(string reason)
		{
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			using (IEnumerator<PortalRecord> enumerator = DestinationRegistry.GetAll().GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					switch (enumerator.Current.Role)
					{
					case PortalRole.Maturing:
						num2++;
						break;
					case PortalRole.Farm:
						num3++;
						break;
					case PortalRole.Cull:
						num4++;
						break;
					default:
						num++;
						break;
					}
				}
			}
			OffspringPortalPlugin.Log.LogInfo((object)$"Portal registry {reason}: {num} breeder(s), {num2} maturing, {num3} farm, {num4} cull.");
		}

		private static void RebuildRegistryFromLoadedPortals()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
			foreach (TeleportWorld portal in array)
			{
				if (OffspringPortalPrefabs.IsOffspringPortal(portal))
				{
					SyncRegistryFromPortal(portal);
				}
			}
		}

		private static void RebuildRegistryFromAllPortalZdos()
		{
			if (ZDOMan.instance == null)
			{
				return;
			}
			List<ZDO> list = new List<ZDO>();
			int num = 0;
			while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("offspring_portal", list, ref num))
			{
			}
			foreach (ZDO item in list)
			{
				SyncRegistryFromZdo(item);
			}
		}
	}
	public static class PortalPlacement
	{
		public const float PortalScale = 0.5f;

		public const float ScaledExitDistance = 1f;

		public static Vector3 GetExitPosition(ZDOID portalId, TeleportWorld fallbackPortal = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001e: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_00b6: 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_00b8: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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)
			Vector3 val = Vector3.zero;
			Quaternion val2 = Quaternion.identity;
			float num = 1f;
			ZDOMan instance = ZDOMan.instance;
			ZDO val3 = ((instance != null) ? instance.GetZDO(portalId) : null);
			if (val3 != null)
			{
				val = val3.GetPosition();
				val2 = val3.GetRotation();
			}
			else if ((Object)(object)fallbackPortal != (Object)null)
			{
				val = ((Component)fallbackPortal).transform.position;
				val2 = ((Component)fallbackPortal).transform.rotation;
				num = fallbackPortal.m_exitDistance;
			}
			ZNetScene instance2 = ZNetScene.instance;
			GameObject val4 = ((instance2 != null) ? instance2.FindInstance(portalId) : null);
			TeleportWorld val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<TeleportWorld>() : null);
			if ((Object)(object)val5 != (Object)null)
			{
				val = ((Component)val5).transform.position;
				val2 = ((Component)val5).transform.rotation;
				num = val5.m_exitDistance;
			}
			return val + val2 * Vector3.forward * num;
		}

		public static Quaternion GetExitRotation(ZDOID portalId, TeleportWorld fallbackPortal = null)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan instance = ZDOMan.instance;
			ZDO val = ((instance != null) ? instance.GetZDO(portalId) : null);
			if (val != null)
			{
				return val.GetRotation();
			}
			ZNetScene instance2 = ZNetScene.instance;
			GameObject val2 = ((instance2 != null) ? instance2.FindInstance(portalId) : null);
			TeleportWorld val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<TeleportWorld>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return ((Component)val3).transform.rotation;
			}
			if (!((Object)(object)fallbackPortal != (Object)null))
			{
				return Quaternion.identity;
			}
			return ((Component)fallbackPortal).transform.rotation;
		}
	}
	public enum PortalRole
	{
		Breeder,
		Maturing,
		Farm,
		Cull
	}
	public enum AdultDestination
	{
		None,
		Farm,
		Cull
	}
	public static class PortalRoleCatalog
	{
		public static PortalRole FromZdo(ZDO zdo)
		{
			if (zdo == null)
			{
				return PortalRole.Breeder;
			}
			string value = zdo.GetString("op_portal_role", string.Empty);
			if (!string.IsNullOrWhiteSpace(value) && Enum.TryParse<PortalRole>(value, ignoreCase: true, out var result))
			{
				return result;
			}
			if (SpeciesCatalog.FromStorageValue(zdo.GetString("op_declared_species", string.Empty)) != SpeciesType.None)
			{
				return PortalRole.Maturing;
			}
			return PortalRole.Breeder;
		}

		public static AdultDestination GetAdultDestination(ZDO zdo)
		{
			if (zdo == null)
			{
				return AdultDestination.None;
			}
			string value = zdo.GetString("op_adult_destination", string.Empty);
			if (!string.IsNullOrWhiteSpace(value) && Enum.TryParse<AdultDestination>(value, ignoreCase: true, out var result))
			{
				return result;
			}
			if (!zdo.GetBool("op_forward_adults", false))
			{
				return AdultDestination.None;
			}
			return AdultDestination.Cull;
		}

		public static string ToStorageValue(PortalRole role)
		{
			return role.ToString();
		}

		public static string ToStorageValue(AdultDestination destination)
		{
			return destination.ToString();
		}

		public static string GetDisplayName(PortalRole role)
		{
			return role switch
			{
				PortalRole.Maturing => "Maturing", 
				PortalRole.Farm => "Farm", 
				PortalRole.Cull => "Cull", 
				_ => "Breeder", 
			};
		}

		public static string GetDisplayName(AdultDestination destination)
		{
			return destination.ToString();
		}

		public static SpeciesType ResolveSpecies(PortalRole role, SpeciesType selectedSpecies)
		{
			if (role != PortalRole.Breeder && role != PortalRole.Cull)
			{
				return selectedSpecies;
			}
			return SpeciesType.None;
		}

		public static AdultDestination ResolveAdultDestination(PortalRole role, AdultDestination selectedDestination)
		{
			if (role != PortalRole.Maturing)
			{
				return AdultDestination.None;
			}
			return selectedDestination;
		}

		public static string GetConfiguredMessage(PortalRole role, SpeciesType species, AdultDestination adultDestination)
		{
			switch (role)
			{
			case PortalRole.Maturing:
			{
				string text = "Maturing (receives " + SpeciesCatalog.GetDisplayName(species) + ")";
				if (adultDestination != AdultDestination.None)
				{
					return text + ", destination " + GetDisplayName(adultDestination);
				}
				return text;
			}
			case PortalRole.Farm:
				return "Farm (receives " + SpeciesCatalog.GetDisplayName(species) + " adults)";
			case PortalRole.Cull:
				return "Cull yard";
			default:
				return "Breeder";
			}
		}
	}
	public static class PortalRpc
	{
		private const string RpcSetConfig = "OffspringPortal_SetConfigV3";

		public static void Register()
		{
			ZRoutedRpc.instance.Register<ZDOID, string, string, string, string>("OffspringPortal_SetConfigV3", (Method<ZDOID, string, string, string, string>)OnSetConfigRpc);
		}

		public static void SetPortalConfig(ZDOID portalId, PortalRole role, SpeciesType species, string name, AdultDestination adultDestination)
		{
			//IL_0039: 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)
			string text = PortalDisplayHelper.SanitizeName(name);
			AdultDestination adultDestination2 = PortalRoleCatalog.ResolveAdultDestination(role, adultDestination);
			if (ZNet.instance.IsServer())
			{
				ApplyPortalConfig(portalId, role, species, text, adultDestination2);
				return;
			}
			ZRoutedRpc.instance.InvokeRoutedRPC("OffspringPortal_SetConfigV3", new object[5]
			{
				portalId,
				PortalRoleCatalog.ToStorageValue(role),
				SpeciesCatalog.ToStorageValue(species),
				text,
				PortalRoleCatalog.ToStorageValue(adultDestination2)
			});
		}

		private static void OnSetConfigRpc(long sender, ZDOID portalId, string roleValue, string speciesValue, string name, string adultDestinationValue)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (ZNet.instance.IsServer())
			{
				PortalRole result;
				PortalRole role = (Enum.TryParse<PortalRole>(roleValue, ignoreCase: true, out result) ? result : PortalRole.Breeder);
				AdultDestination result2;
				AdultDestination adultDestination = (Enum.TryParse<AdultDestination>(adultDestinationValue, ignoreCase: true, out result2) ? result2 : AdultDestination.None);
				ApplyPortalConfig(portalId, role, SpeciesCatalog.FromStorageValue(speciesValue), PortalDisplayHelper.SanitizeName(name), adultDestination);
			}
		}

		private static void ApplyPortalConfig(ZDOID portalId, PortalRole role, SpeciesType species, string name, AdultDestination adultDestination)
		{
			//IL_0005: 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_0077: 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)
			ZDO zDO = ZDOMan.instance.GetZDO(portalId);
			if (zDO != null)
			{
				SpeciesType speciesType = PortalRoleCatalog.ResolveSpecies(role, species);
				AdultDestination adultDestination2 = PortalRoleCatalog.ResolveAdultDestination(role, adultDestination);
				zDO.Set("op_portal_role", PortalRoleCatalog.ToStorageValue(role));
				zDO.Set("op_declared_species", SpeciesCatalog.ToStorageValue(speciesType));
				zDO.Set("op_portal_name", name);
				zDO.Set("op_adult_destination", PortalRoleCatalog.ToStorageValue(adultDestination2));
				zDO.Set("op_forward_adults", adultDestination2 == AdultDestination.Cull);
				PortalTravelGuard.ClearTravelBindings(zDO);
				DestinationRegistry.RegisterOrUpdate(portalId, zDO.GetPosition(), role, speciesType, adultDestination2);
				DestinationRegistry.RefreshCapWarnings();
				if ((Object)(object)FindPortal(portalId) != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					string text = (string.IsNullOrEmpty(name) ? "(No Name)" : name);
					string configuredMessage = PortalRoleCatalog.GetConfiguredMessage(role, speciesType, adultDestination2);
					((Character)Player.m_localPlayer).Message((MessageType)1, "Portal \"" + text + "\" configured as " + configuredMessage + ".", 0, (Sprite)null);
				}
			}
		}

		private static TeleportWorld FindPortal(ZDOID portalId)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ZDOMan.instance.GetZDO(portalId);
			if (zDO == null)
			{
				return null;
			}
			ZNetView val = ZNetScene.instance.FindInstance(zDO);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<TeleportWorld>();
		}
	}
	public static class PortalTravelGuard
	{
		public const string PlayerTravelBlockedMessage = "Offspring portals route juveniles only. Use a standard portal to travel.";

		private const string XPortalTargetField = "XPortal_TargetId";

		private const string XPortalPreviousField = "XPortal_PreviousId";

		public static bool IsOffspringPortalZdo(ZDO zdo)
		{
			if (zdo == null)
			{
				return false;
			}
			if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal"))
			{
				return true;
			}
			return !string.IsNullOrEmpty(zdo.GetString("op_portal_role", string.Empty));
		}

		public static bool TryGetConnectedPortal(TeleportWorld portal, out TeleportWorld connected)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			connected = null;
			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;
			}
			ZDOID connectionZDOID = val.GetConnectionZDOID((ConnectionType)1);
			if (connectionZDOID == ZDOID.None)
			{
				return false;
			}
			ZNetScene instance = ZNetScene.instance;
			GameObject val2 = ((instance != null) ? instance.FindInstance(connectionZDOID) : null);
			connected = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<TeleportWorld>() : null);
			return (Object)(object)connected != (Object)null;
		}

		public static bool BlocksPlayerTravel(TeleportWorld source, Player player, out string message)
		{
			message = null;
			if ((Object)(object)source == (Object)null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (OffspringPortalPrefabs.IsOffspringPortal(source))
			{
				message = "Offspring portals route juveniles only. Use a standard portal to travel.";
				return true;
			}
			if (TryGetConnectedPortal(source, out var connected) && OffspringPortalPrefabs.IsOffspringPortal(connected))
			{
				message = "Offspring portals route juveniles only. Use a standard portal to travel.";
				return true;
			}
			return false;
		}

		public static void ClearTravelBindings(ZDO zdo)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (zdo != null)
			{
				zdo.UpdateConnection((ConnectionType)1, ZDOID.None);
				zdo.Set("XPortal_TargetId", ZDOID.None);
				zdo.Set("XPortal_PreviousId", ZDOID.None);
			}
		}

		public static void ClearTravelBindings(TeleportWorld portal)
		{
			if (!((Object)(object)portal == (Object)null) && ZNet.instance.IsServer())
			{
				ZNetView component = ((Component)portal).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				if (val != null && component.IsOwner())
				{
					ClearTravelBindings(val);
				}
			}
		}

		public static void ClearAllOffspringTravelBindings()
		{
			if (!ZNet.instance.IsServer())
			{
				return;
			}
			TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
			foreach (TeleportWorld portal in array)
			{
				if (OffspringPortalPrefabs.IsOffspringPortal(portal))
				{
					ClearTravelBindings(portal);
				}
			}
		}
	}
	public static class SpeciesHelper
	{
		private static readonly Dictionary<string, SpeciesType> AdultPrefabMap = new Dictionary<string, SpeciesType>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"Boar",
				SpeciesType.Boar
			},
			{
				"Wolf",
				SpeciesType.Wolf
			},
			{
				"WolfCub",
				SpeciesType.Wolf
			},
			{
				"Lox",
				SpeciesType.Lox
			},
			{
				"Hen",
				SpeciesType.Chicken
			},
			{
				"Chicken",
				SpeciesType.Chicken
			},
			{
				"Asksvin",
				SpeciesType.Asksvin
			}
		};

		public static bool IsEligibleJuvenile(Character character)
		{
			if ((Object)(object)character == (Object)null || !character.IsTamed())
			{
				return false;
			}
			if ((Object)(object)((Component)character).GetComponent<Growup>() != (Object)null)
			{
				return true;
			}
			return (((Object)character).name ?? string.Empty).IndexOf("wolfcub", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		public static bool IsEligibleAdult(Character character)
		{
			if ((Object)(object)character != (Object)null && character.IsTamed() && (Object)(object)((Component)character).GetComponent<Growup>() == (Object)null)
			{
				return GetAdultSpecies(character) != SpeciesType.None;
			}
			return false;
		}

		public static SpeciesType GetAdultSpecies(Character character)
		{
			return MapAdultPrefab((character != null) ? ((Object)character).name : null);
		}

		public static SpeciesType GetJuvenileSpecies(Character character)
		{
			Growup component = ((Component)character).GetComponent<Growup>();
			if ((Object)(object)component == (Object)null)
			{
				return SpeciesType.None;
			}
			if ((Object)(object)component.m_grownPrefab != (Object)null)
			{
				SpeciesType speciesType = MapAdultPrefab(((Object)component.m_grownPrefab).name);
				if (speciesType != SpeciesType.None)
				{
					return speciesType;
				}
			}
			if (component.m_altGrownPrefabs != null)
			{
				foreach (GrownEntry altGrownPrefab in component.m_altGrownPrefabs)
				{
					if (!((Object)(object)altGrownPrefab?.m_prefab == (Object)null))
					{
						SpeciesType speciesType2 = MapAdultPrefab(((Object)altGrownPrefab.m_prefab).name);
						if (speciesType2 != SpeciesType.None)
						{
							return speciesType2;
						}
					}
				}
			}
			return MapAdultPrefab(((Object)character).name);
		}

		public static bool SpeciesMatches(SpeciesType juvenile, SpeciesType destination)
		{
			return destination switch
			{
				SpeciesType.None => false, 
				SpeciesType.All => true, 
				_ => juvenile == destination, 
			};
		}

		private static SpeciesType MapAdultPrefab(string prefabName)
		{
			if (string.IsNullOrWhiteSpace(prefabName))
			{
				return SpeciesType.None;
			}
			foreach (KeyValuePair<string, SpeciesType> item in AdultPrefabMap)
			{
				if (prefabName.IndexOf(item.Key, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return item.Value;
				}
			}
			return SpeciesType.None;
		}
	}
	public enum SpeciesType
	{
		None,
		All,
		Boar,
		Wolf,
		Lox,
		Chicken,
		Asksvin
	}
	public static class SpeciesCatalog
	{
		public static readonly IReadOnlyList<SpeciesType> DestinationOptions = new SpeciesType[6]
		{
			SpeciesType.Boar,
			SpeciesType.Wolf,
			SpeciesType.Lox,
			SpeciesType.Chicken,
			SpeciesType.Asksvin,
			SpeciesType.All
		};

		public static string ToStorageValue(SpeciesType species)
		{
			if (species != SpeciesType.None)
			{
				return species.ToString();
			}
			return string.Empty;
		}

		public static SpeciesType FromStorageValue(string value)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return SpeciesType.None;
			}
			if (!Enum.TryParse<SpeciesType>(value, ignoreCase: true, out var result))
			{
				return SpeciesType.None;
			}
			return result;
		}

		public static string GetDisplayName(SpeciesType species)
		{
			return species switch
			{
				SpeciesType.All => "All", 
				SpeciesType.Boar => "Boar", 
				SpeciesType.Wolf => "Wolf", 
				SpeciesType.Lox => "Lox", 
				SpeciesType.Chicken => "Hen", 
				SpeciesType.Asksvin => "Asksvin", 
				_ => "Breeder", 
			};
		}
	}
	internal static class ValheimExtensions
	{
		public static ZNetView GetNview(this Character character)
		{
			if (!((Object)(object)character != (Object)null))
			{
				return null;
			}
			return ((Component)character).GetComponent<ZNetView>();
		}

		public static ZDO GetZdo(this Character character)
		{
			ZNetView nview = character.GetNview();
			if (!((Object)(object)nview != (Object)null))
			{
				return null;
			}
			return nview.GetZDO();
		}
	}
	internal static class XPortalCompat
	{
		public static void TryApply(Harmony harmony)
		{
			Type type = AccessTools.TypeByName("XPortal.XPortal");
			if (!(type == null))
			{
				Patch(harmony, type, "OnPrePortalHover", "OnPrePortalHoverPrefix");
				Patch(harmony, type, "OnPortalPlaced", "OnPortalPlacedPrefix");
				Patch(harmony, type, "OnPortalRequestText", "OnPortalRequestTextPrefix");
				OffspringPortalPlugin.Log.LogInfo((object)"XPortal compatibility enabled: offspring portals excluded from travel network.");
			}
		}

		private static void Patch(Harmony harmony, Type targetType, string methodName, string handlerName)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(XPortalCompat), handlerName, (Type[])null, (Type[])null);
			if (!(methodInfo == null) && !(methodInfo2 == null))
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static bool ShouldBlock(ZDOID portalId)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan instance = ZDOMan.instance;
			return PortalTravelGuard.IsOffspringPortalZdo((instance != null) ? instance.GetZDO(portalId) : null);
		}

		private static bool OnPrePortalHoverPrefix(ZDOID portalId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return !ShouldBlock(portalId);
		}

		private static bool OnPortalPlacedPrefix(ZDOID portalId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (!ShouldBlock(portalId))
			{
				return true;
			}
			PortalTravelGuard.ClearTravelBindings(FindPortal(portalId));
			return false;
		}

		private static bool OnPortalRequestTextPrefix(ZDOID portalId)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return !ShouldBlock(portalId);
		}

		private static TeleportWorld FindPortal(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<TeleportWorld>();
		}
	}
	public static class ZdoFields
	{
		public const string DeclaredSpecies = "op_declared_species";

		public const string PortalName = "op_portal_name";

		public const string PortalRole = "op_portal_role";

		public const string ForwardAdults = "op_forward_adults";

		public const string AdultDestination = "op_adult_destination";

		public const string Transported = "op_transported";

		public const string FollowTarget = "op_follow_target";

		public const string CapWarning = "op_cap_warning";
	}
	public static class PrefabNames
	{
		public const string OffspringPortal = "offspring_portal";

		public const string VanillaPortalWood = "portal_wood";
	}
}
namespace OffspringPortal.UI
{
	public sealed class SpeciesConfigPanel
	{
		private static SpeciesConfigPanel instance;

		private const float Padding = 24f;

		private const float LabelWidth = 160f;

		private const float InputWidth = 460f;

		private const float RowHeight = 32f;

		private const float ButtonWidth = 110f;

		private const float ButtonHeight = 48f;

		private const float FirstColumnLeft = 24f;

		private const float SecondColumnLeft = 208f;

		private const float NameRowTop = -84f;

		private const float TypeRowTop = -140f;

		private const float ReceivesRowTop = -196f;

		private const float DestinationRowTop = -252f;

		private const float ButtonRowHeight = 72f;

		private GameObject mainPanel;

		private GameObject receivesLabelObject;

		private GameObject destinationLabelObject;

		private InputField nameInputField;

		private Dropdown typeDropdown;

		private Dropdown speciesDropdown;

		private Dropdown destinationDropdown;

		private readonly Dictionary<int, PortalRole> indexToRole = new Dictionary<int, PortalRole>();

		private readonly Dictionary<int, SpeciesType> indexToSpecies = new Dictionary<int, SpeciesType>();

		private readonly Dictionary<int, AdultDestination> indexToDestination = new Dictionary<int, AdultDestination>();

		private ZDOID portalId;

		private SpeciesType savedSpecies = SpeciesType.Boar;

		private AdultDestination savedDestination;

		private bool initialized;

		public static SpeciesConfigPanel Instance => instance ?? (instance = new SpeciesConfigPanel());

		public void Open(ZDOID id, PortalRole currentRole, SpeciesType currentSpecies, string currentName, AdultDestination adultDestination)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			EnsureInitialized();
			if (!((Object)(object)mainPanel == (Object)null))
			{
				portalId = id;
				savedSpecies = ((currentSpecies == SpeciesType.None) ? SpeciesType.Boar : currentSpecies);
				savedDestination = adultDestination;
				nameInputField.text = currentName ?? string.Empty;
				PopulateTypeDropdown(currentRole);
				PopulateSpeciesDropdown(savedSpecies);
				PopulateDestinationDropdown(savedDestination);
				UpdatePanelState();
				mainPanel.SetActive(true);
				GUIManager.BlockInput(true);
			}
		}

		public void Close()
		{
			if ((Object)(object)mainPanel != (Object)null)
			{
				mainPanel.SetActive(false);
			}
			GUIManager.BlockInput(false);
		}

		private void EnsureInitialized()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Expected O, but got Unknown
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Expected O, but got Unknown
			if (initialized)
			{
				return;
			}
			GameObject val = GameObject.Find("_GameMain/LoadingGUI/CustomGUIFront");
			if ((Object)(object)val == (Object)null)
			{
				OffspringPortalPlugin.Log.LogError((object)"Could not find Valheim custom GUI root.");
				return;
			}
			float num = 692f;
			float num2 = 308f + 72f + 24f;
			mainPanel = GUIManager.Instance.CreateWoodpanel(val.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), num, num2, false);
			((Object)mainPanel).name = "OffspringPortal_ConfigPanel";
			mainPanel.AddComponent<CanvasGroup>();
			if ((Object)(object)mainPanel.GetComponentInParent<Localize>() == (Object)null)
			{
				mainPanel.AddComponent<Localize>();
			}
			GameObject obj = GUIManager.Instance.CreateText("Configure Portal", mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(20f, -15f), GUIManager.Instance.AveriaSerifBold, 32, GUIManager.Instance.ValheimOrange, true, Color.black, 250f, 50f, false);
			obj.GetComponent<Text>().alignment = (TextAnchor)1;
			obj.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 1f);
			CreateLabel("Name", -84f, out var labelObject);
			GameObject val2 = GUIManager.Instance.CreateInputField(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -84f), (ContentType)0, "e.g. Boar Farm", 18, 460f, 32f);
			val2.GetComponent<RectTransform>().pivot = new Vector2(0f, 1f);
			nameInputField = val2.GetComponent<InputField>();
			nameInputField.characterLimit = 32;
			CreateLabel("Type", -140f, out labelObject);
			GameObject val3 = GUIManager.Instance.CreateDropDown(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -140f), 18, 460f, 32f);
			val3.GetComponent<RectTransform>().pivot = new Vector2(0f, 1f);
			typeDropdown = val3.GetComponent<Dropdown>();
			((UnityEvent<int>)(object)typeDropdown.onValueChanged).AddListener((UnityAction<int>)OnTypeChanged);
			ApplyDropdownStyle(typeDropdown);
			CreateLabel("Receives", -196f, out receivesLabelObject);
			GameObject val4 = GUIManager.Instance.CreateDropDown(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -196f), 18, 460f, 32f);
			val4.GetComponent<RectTransform>().pivot = new Vector2(0f, 1f);
			speciesDropdown = val4.GetComponent<Dropdown>();