Decompiled source of PortableShips v0.12.8

BepInEx/plugins/PortableShips/PortableShips.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using PortableShips.Compatibility;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
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("PortableShips")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.12.8.0")]
[assembly: AssemblyInformationalVersion("0.12.8")]
[assembly: AssemblyProduct("PortableShips")]
[assembly: AssemblyTitle("PortableShips")]
[assembly: AssemblyVersion("0.12.8.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 PortableShips
{
	internal static class AnimalBagPolicy
	{
		internal static bool Empty(string encoded)
		{
			if (string.IsNullOrEmpty(encoded))
			{
				return true;
			}
			if (encoded.Length > 24)
			{
				return false;
			}
			try
			{
				using MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(encoded), writable: false);
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				int num = binaryReader.ReadInt32();
				if (num < 1 || num > 110)
				{
					return false;
				}
				return ((num >= 108) ? binaryReader.ReadUInt16() : binaryReader.ReadInt32()) == 0 && memoryStream.Position == memoryStream.Length;
			}
			catch (Exception ex) when (ex is FormatException || ex is IOException || ex is ArgumentException)
			{
				return false;
			}
		}
	}
	internal readonly struct AnimalCapsuleShape
	{
		internal readonly float Radius;

		internal readonly float HalfSegment;

		internal readonly float RootHeight;

		internal AnimalCapsuleShape(float radius, float halfSegment, float rootHeight)
		{
			Radius = radius;
			HalfSegment = halfSegment;
			RootHeight = rootHeight;
		}

		internal static bool TryCreate(float radius, float height, int direction, float centerY, float sx, float sy, float sz, out AnimalCapsuleShape shape)
		{
			shape = default(AnimalCapsuleShape);
			if (!AnimalRules.Number(radius, 0.001f, 100f) || !AnimalRules.Number(height, 0.001f, 100f) || direction < 0 || direction > 2 || !AnimalRules.Number(centerY, -100f, 100f) || !AnimalRules.Number(sx, 0.05f, 20f) || !AnimalRules.Number(sy, 0.05f, 20f) || !AnimalRules.Number(sz, 0.05f, 20f))
			{
				return false;
			}
			float num = direction switch
			{
				1 => sy, 
				0 => sx, 
				_ => sz, 
			};
			float num2 = radius * direction switch
			{
				1 => Math.Max(sx, sz), 
				0 => Math.Max(sy, sz), 
				_ => Math.Max(sx, sy), 
			};
			float num3 = Math.Max(0f, height * num * 0.5f - num2);
			shape = new AnimalCapsuleShape(num2, num3, num2 + ((direction == 1) ? num3 : 0f) - centerY * sy + 0.12f);
			return true;
		}
	}
	internal static class AnimalCast
	{
		internal static void BeginPacking(Player player, Character actor)
		{
			ShipCast.CheckPlayer(player);
			AnimalPackingService.Validate(player, actor);
			AnimalPackingAccess access = ((Component)actor).GetComponent<AnimalPackingAccess>();
			ZNetView view = ((Component)actor).GetComponent<ZNetView>();
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)access), "Animal is still initializing. Try again shortly.");
			string token = TransactionJournal.NewId();
			bool finished = false;
			ShipCast.Start(Packing(), delegate
			{
				//IL_0011: 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_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				if (!finished)
				{
					ShipCastVisualRelay.Send(player, 0);
				}
				if (Object.op_Implicit((Object)(object)access))
				{
					access.Release(token);
				}
			});
			IEnumerator Packing()
			{
				float until = Time.realtimeSinceStartup + 5f;
				float nextRequest = 0f;
				while (!AnimalPackingAccess.Owns(view, token))
				{
					ShipCast.CheckPlayer(player);
					AnimalPackingService.Validate(player, actor);
					InputAndFeedback.Require(string.IsNullOrEmpty(access.Rejection) || access.Rejection == "retry", access.Rejection);
					InputAndFeedback.Require(Time.realtimeSinceStartup < until, "Animal did not respond. Try again after its state synchronizes.");
					if (Time.realtimeSinceStartup >= nextRequest)
					{
						nextRequest = Time.realtimeSinceStartup + 0.3f;
						access.BeginRequest(token);
					}
					yield return null;
				}
				IEnumerator cast = ShipCast.AnimatedCountdown(player, "Shrinking " + actor.GetHoverName(), delegate
				{
					//IL_0049: Unknown result type (might be due to invalid IL or missing references)
					//IL_0059: Unknown result type (might be due to invalid IL or missing references)
					ShipCast.CheckPlayer(player);
					AnimalPackingService.Validate(player, actor);
					InputAndFeedback.Require(AnimalPackingAccess.Owns(view, token), "Animal reservation changed. Try again.");
					ShipCastVisualRelay.Send(player, 1, ((Component)actor).transform.position, ((Component)actor).transform.rotation);
				});
				while (cast.MoveNext())
				{
					yield return cast.Current;
				}
				Vector3 position = ((Component)actor).transform.position;
				Quaternion rotation = ((Component)actor).transform.rotation;
				AnimalPackingService.Pack(player, actor, token);
				finished = true;
				ShipCastVisualRelay.Send(player, 2, position, rotation);
			}
		}

		internal static void BeginDeployment(Player player, Inventory? source, ItemData item)
		{
			//IL_004a: 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)
			ShipCast.CheckPlayer(player);
			AnimalType type = AnimalIdentification.FromItem(item);
			AnimalDeploymentService.Deploy(player, source, item, validateOnly: true);
			bool finished = false;
			Vector3 point = default(Vector3);
			ShipCast.Start(Deploying(), delegate
			{
				//IL_0011: 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_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				if (!finished)
				{
					ShipCastVisualRelay.Send(player, 0);
				}
			});
			IEnumerator Deploying()
			{
				IEnumerator cast = ShipCast.AnimatedCountdown(player, "Releasing " + type.Label, delegate
				{
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0024: Unknown result type (might be due to invalid IL or missing references)
					//IL_0031: 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)
					ShipCast.CheckPlayer(player);
					point = AnimalDeploymentService.Deploy(player, source, item, validateOnly: true);
					ShipCastVisualRelay.Send(player, 1, point, ((Component)player).transform.rotation);
				});
				while (cast.MoveNext())
				{
					yield return cast.Current;
				}
				point = AnimalDeploymentService.Deploy(player, source, item);
				finished = true;
				ShipCastVisualRelay.Send(player, 2, point, ((Component)player).transform.rotation);
			}
		}
	}
	internal static class AnimalDeploymentService
	{
		internal static Vector3 Deploy(Player player, Inventory? source, ItemData item, bool validateOnly = false)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: 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_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: 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_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = ((Humanoid)player).GetInventory();
			InputAndFeedback.Require((source == null || source == inventory) && inventory.ContainsItem(item), "Move the packed animal to your own hotbar first.");
			AnimalType animalType = AnimalIdentification.FromItem(item);
			PackedAnimalState packedAnimalState = PackedAnimalItem.Validate(item, animalType);
			GameObject val = AnimalIdentification.Resolve(animalType);
			AnimalSnapshot.Preflight(packedAnimalState, val);
			InputAndFeedback.Require(!ZNetView.m_useInitZDO && ZNetView.m_initZDO == null, "Another network spawn is initializing. Try again.");
			Camera mainCamera = Utils.GetMainCamera();
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)mainCamera), "Game camera unavailable.");
			Ray ray = mainCamera.ScreenPointToRay(new Vector3((float)Screen.width / 2f, (float)Screen.height / 2f));
			int mask = LayerMask.GetMask(new string[11]
			{
				"Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle", "character", "character_net", "character_noenv",
				"item"
			});
			InputAndFeedback.Require(InputAndFeedback.AimHit(ray, 60f, mask, player, out var hit) && Vector3.Distance(((Component)player).transform.position, ((RaycastHit)(ref hit)).point) <= PortableShipsPlugin.Instance.DeployDistance.Value && ((RaycastHit)(ref hit)).normal.y >= 0.6f, "Aim at nearby, reasonably level ground or a clear ship deck.");
			InputAndFeedback.Require(!Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Character>()) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<ItemDrop>()), "Aim at solid ground, not an animal or dropped item.");
			Rigidbody attachedRigidbody = ((RaycastHit)(ref hit)).collider.attachedRigidbody;
			InputAndFeedback.Require(!Object.op_Implicit((Object)(object)attachedRigidbody) || attachedRigidbody.isKinematic || Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Ship>()), "Aim at stable ground or a ship deck.");
			float liquidLevel = Floating.GetLiquidLevel(((RaycastHit)(ref hit)).point, 0f, (LiquidType)0);
			InputAndFeedback.Require(liquidLevel < -9999f || ((RaycastHit)(ref hit)).point.y >= liquidLevel + 0.05f, "Choose dry ground or a deck above the water.");
			Vector3 val2 = Vector3.ProjectOnPlane(((Character)player).GetLookDir(), Vector3.up);
			Quaternion val3 = ((((Vector3)(ref val2)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up) : ((Component)player).transform.rotation);
			CapsuleCollider component = val.GetComponent<CapsuleCollider>();
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(packedAnimalState.ScaleX, packedAnimalState.ScaleY, packedAnimalState.ScaleZ);
			InputAndFeedback.Require(AnimalCapsuleShape.TryCreate(component.radius, component.height, component.direction, component.center.y, val4.x, val4.y, val4.z, out var shape), "Animal collision shape is unsupported; packed item unchanged.");
			float radius = shape.Radius;
			float halfSegment = shape.HalfSegment;
			Vector3 val5 = val3 * ((component.direction == 0) ? Vector3.right : ((component.direction == 1) ? Vector3.up : Vector3.forward));
			Vector3 val6 = Vector3.Scale(component.center, val4);
			Vector3 val7 = ((RaycastHit)(ref hit)).point + Vector3.up * shape.RootHeight;
			Vector3 val8 = val7 + val3 * val6;
			InputAndFeedback.Require(!Physics.CheckCapsule(val8 - val5 * halfSegment, val8 + val5 * halfSegment, radius * 0.98f, mask, (QueryTriggerInteraction)1), "Not enough space for this animal. Aim at a clear area.");
			InputAndFeedback.Require(PrivateArea.CheckAccess(val7, radius, true, false), "A ward prevents releasing the animal here.");
			if (validateOnly)
			{
				return val7;
			}
			string text = TransactionJournal.NewId();
			TransactionJournal.Write(text, "animal-deploy-intent", string.Format("player={0} animal={1} identity={2} position={3} prior={4}", player.GetPlayerID(), animalType.Prefab, packedAnimalState.Identity, val7, item.m_customData["PortableShips.AnimalTransaction"]));
			item.m_customData["PortableShips.AnimalState"] = "deploying";
			item.m_customData["PortableShips.AnimalTransaction"] = text;
			PortableShipsPlugin.Instance.Busy = true;
			try
			{
				inventory.m_onChanged?.Invoke();
				ZDO val9 = ZDOMan.instance.CreateNewZDO(val7, StringExtensionMethods.GetStableHashCode(animalType.Prefab));
				val9.SetPrefab(StringExtensionMethods.GetStableHashCode(animalType.Prefab));
				val9.SetRotation(val3);
				ZNetView component2 = val.GetComponent<ZNetView>();
				val9.Persistent = true;
				val9.SetType(component2.m_type);
				val9.SetDistant(component2.m_distant);
				val9.Set("PortableShips.Transaction", "animal-deploy:" + text);
				AnimalSnapshot.Restore(val9, packedAnimalState, val);
				ZNetView.m_useInitZDO = true;
				ZNetView.m_initZDO = val9;
				GameObject val10;
				try
				{
					val10 = Object.Instantiate<GameObject>(val, val7, val3);
				}
				finally
				{
					ZNetView.m_useInitZDO = false;
					ZNetView.m_initZDO = null;
				}
				ZNetView component3 = val10.GetComponent<ZNetView>();
				Character component4 = val10.GetComponent<Character>();
				InputAndFeedback.Require(Object.op_Implicit((Object)(object)component3) && component3.IsValid() && component3.IsOwner() && component3.GetZDO() == val9 && Object.op_Implicit((Object)(object)component4), "Animal spawn could not be verified. Keep the pending item and check the journal.");
				component4.SetLevel(packedAnimalState.Level);
				if (Object.op_Implicit((Object)(object)attachedRigidbody))
				{
					val10.GetComponent<Rigidbody>().linearVelocity = attachedRigidbody.GetPointVelocity(val7);
				}
				val9.Set(ZDOVars.s_maxHealth, packedAnimalState.MaxHealth);
				val9.Set(ZDOVars.s_health, packedAnimalState.Health);
				MonsterAI component5 = ((Component)component4).GetComponent<MonsterAI>();
				if (Object.op_Implicit((Object)(object)component5))
				{
					component5.MakeTame();
					component5.SetDespawnInDay(false);
					component5.SetEventCreature(false);
				}
				TransactionJournal.Write(text, "animal-created", ((object)Unsafe.As<ZDOID, ZDOID>(ref val9.m_uid)/*cast due to .constrained prefix*/).ToString());
				((MonoBehaviour)PortableShipsPlugin.Instance).StartCoroutine(Complete(player, inventory, item, component4, component3, packedAnimalState, text));
				return val7;
			}
			catch
			{
				PortableShipsPlugin.Instance.Busy = false;
				PortableShipsPlugin.Instance.Error("Animal deployment " + text + " interrupted. Keep pending item/animal lock; inspect the journal before recovery.");
				throw;
			}
		}

		private static IEnumerator Complete(Player player, Inventory inventory, ItemData item, Character actor, ZNetView view, PackedAnimalState state, string tx)
		{
			yield return null;
			yield return (object)new WaitForFixedUpdate();
			yield return null;
			try
			{
				InputAndFeedback.Require(Object.op_Implicit((Object)(object)player) && (Object)(object)Player.m_localPlayer == (Object)(object)player && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)actor) && Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner(), "Animal release interrupted. Keep the pending item and check the journal.");
				AnimalSnapshot.Verify(actor, state);
				InputAndFeedback.Require(inventory.ContainsItem(item) && inventory.RemoveItem(item), "Could not consume the reserved animal item. Consult the journal before recovery.");
				view.GetZDO().Set("PortableShips.Transaction", "");
				TransactionJournal.Write(tx, "animal-deploy-commit", ((object)Unsafe.As<ZDOID, ZDOID>(ref view.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString());
				InputAndFeedback.Say("Animal released, still tamed.");
			}
			catch (Exception ex)
			{
				PortableShipsPlugin.Instance.Error("Animal release " + tx + ": " + ex);
				InputAndFeedback.Say(ex.Message);
			}
			finally
			{
				PortableShipsPlugin.Instance.Busy = false;
			}
		}
	}
	internal static class AnimalIcons
	{
		private static readonly Dictionary<string, Sprite> Icons = new Dictionary<string, Sprite>();

		internal static Sprite For(AnimalType type)
		{
			string key = ((type.Prefab == "Hen" || type.Prefab == "Chicken") ? type.Prefab : type.Trophy);
			if (Icons.TryGetValue(key, out Sprite value) && Object.op_Implicit((Object)(object)value))
			{
				return value;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(type.Trophy);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				prefab = PrefabManager.Instance.GetPrefab("TrophyBoar");
			}
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			return prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_icons[0];
		}

		internal static void Refresh()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4 || !Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return;
			}
			StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Cold"));
			if (!Object.op_Implicit((Object)(object)statusEffect) || !Object.op_Implicit((Object)(object)statusEffect.m_icon))
			{
				PortableShipsPlugin.Instance.LogInfo("Cold status icon is not ready for packed animals.");
				return;
			}
			AnimalType[] types = AnimalIdentification.Types;
			foreach (AnimalType animalType in types)
			{
				string key = ((animalType.Prefab == "Hen" || animalType.Prefab == "Chicken") ? animalType.Prefab : animalType.Trophy);
				if (!Icons.ContainsKey(key))
				{
					try
					{
						Sprite foreground = For(animalType);
						if (animalType.Prefab == "Hen" || animalType.Prefab == "Chicken")
						{
							GameObject prefab = PrefabManager.Instance.GetPrefab(animalType.Prefab);
							Sprite val = RenderManager.Instance.Render(new RenderRequest(prefab)
							{
								Width = 128,
								Height = 128,
								Rotation = Quaternion.Euler(10f, 135f, 0f),
								UseCache = true,
								TargetPlugin = ((BaseUnityPlugin)PortableShipsPlugin.Instance).Info.Metadata,
								ParticleSimulationTime = -1f
							});
							if (Object.op_Implicit((Object)(object)val))
							{
								Rect rect = val.rect;
								if (((Rect)(ref rect)).width > 0f)
								{
									foreground = val;
								}
							}
						}
						Icons[key] = Compose(statusEffect.m_icon, foreground);
					}
					catch (Exception ex)
					{
						PortableShipsPlugin.Instance.Error("Packed animal icon " + animalType.Prefab + ": " + ex.Message);
					}
				}
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(animalType.Item);
				if (Object.op_Implicit((Object)(object)prefab2))
				{
					prefab2.GetComponent<ItemDrop>().m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { For(animalType) };
				}
			}
		}

		private static Color[] Pixels(Sprite sprite, int size)
		{
			//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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture active = RenderTexture.active;
			RenderTexture temporary = RenderTexture.GetTemporary(size, size, 0, (RenderTextureFormat)0);
			Texture2D val = null;
			try
			{
				Rect textureRect = sprite.textureRect;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(((Rect)(ref textureRect)).width / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)sprite.texture).height);
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)sprite.texture).height);
				Graphics.Blit((Texture)(object)sprite.texture, temporary, val2, val3);
				RenderTexture.active = temporary;
				val = new Texture2D(size, size, (TextureFormat)4, false);
				val.ReadPixels(new Rect(0f, 0f, (float)size, (float)size), 0, 0);
				val.Apply();
				return val.GetPixels();
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static Sprite Compose(Sprite background, Sprite foreground)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = Pixels(background, 128);
			Color[] array2 = Pixels(foreground, 96);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].a *= 0.9f;
			}
			for (int j = 0; j < 96; j++)
			{
				for (int k = 0; k < 96; k++)
				{
					int num = (j + 16) * 128 + k + 16;
					Color val = array2[j * 96 + k];
					Color val2 = array[num];
					float num2 = val.a + val2.a * (1f - val.a);
					array[num] = (Color)((num2 <= 0f) ? Color.clear : new Color((val.r * val.a + val2.r * val2.a * (1f - val.a)) / num2, (val.g * val.a + val2.g * val2.a * (1f - val.a)) / num2, (val.b * val.a + val2.b * val2.a * (1f - val.a)) / num2, num2));
				}
			}
			Texture2D val3 = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				name = "PortableShips.FrozenAnimalIcon",
				filterMode = (FilterMode)1
			};
			val3.SetPixels(array);
			val3.Apply(false, true);
			return Sprite.Create(val3, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
		}
	}
	internal sealed class AnimalType
	{
		internal readonly string Prefab;

		internal readonly string Label;

		internal readonly string Trophy;

		internal readonly string Item;

		internal AnimalType(string prefab, string label, string trophy)
		{
			Prefab = prefab;
			Label = label;
			Trophy = trophy;
			Item = "PortableShips_PackedAnimal_" + prefab;
		}
	}
	internal static class AnimalIdentification
	{
		internal static readonly AnimalType[] Types = new AnimalType[27]
		{
			new AnimalType("Boar", "Boar", "TrophyBoar"),
			new AnimalType("Boar_piggy", "Piglet", "TrophyBoar"),
			new AnimalType("Wolf", "Wolf", "TrophyWolf"),
			new AnimalType("Wolf_cub", "Wolf cub", "TrophyWolf"),
			new AnimalType("Lox", "Lox", "TrophyLox"),
			new AnimalType("Lox_Calf", "Lox calf", "TrophyLox"),
			new AnimalType("Hen", "Hen", "ChickenEgg"),
			new AnimalType("Chicken", "Chick", "ChickenEgg"),
			new AnimalType("Asksvin", "Asksvin", "TrophyAsksvin"),
			new AnimalType("Asksvin_hatchling", "Asksvin hatchling", "TrophyAsksvin"),
			new AnimalType("Moose", "Moose", "TrophyMoose"),
			new AnimalType("Moose_calf", "Moose calf", "TrophyMoose"),
			new AnimalType("rae_OdinHorse", "Horse", "rae_OdinHorse_Trophy"),
			new AnimalType("rae_Offspring_Normal", "Foal", "rae_OdinHorse_Trophy"),
			new AnimalType("Fox_TW", "Fox", "TrophyFox_TW"),
			new AnimalType("FoxCub_TW", "Fox cub", "TrophyFox_TW"),
			new AnimalType("Razorback_TW", "Razorback", "TrophyRazorback_TW"),
			new AnimalType("RazorbackPiggy_TW", "Razorback piglet", "TrophyRazorback_TW"),
			new AnimalType("BlackBear_TW", "Black bear", "TrophyBlackBear_TW"),
			new AnimalType("BlackBearCub_TW", "Black bear cub", "TrophyBlackBear_TW"),
			new AnimalType("GrizzlyBear_TW", "Grizzly bear", "TrophyGrizzlyBear_TW"),
			new AnimalType("GrizzlyBearCub_TW", "Grizzly cub", "TrophyGrizzlyBear_TW"),
			new AnimalType("Prowler_TW", "Prowler", "TrophyProwler_TW"),
			new AnimalType("ProwlerCub_TW", "Prowler cub", "TrophyProwler_TW"),
			new AnimalType("ArcticBear_TW", "Arctic bear", "TrophyArcticBear_TW"),
			new AnimalType("ArcticBearCub_TW", "Arctic bear cub", "TrophyArcticBear_TW"),
			new AnimalType("BearCubBase_TW", "Bear cub", "TrophyArcticBear_TW")
		};

		internal static AnimalType? FromCharacter(Character actor)
		{
			ZNetView view = (Object.op_Implicit((Object)(object)actor) ? ((Component)actor).GetComponent<ZNetView>() : null);
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
			{
				return null;
			}
			return Types.FirstOrDefault((AnimalType t) => StringExtensionMethods.GetStableHashCode(t.Prefab) == view.GetZDO().GetPrefab());
		}

		internal static AnimalType? FromItem(ItemData item)
		{
			if (item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab))
			{
				return null;
			}
			return Types.FirstOrDefault((AnimalType t) => t.Item == ((Object)item.m_dropPrefab).name);
		}

		internal static GameObject Resolve(AnimalType type)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(type.Prefab);
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)prefab) && Object.op_Implicit((Object)(object)prefab.GetComponent<Character>()) && Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>()) && Object.op_Implicit((Object)(object)prefab.GetComponent<CapsuleCollider>()), "Animal prefab unavailable: " + type.Prefab);
			return prefab;
		}
	}
	internal static class AnimalModCompatibility
	{
		[HarmonyPatch]
		private static class HorseMutations
		{
			private static bool Prepare()
			{
				if (Chainloader.PluginInfos.TryGetValue("Raelaziel.OdinHorse", out var value) && value.Metadata.Version.ToString() == "1.9.1")
				{
					return AccessTools.TypeByName("OdinHorse.TameableExtensions") != null;
				}
				return false;
			}

			private static IEnumerable<MethodBase> TargetMethods()
			{
				Type type = AccessTools.TypeByName("OdinHorse.TameableExtensions");
				string[] array = new string[3] { "RPC_AddArmor", "RPC_RemoveArmor", "RPC_ToggleWait" };
				foreach (string text in array)
				{
					MethodInfo methodInfo = AccessTools.Method(type, text, (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						yield return methodInfo;
					}
				}
				MethodInfo methodInfo2 = AccessTools.Method(AccessTools.TypeByName("OdinHorse.HorseSaddlebags"), "Open", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					yield return methodInfo2;
				}
			}

			[HarmonyPriority(800)]
			private static bool Prefix(Tameable __0)
			{
				return !AnimalPackingAccess.Reserved(((Component)__0).GetComponent<ZNetView>());
			}
		}

		[HarmonyPatch]
		private static class HorseCart
		{
			private static bool Prepare()
			{
				if (!Chainloader.PluginInfos.TryGetValue("Raelaziel.OdinHorse", out var value) || value.Metadata.Version.ToString() != "1.9.1")
				{
					return false;
				}
				Type type = AccessTools.TypeByName("OdinHorse.OdinHorse");
				if (type != null)
				{
					return AccessTools.Method(type, "AttachCartTo", (Type[])null, (Type[])null) != null;
				}
				return false;
			}

			private static MethodBase TargetMethod()
			{
				return AccessTools.Method(AccessTools.TypeByName("OdinHorse.OdinHorse"), "AttachCartTo", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(800)]
			private static bool Prefix(Character __0)
			{
				return !AnimalPackingAccess.Reserved(((Component)__0).GetComponent<ZNetView>());
			}
		}

		internal static void RequireVersion(string prefab)
		{
			string text = (AnimalRules.Horse(prefab) ? "Raelaziel.OdinHorse" : (prefab.EndsWith("_TW", StringComparison.Ordinal) ? "Therzie.Monstrum" : ""));
			if (text.Length != 0)
			{
				string text2 = ((text == "Raelaziel.OdinHorse") ? "1.9.1" : "1.6.1");
				InputAndFeedback.Require(Chainloader.PluginInfos.TryGetValue(text, out var value) && value.Metadata.Version.ToString() == text2, "This animal requires the inspected " + text + " " + text2 + " build to preserve its data.");
			}
		}

		internal static void RequireHorseCoat(int coat)
		{
			Type type = AccessTools.TypeByName("OdinHorse.OdinHorse");
			IList list = ((type == null) ? null : (AccessTools.Field(type, "horseMaterials")?.GetValue(null) as IList));
			InputAndFeedback.Require(list != null && coat >= 0 && coat < list.Count, "Horse coat is still initializing or the OdinHorse palette changed. Animal/item unchanged.");
		}

		internal static void ValidateHorseStorage(Character actor)
		{
			InputAndFeedback.Require(AnimalBagPolicy.Empty(((Component)actor).GetComponent<ZNetView>().GetZDO().GetString("rae_saddlebags", "")), "Empty and close the horse's saddlebags before shrinking it.");
		}
	}
	internal sealed class AnimalPackingAccess : MonoBehaviour
	{
		[HarmonyPatch(typeof(Character), "Awake")]
		private static class Register
		{
			private static void Postfix(Character __instance)
			{
				if (AnimalIdentification.FromCharacter(__instance) != null && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<AnimalPackingAccess>()))
				{
					((Component)__instance).gameObject.AddComponent<AnimalPackingAccess>().Initialize(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Character), "GetHoverText")]
		private static class Hover
		{
			private static void Postfix(Character __instance, ref string __result)
			{
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if (Object.op_Implicit((Object)(object)localPlayer) && Beastbinding.Learned(localPlayer) && __instance.IsTamed() && AnimalIdentification.FromCharacter(__instance) != null && InputAndFeedback.CanAct(localPlayer) && (Object)(object)AnimalPackingService.AimedAnimal(localPlayer) == (Object)(object)__instance)
				{
					__result = __result + "\n[<color=yellow><b>" + ((object)PortableShipsPlugin.Instance.PackKey.Value/*cast due to .constrained prefix*/).ToString() + "</b></color>] Shrink";
				}
			}
		}

		[HarmonyPatch(typeof(BaseAI), "UpdateAI")]
		private static class PauseAI
		{
			private static bool Prefix(BaseAI __instance, ref bool __result)
			{
				if (!Reserved(((Component)__instance).GetComponent<ZNetView>()))
				{
					return true;
				}
				__instance.StopMoving();
				__result = false;
				return false;
			}
		}

		[HarmonyPatch]
		private static class PauseLifeCycle
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Growup), "GrowUpdate", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Procreation), "Procreate", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Tameable), "RPC_AddSaddle", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Tameable), "RPC_SetName", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Sadle), "RPC_RemoveSaddle", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Sadle), "UpdateStamina", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Sadle), "UpdateDrown", (Type[])null, (Type[])null);
			}

			private static bool Prefix(Component __instance)
			{
				return !Reserved(__instance.GetComponentInParent<ZNetView>());
			}
		}

		[HarmonyPatch(typeof(Sadle), "RPC_RequestControl")]
		private static class RiderGuard
		{
			private static bool Prefix(Sadle __instance, long sender)
			{
				ZNetView componentInParent = ((Component)__instance).GetComponentInParent<ZNetView>();
				if (!Reserved(componentInParent))
				{
					return true;
				}
				if (componentInParent.IsOwner())
				{
					componentInParent.InvokeRPC(sender, "RequestRespons", new object[1] { false });
				}
				return false;
			}
		}

		[HarmonyPatch]
		private static class InteractionGuard
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Tameable), "Interact", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Tameable), "UseItem", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Tameable), "DropSaddle", (Type[])null, (Type[])null);
			}

			[HarmonyPriority(800)]
			private static bool Prefix(Tameable __instance, ref bool __result)
			{
				if (!Reserved(((Component)__instance).GetComponent<ZNetView>()))
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch]
		private static class CommitDamageGuard
		{
			private static IEnumerable<MethodBase> TargetMethods()
			{
				yield return AccessTools.Method(typeof(Character), "RPC_Damage", (Type[])null, (Type[])null);
				yield return AccessTools.Method(typeof(Character), "RPC_Heal", (Type[])null, (Type[])null);
			}

			private static bool Prefix(Character __instance)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid())
				{
					return !component.GetZDO().GetString("PortableShips.Transaction", "").StartsWith("animal-", StringComparison.Ordinal);
				}
				return true;
			}
		}

		private const string RequestRpc = "PortableShips.RequestAnimal";

		private const string ReplyRpc = "PortableShips.AnimalReply";

		private Character actor;

		private ZNetView view;

		internal string Rejection = "";

		private string requested = "";

		private PackedAnimalState? appearance;

		private float appearanceUntil;

		private float nextAppearance;

		internal void Initialize(Character target)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			actor = target;
			view = ((Component)target).GetComponent<ZNetView>();
			view.Register<string>("PortableShips.RequestAnimal", (Action<long, string>)Request);
			view.Register<string, string>("PortableShips.AnimalReply", (Action<long, string, string>)Reply);
			ZDO zDO = view.GetZDO();
			Vector3 vec = zDO.GetVec3("PortableShips.AnimalScale", Vector3.zero);
			if (AnimalRules.Number(vec.x, 0.05f, 20f) && AnimalRules.Number(vec.y, 0.05f, 20f) && AnimalRules.Number(vec.z, 0.05f, 20f))
			{
				((Component)actor).transform.localScale = vec;
			}
			if (PackedAnimalState.TryDecode(zDO.GetString("PortableShips.AnimalAppearance", ""), AnimalIdentification.FromCharacter(target).Prefab, out PackedAnimalState state))
			{
				appearance = state;
				appearanceUntil = Time.unscaledTime + 2f;
			}
		}

		private void LateUpdate()
		{
			if (appearance == null || Time.unscaledTime > appearanceUntil || Time.unscaledTime < nextAppearance)
			{
				return;
			}
			nextAppearance = Time.unscaledTime + 0.15f;
			try
			{
				AnimalAppearance.Apply(actor, appearance);
			}
			catch (Exception ex)
			{
				appearance = null;
				PortableShipsPlugin.Instance.Error("Animal appearance: " + ex.Message);
			}
		}

		internal static bool Reserved(ZNetView view)
		{
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				if (!view.GetZDO().GetString("PortableShips.Transaction", "").StartsWith("animal-", StringComparison.Ordinal))
				{
					if (!string.IsNullOrEmpty(view.GetZDO().GetString("PortableShips.AnimalLease", "")) && Object.op_Implicit((Object)(object)ZNet.instance))
					{
						return view.GetZDO().GetLong("PortableShips.AnimalLeaseExpires", 0L) > ZNet.instance.GetTime().Ticks;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static bool Owns(ZNetView view, string token)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner() && view.GetZDO().GetString("PortableShips.AnimalLease", "") == token)
			{
				return view.GetZDO().GetLong("PortableShips.AnimalLeaseExpires", 0L) > ZNet.instance.GetTime().Ticks;
			}
			return false;
		}

		internal void BeginRequest(string token)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			requested = token;
			Rejection = "";
			if (!view.HasOwner())
			{
				view.ClaimOwnership();
			}
			Beastbinding.Publish(Player.m_localPlayer);
			ZNetView component = ((Component)Player.m_localPlayer).GetComponent<ZNetView>();
			if (view.GetZDO().GetOwner() != ZNet.GetUID())
			{
				ZDOMan.instance.ForceSendZDO(view.GetZDO().GetOwner(), component.GetZDO().m_uid);
			}
			view.InvokeRPC("PortableShips.RequestAnimal", new object[1] { token });
		}

		private void Request(long sender, string token)
		{
			//IL_01c3: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			if (!view.IsValid() || !view.IsOwner())
			{
				return;
			}
			try
			{
				InputAndFeedback.Require(Guid.TryParseExact(token, "N", out var _), "Invalid animal request.");
				if (view.GetZDO().GetString("PortableShips.AnimalLease", "") == token && Owns(view, token))
				{
					view.InvokeRPC(sender, "PortableShips.AnimalReply", new object[2] { token, "" });
					return;
				}
				InputAndFeedback.Require(!Reserved(view) && string.IsNullOrEmpty(view.GetZDO().GetString("PortableShips.Transaction", "")), "This animal is busy or has an unfinished transaction.");
				Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)((Component)p).GetComponent<ZNetView>()) && ((Component)p).GetComponent<ZNetView>().IsValid() && ((Component)p).GetComponent<ZNetView>().GetZDO().GetOwner() == sender));
				InputAndFeedback.Require(Object.op_Implicit((Object)(object)val) && !((Character)val).IsDead() && Vector3.Distance(((Component)val).transform.position, ((Component)actor).transform.position) <= 10f, "Move closer to the animal.");
				InputAndFeedback.Require(((Component)val).GetComponent<ZNetView>().GetZDO().GetBool("PortableShips.BeastbindingLearned", false), "retry");
				AnimalPackingService.ValidateActor(actor);
				view.GetZDO().Set("PortableShips.AnimalLease", token);
				view.GetZDO().Set("PortableShips.AnimalLeaseExpires", ZNet.instance.GetTime().AddSeconds(10.0).Ticks);
				ZDOMan.instance.ForceSendZDO(sender, view.GetZDO().m_uid);
				view.GetZDO().SetOwner(sender);
				view.InvokeRPC(sender, "PortableShips.AnimalReply", new object[2] { token, "" });
			}
			catch (Exception ex)
			{
				string text = ((ex is InvalidOperationException) ? ex.Message : "Animal reservation failed. Check the PortableShips log.");
				if (!(ex is InvalidOperationException))
				{
					PortableShipsPlugin.Instance.Error(ex.ToString());
				}
				view.InvokeRPC(sender, "PortableShips.AnimalReply", new object[2] { token, text });
			}
		}

		private void Reply(long sender, string token, string error)
		{
			if (token == requested)
			{
				Rejection = error;
			}
		}

		internal void Release(string token)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)ZNetScene.instance) && ZDOMan.instance != null && Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner() && view.GetZDO().GetString("PortableShips.AnimalLease", "") == token && string.IsNullOrEmpty(view.GetZDO().GetString("PortableShips.Transaction", "")))
			{
				view.GetZDO().Set("PortableShips.AnimalLease", "");
				view.GetZDO().Set("PortableShips.AnimalLeaseExpires", 0L);
			}
			requested = "";
		}
	}
	internal static class AnimalPackingService
	{
		internal static Character? AimedAnimal(Player player)
		{
			//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_0033: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			Camera mainCamera = Utils.GetMainCamera();
			if (!Object.op_Implicit((Object)(object)mainCamera))
			{
				return null;
			}
			Ray ray = mainCamera.ScreenPointToRay(new Vector3((float)Screen.width / 2f, (float)Screen.height / 2f));
			int mask = LayerMask.GetMask(new string[11]
			{
				"Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle", "character", "character_net", "character_noenv",
				"character_ghost"
			});
			if (!InputAndFeedback.AimHit(ray, 50f, mask, player, out var hit) || Vector3.Distance(((Character)player).GetEyePoint(), ((RaycastHit)(ref hit)).point) > PortableShipsPlugin.Instance.PackDistance.Value)
			{
				return null;
			}
			Character componentInParent = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Character>();
			if (!Object.op_Implicit((Object)(object)componentInParent) || componentInParent.IsPlayer())
			{
				return null;
			}
			return componentInParent;
		}

		internal static void ValidateActor(Character actor)
		{
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)actor) && AnimalIdentification.FromCharacter(actor) != null, "This creature is not a supported permanent tameable animal.");
			AnimalModCompatibility.RequireVersion(AnimalIdentification.FromCharacter(actor).Prefab);
			InputAndFeedback.Require(actor.IsTamed(), "Only fully tamed animals can be shrunk.");
			InputAndFeedback.Require(!actor.IsDead() && actor.GetHealth() > 0f, "This animal is no longer alive.");
			ZNetView view = ((Component)actor).GetComponent<ZNetView>();
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)view) && view.IsValid(), "Animal is no longer available.");
			Tameable component = ((Component)actor).GetComponent<Tameable>();
			InputAndFeedback.Require(!Object.op_Implicit((Object)(object)component) || (component.m_unsummonDistance <= 0f && component.m_unsummonOnOwnerLogoutSeconds <= 0f), "Temporary summons cannot be packed.");
			InputAndFeedback.Require(!Object.op_Implicit((Object)(object)component) || !component.HaveRider(), "Dismount before shrinking the animal.");
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				Transform attachPoint = allPlayer.GetAttachPoint();
				InputAndFeedback.Require(!Object.op_Implicit((Object)(object)attachPoint) || (Object)(object)((Component)attachPoint).GetComponentInParent<Character>() != (Object)(object)actor, "A player is still mounted on this animal.");
			}
			InputAndFeedback.Require(((Component)actor).GetComponentsInChildren<ZNetView>(true).All((ZNetView v) => (Object)(object)v == (Object)(object)view), "Animal has independently networked attachments. Packing blocked to preserve them.");
			Container[] componentsInChildren = ((Component)actor).GetComponentsInChildren<Container>(true);
			foreach (Container val in componentsInChildren)
			{
				InputAndFeedback.Require(AnimalRules.Horse(AnimalIdentification.FromCharacter(actor).Prefab) && ((Object)val).name == "SaddlebagContainer" && !val.IsInUse() && val.GetInventory().GetAllItems().Count == 0, "Empty and close the animal's storage before shrinking; unsupported storage attachments must be removed.");
			}
			if (AnimalRules.Horse(AnimalIdentification.FromCharacter(actor).Prefab))
			{
				AnimalModCompatibility.ValidateHorseStorage(actor);
			}
			Rigidbody body = ((Component)actor).GetComponent<Rigidbody>();
			InputAndFeedback.Require(!Object.FindObjectsByType<Joint>((FindObjectsSortMode)0).Any((Joint j) => (Object)(object)j.connectedBody == (Object)(object)body), "Detach the cart or physical tether before shrinking this animal.");
			if (view.GetZDO().GetBool(ZDOVars.s_haveSaddleHash, false))
			{
				InputAndFeedback.Require(Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_saddle) && Object.op_Implicit((Object)(object)component.m_saddleItem) && AnimalRules.CanSaddle(AnimalIdentification.FromCharacter(actor).Prefab), "Animal's saddle cannot be preserved safely.");
			}
		}

		internal static void Validate(Player player, Character actor)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			InputAndFeedback.Require(Beastbinding.Learned(player), "Buy Beastbinding from the Bog Witch for 1,000 coins to shrink tamed animals.");
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)actor) && (Object)(object)AimedAnimal(player) == (Object)(object)actor, "Keep aiming at the same nearby animal.");
			ValidateActor(actor);
			InputAndFeedback.Require(string.IsNullOrEmpty(((Component)actor).GetComponent<ZNetView>().GetZDO().GetString("PortableShips.Transaction", "")), "Animal has an unfinished transaction. Check the journal.");
			InputAndFeedback.Require(PrivateArea.CheckAccess(((Component)actor).transform.position, 0f, true, false), "A ward prevents shrinking this animal.");
			InputAndFeedback.Require(((Humanoid)player).GetInventory().HaveEmptySlot(), "Free an inventory slot before shrinking the animal.");
		}

		internal unsafe static void Pack(Player player, Character actor, string token)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			Validate(player, actor);
			AnimalType animalType = AnimalIdentification.FromCharacter(actor);
			ZNetView component = ((Component)actor).GetComponent<ZNetView>();
			InputAndFeedback.Require(AnimalPackingAccess.Owns(component, token), "Animal reservation changed. Try again.");
			PackedAnimalState packedAnimalState = AnimalSnapshot.Capture(actor, animalType);
			string text = TransactionJournal.NewId();
			ItemData val = PackedAnimalItem.Create(animalType, packedAnimalState, text);
			Inventory inventory = ((Humanoid)player).GetInventory();
			InputAndFeedback.Require(inventory.CanAddItem(val, -1), "No room for the packed animal.");
			TransactionJournal.Write(text, "animal-pack-intent", $"player={player.GetPlayerID()} animal={animalType.Prefab} identity={packedAnimalState.Identity} zdo={component.GetZDO().m_uid} hp={packedAnimalState.Health}/{packedAnimalState.MaxHealth} saddle={packedAnimalState.Saddle}");
			bool flag = false;
			PortableShipsPlugin.Instance.Busy = true;
			try
			{
				InputAndFeedback.Require(inventory.AddItem(val) && inventory.ContainsItem(val), "Unable to reserve an inventory slot.");
				InputAndFeedback.Require(AnimalPackingAccess.Owns(component, token), "Animal authority changed before packing.");
				ValidateActor(actor);
				component.GetZDO().Set("PortableShips.Transaction", "animal-pack:" + text);
				flag = true;
				ZDOID uid = component.GetZDO().m_uid;
				ZDOMan instance = ZDOMan.instance;
				TransactionJournal.Write(text, "animal-delete-intent", ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString());
				component.Destroy();
				((MonoBehaviour)PortableShipsPlugin.Instance).StartCoroutine(Complete(player, inventory, val, instance, uid, text));
			}
			catch
			{
				PortableShipsPlugin.Instance.Busy = false;
				if (!flag)
				{
					inventory.RemoveItem(val);
				}
				else
				{
					PortableShipsPlugin.Instance.Error("Animal packing " + text + " interrupted; pending item/lock retained. Check the journal before recovery.");
				}
				throw;
			}
		}

		private unsafe static IEnumerator Complete(Player player, Inventory inventory, ItemData item, ZDOMan manager, ZDOID id, string tx)
		{
			//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 until = Time.realtimeSinceStartup + 15f;
			while (ZDOMan.instance == manager && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)player) && (Object)(object)Player.m_localPlayer == (Object)(object)player && manager.GetZDO(id) != null && Time.realtimeSinceStartup < until)
			{
				yield return null;
			}
			try
			{
				if (ZDOMan.instance != manager || !Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)player) || (Object)(object)Player.m_localPlayer != (Object)(object)player || manager.GetZDO(id) != null || !inventory.ContainsItem(item))
				{
					PortableShipsPlugin.Instance.Error("Animal pack " + tx + " acknowledgement uncertain. Keep the pending item and inspect the journal.");
					InputAndFeedback.Say("Animal pack confirmation interrupted. Keep the pending item and check the journal.");
					yield break;
				}
				TransactionJournal.Write(tx, "animal-pack-commit", ((object)(*(ZDOID*)(&id))/*cast due to .constrained prefix*/).ToString());
				item.m_customData["PortableShips.AnimalState"] = "ready";
				inventory.m_onChanged?.Invoke();
				InputAndFeedback.Say("Animal safely packed.");
			}
			finally
			{
				PortableShipsPlugin.Instance.Busy = false;
			}
		}
	}
	internal static class AnimalAppearance
	{
		private static readonly int[] Floats = new int[3]
		{
			Shader.PropertyToID("_Hue"),
			Shader.PropertyToID("_Saturation"),
			Shader.PropertyToID("_Value")
		};

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private static readonly int SkinId = Shader.PropertyToID("_SkinColor");

		internal static AnimalTint[] Capture(Character actor)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			List<AnimalTint> list = new List<AnimalTint>();
			SkinnedMeshRenderer[] componentsInChildren = ((Component)actor).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			InputAndFeedback.Require(componentsInChildren.Length <= 128, "Animal has an unsupported appearance layout.");
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = ((Renderer)componentsInChildren[i]).sharedMaterials;
				InputAndFeedback.Require(sharedMaterials.Length <= 16, "Animal has too many appearance materials.");
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material material = sharedMaterials[j];
					if (!Object.op_Implicit((Object)(object)material))
					{
						continue;
					}
					MaterialPropertyBlock block = new MaterialPropertyBlock();
					((Renderer)componentsInChildren[i]).GetPropertyBlock(block, j);
					AnimalTint tint = new AnimalTint
					{
						Renderer = i,
						Material = j
					};
					for (int k = 0; k < Floats.Length; k++)
					{
						if (material.HasProperty(Floats[k]))
						{
							tint.Flags |= 1 << k;
							tint.Values[k] = (block.HasFloat(Floats[k]) ? block.GetFloat(Floats[k]) : material.GetFloat(Floats[k]));
						}
					}
					Color(ColorId, 8, 3);
					Color(SkinId, 16, 7);
					if (tint.Flags != 0)
					{
						list.Add(tint);
					}
					void Color(int id, int bit, int offset)
					{
						//IL_0045: 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_004a: Unknown result type (might be due to invalid IL or missing references)
						//IL_0057: Unknown result type (might be due to invalid IL or missing references)
						//IL_006c: 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_0096: Unknown result type (might be due to invalid IL or missing references)
						if (material.HasProperty(id))
						{
							tint.Flags |= bit;
							Color val = (block.HasColor(id) ? block.GetColor(id) : material.GetColor(id));
							tint.Values[offset] = val.r;
							tint.Values[offset + 1] = val.g;
							tint.Values[offset + 2] = val.b;
							tint.Values[offset + 3] = val.a;
						}
					}
				}
			}
			InputAndFeedback.Require(list.Count <= 64, "Animal appearance is too complex to preserve safely.");
			return list.ToArray();
		}

		internal static void Apply(Character actor, PackedAnimalState state)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			if (actor.GetLevel() != state.Level)
			{
				return;
			}
			SkinnedMeshRenderer[] componentsInChildren = ((Component)actor).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			AnimalTint[] tints = state.Tints;
			foreach (AnimalTint tint in tints)
			{
				InputAndFeedback.Require(tint.Renderer < componentsInChildren.Length && tint.Material < ((Renderer)componentsInChildren[tint.Renderer]).sharedMaterials.Length, "Animal appearance layout changed. Check the journal.");
				SkinnedMeshRenderer val = componentsInChildren[tint.Renderer];
				MaterialPropertyBlock block = new MaterialPropertyBlock();
				((Renderer)val).GetPropertyBlock(block, tint.Material);
				for (int j = 0; j < Floats.Length; j++)
				{
					if ((tint.Flags & (1 << j)) != 0)
					{
						block.SetFloat(Floats[j], tint.Values[j]);
					}
				}
				Color(ColorId, 8, 3);
				Color(SkinId, 16, 7);
				((Renderer)val).SetPropertyBlock(block, tint.Material);
				void Color(int id, int flag, int offset)
				{
					//IL_0051: Unknown result type (might be due to invalid IL or missing references)
					if ((tint.Flags & flag) != 0)
					{
						block.SetColor(id, new Color(tint.Values[offset], tint.Values[offset + 1], tint.Values[offset + 2], tint.Values[offset + 3]));
					}
				}
			}
		}
	}
	internal static class AnimalSnapshot
	{
		private static double Seconds(long now, long before)
		{
			if (before <= 0)
			{
				return 0.0;
			}
			return Math.Max(0.0, (double)(now - before) / 10000000.0);
		}

		internal static PackedAnimalState Capture(Character actor, AnimalType type)
		{
			//IL_0043: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ((Component)actor).GetComponent<ZNetView>().GetZDO();
			long ticks = ZNet.instance.GetTime().Ticks;
			Tameable component = ((Component)actor).GetComponent<Tameable>();
			Procreation component2 = ((Component)actor).GetComponent<Procreation>();
			long num = zDO.GetLong(ZDOVars.s_pregnant, 0L);
			Vector3 localScale = ((Component)actor).transform.localScale;
			string text = zDO.GetString("PortableShips.AnimalIdentity", "");
			Guid result;
			PackedAnimalState packedAnimalState = new PackedAnimalState
			{
				Prefab = type.Prefab,
				Identity = (Guid.TryParseExact(text, "N", out result) ? text : TransactionJournal.NewId()),
				Name = zDO.GetString(ZDOVars.s_tamedName, ""),
				Author = zDO.GetString(ZDOVars.s_tamedNameAuthor, ""),
				Health = actor.GetHealth(),
				MaxHealth = actor.GetMaxHealth(),
				Level = actor.GetLevel(),
				Saddle = zDO.GetBool(ZDOVars.s_haveSaddleHash, false),
				HorseMaterial = (AnimalRules.Horse(type.Prefab) ? zDO.GetInt("HorseMaterial", -1) : (-1)),
				HorseArmor = (AnimalRules.Horse(type.Prefab) && zDO.GetBool("HaveArmor", false)),
				HorseWaiting = (AnimalRules.Horse(type.Prefab) && zDO.GetBool("IsWaiting", false)),
				ScaleX = localScale.x,
				ScaleY = localScale.y,
				ScaleZ = localScale.z,
				RandomSeed = zDO.GetInt("RandMatSeed", -1),
				AgeSeconds = Seconds(ticks, zDO.GetLong(ZDOVars.s_spawnTime, 0L)),
				FedSeconds = ((Object.op_Implicit((Object)(object)component) && zDO.GetLong(ZDOVars.s_tameLastFeeding, 0L) > 0) ? Mathf.Clamp(component.m_fedDuration - (float)Seconds(ticks, zDO.GetLong(ZDOVars.s_tameLastFeeding, 0L)), 0f, component.m_fedDuration) : 0f),
				PregnancySeconds = ((Object.op_Implicit((Object)(object)component2) && num > 0) ? Mathf.Clamp(component2.m_pregnancyDuration - (float)Seconds(ticks, num), 0f, component2.m_pregnancyDuration) : (-1f)),
				LovePoints = zDO.GetInt(ZDOVars.s_lovePoints, 0),
				Stamina = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_saddle)) ? zDO.GetFloat(ZDOVars.s_stamina, component.m_saddle.GetMaxStamina()) : 0f),
				Tints = AnimalAppearance.Capture(actor)
			};
			if (AnimalRules.Horse(type.Prefab))
			{
				AnimalModCompatibility.RequireHorseCoat(packedAnimalState.HorseMaterial);
			}
			InputAndFeedback.Require(packedAnimalState.RandomSeed >= 0 || ((Component)actor).GetComponentsInChildren<RandomMaterialValues>(true).Length == 0, "Animal appearance is still initializing. Wait a moment and try again.");
			InputAndFeedback.Require(packedAnimalState.Valid, "Animal has unsupported health, name or appearance data. Animal unchanged.");
			return packedAnimalState;
		}

		private static long Before(long now, double seconds)
		{
			return Math.Max(1L, now - (long)(seconds * 10000000.0));
		}

		internal static void Preflight(PackedAnimalState state, GameObject prefab)
		{
			AnimalModCompatibility.RequireVersion(state.Prefab);
			if (AnimalRules.Horse(state.Prefab))
			{
				AnimalModCompatibility.RequireHorseCoat(state.HorseMaterial);
			}
			Tameable component = prefab.GetComponent<Tameable>();
			InputAndFeedback.Require(!state.Saddle || (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_saddle) && Object.op_Implicit((Object)(object)component.m_saddleItem)), "Saved saddle is unavailable on this animal prefab.");
			InputAndFeedback.Require(state.PregnancySeconds < 0f || Object.op_Implicit((Object)(object)prefab.GetComponent<Procreation>()), "Saved breeding state is unavailable on this animal prefab.");
			SkinnedMeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			AnimalTint[] tints = state.Tints;
			foreach (AnimalTint animalTint in tints)
			{
				InputAndFeedback.Require(animalTint.Renderer < componentsInChildren.Length && animalTint.Material < ((Renderer)componentsInChildren[animalTint.Renderer]).sharedMaterials.Length, "Animal appearance layout changed. Keep the packed item and restore compatible animal assets.");
			}
		}

		internal static void Restore(ZDO zdo, PackedAnimalState state, GameObject prefab)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			long ticks = ZNet.instance.GetTime().Ticks;
			zdo.Set(ZDOVars.s_tamed, true);
			zdo.Set(ZDOVars.s_level, state.Level, false);
			zdo.Set(ZDOVars.s_health, state.Health);
			zdo.Set(ZDOVars.s_maxHealth, state.MaxHealth);
			zdo.Set(ZDOVars.s_tamedName, state.Name);
			zdo.Set(ZDOVars.s_tamedNameAuthor, state.Author);
			if (AnimalRules.Horse(state.Prefab))
			{
				zdo.Set("HorseMaterial", state.HorseMaterial);
				zdo.Set("HaveArmor", state.HorseArmor);
				zdo.Set("IsWaiting", state.HorseWaiting);
			}
			zdo.Set(ZDOVars.s_haveSaddleHash, state.Saddle);
			zdo.Set(ZDOVars.s_stamina, state.Stamina);
			zdo.Set("PortableShips.AnimalIdentity", state.Identity);
			zdo.Set("PortableShips.AnimalScale", new Vector3(state.ScaleX, state.ScaleY, state.ScaleZ));
			zdo.Set("PortableShips.AnimalAppearance", state.Encode());
			if (state.RandomSeed >= 0)
			{
				zdo.Set("RandMatSeed", state.RandomSeed);
			}
			zdo.Set(ZDOVars.s_spawnTime, Before(ticks, state.AgeSeconds));
			zdo.Set(ZDOVars.s_follow, "");
			zdo.Set(ZDOVars.s_patrol, false);
			Tameable component = prefab.GetComponent<Tameable>();
			Procreation component2 = prefab.GetComponent<Procreation>();
			if (Object.op_Implicit((Object)(object)component))
			{
				zdo.Set(ZDOVars.s_tameLastFeeding, Before(ticks, Math.Max(0f, component.m_fedDuration - state.FedSeconds)));
			}
			zdo.Set(ZDOVars.s_lovePoints, state.LovePoints, false);
			if (state.PregnancySeconds >= 0f)
			{
				InputAndFeedback.Require(Object.op_Implicit((Object)(object)component2), "This animal no longer supports its saved breeding state.");
				zdo.Set(ZDOVars.s_pregnant, Before(ticks, Math.Max(0f, component2.m_pregnancyDuration - state.PregnancySeconds)));
			}
		}

		internal static void Verify(Character actor, PackedAnimalState state)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ((Component)actor).GetComponent<ZNetView>().GetZDO();
			InputAndFeedback.Require(actor.IsTamed() && actor.GetLevel() == state.Level && Mathf.Abs(actor.GetHealth() - state.Health) < 0.001f && Mathf.Abs(actor.GetMaxHealth() - state.MaxHealth) < 0.001f && zDO.GetBool(ZDOVars.s_haveSaddleHash, false) == state.Saddle && zDO.GetString(ZDOVars.s_tamedName, "") == state.Name && zDO.GetString("PortableShips.AnimalIdentity", "") == state.Identity && zDO.GetInt("RandMatSeed", -1) == state.RandomSeed && Vector3.Distance(((Component)actor).transform.localScale, new Vector3(state.ScaleX, state.ScaleY, state.ScaleZ)) < 0.001f, "Animal restoration could not be verified. Keep the pending item and consult the journal.");
			if (AnimalRules.Horse(state.Prefab))
			{
				InputAndFeedback.Require(zDO.GetInt("HorseMaterial", -1) == state.HorseMaterial && zDO.GetBool("HaveArmor", false) == state.HorseArmor && zDO.GetBool("IsWaiting", false) == state.HorseWaiting, "Horse coat/armor/wait restoration failed. Consult the journal.");
			}
			AnimalAppearance.Apply(actor, state);
		}
	}
	internal static class Beastbinding
	{
		[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
		private static class WitchOffer
		{
			private static void Postfix(Trader __instance, List<TradeItem> __result)
			{
				//IL_004c: 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_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Expected O, but got Unknown
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Expected O, but got Unknown
				Player localPlayer = Player.m_localPlayer;
				ZNetView componentInParent = ((Component)__instance).GetComponentInParent<ZNetView>();
				if (Object.op_Implicit((Object)(object)localPlayer) && !Learned(localPlayer) && Object.op_Implicit((Object)(object)componentInParent) && componentInParent.IsValid() && componentInParent.GetZDO().GetPrefab() == StringExtensionMethods.GetStableHashCode("BogWitch"))
				{
					if (offer == null)
					{
						offer = new TradeItem
						{
							m_price = 1000,
							m_stack = 1,
							m_buyKey = "PortableShips.Beastbinding",
							m_name = "Beastbinding",
							m_requiredGlobalKey = "",
							m_incrementKey = "PortableShips.BeastbindingRank",
							m_incrementAmount = 1,
							m_tooltip = "Permanent character ability. Approach a tamed animal, aim at it and press P to shrink it. Health, stars, saddle, appearance and name are preserved. Use the packed animal from your hotbar to release it.",
							m_buyPlayerEffects = new EffectList
							{
								m_effectPrefabs = Array.Empty<EffectData>()
							},
							m_levelUpEffect = true
						};
					}
					offer.m_icon = AnimalIcons.For(AnimalIdentification.Types.First((AnimalType t) => t.Prefab == "Wolf"));
					if (!__result.Any((TradeItem i) => i.m_buyKey == "PortableShips.Beastbinding"))
					{
						__result.Add(offer);
					}
				}
			}
		}

		[HarmonyPatch(typeof(StoreGui), "BuySelectedItem")]
		private static class NativePurchase
		{
			private static bool Prefix(TradeItem ___m_selectedItem)
			{
				if (___m_selectedItem != null && !(___m_selectedItem.m_buyKey != "PortableShips.Beastbinding"))
				{
					return !Learned(Player.m_localPlayer);
				}
				return true;
			}

			private static void Postfix()
			{
				if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					Publish(Player.m_localPlayer);
				}
			}
		}

		internal const string Key = "PortableShips.Beastbinding";

		internal const string Proof = "PortableShips.BeastbindingLearned";

		internal const int Price = 1000;

		private static TradeItem? offer;

		internal static bool Learned(Player player)
		{
			if (Object.op_Implicit((Object)(object)player))
			{
				return ((Humanoid)player).HaveUniqueKey("PortableShips.Beastbinding");
			}
			return false;
		}

		internal static void Publish(Player player)
		{
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner() && (Object)(object)player == (Object)(object)Player.m_localPlayer)
			{
				component.GetZDO().Set("PortableShips.BeastbindingLearned", Learned(player));
			}
		}
	}
	internal static class BoonCostPlan
	{
		internal static readonly string[] Prefabs = new string[3] { "Eitr", "YggdrasilWood", "JuteBlue" };

		internal static readonly int[] Amounts = new int[3] { 20, 20, 10 };

		internal static bool TryCreate(IReadOnlyList<string> prefabs, IReadOnlyList<int> stacks, out Dictionary<int, int> spend)
		{
			return TryCreate(prefabs, stacks, Prefabs, Amounts, out spend);
		}

		internal static bool TryCreate(IReadOnlyList<string> prefabs, IReadOnlyList<int> stacks, IReadOnlyList<string> costs, IReadOnlyList<int> amounts, out Dictionary<int, int> spend)
		{
			spend = new Dictionary<int, int>();
			if (prefabs.Count != stacks.Count || costs.Count != amounts.Count)
			{
				return false;
			}
			for (int i = 0; i < costs.Count; i++)
			{
				int num = amounts[i];
				if (num <= 0)
				{
					spend.Clear();
					return false;
				}
				for (int j = 0; j < prefabs.Count; j++)
				{
					if (num <= 0)
					{
						break;
					}
					if (!(prefabs[j] != costs[i]) && stacks[j] > 0)
					{
						int num2 = Math.Min(num, stacks[j]);
						spend.Add(j, num2);
						num -= num2;
					}
				}
				if (num != 0)
				{
					spend.Clear();
					return false;
				}
			}
			return true;
		}
	}
	internal sealed class BoonRuneVisual : MonoBehaviour
	{
		internal sealed class HullSurface : IDisposable
		{
			private readonly GameObject helper;

			internal readonly Collider[] Colliders;

			internal HullSurface(Ship ship)
			{
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Expected O, but got Unknown
				//IL_006f: 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_0095: Unknown result type (might be due to invalid IL or missing references)
				MeshRenderer val = VisibleHull(ship);
				MeshFilter val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<MeshFilter>() : null);
				InputAndFeedback.Require(Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.sharedMesh), "Visible wooden hull mesh unavailable for rune projection.");
				helper = new GameObject("PortableShips.RuneProjectionQuery")
				{
					hideFlags = (HideFlags)61,
					layer = 2
				};
				try
				{
					helper.transform.SetPositionAndRotation(((Component)val2).transform.position, ((Component)val2).transform.rotation);
					helper.transform.localScale = ((Component)val2).transform.lossyScale;
					MeshCollider val3 = helper.AddComponent<MeshCollider>();
					val3.sharedMesh = val2.sharedMesh;
					Colliders = (Collider[])(object)new Collider[1] { (Collider)val3 };
					Physics.SyncTransforms();
				}
				catch
				{
					helper.SetActive(false);
					Object.Destroy((Object)(object)helper);
					throw;
				}
			}

			public void Dispose()
			{
				helper.SetActive(false);
				Object.Destroy((Object)(object)helper);
			}
		}

		internal const float SurfaceClearance = 0.022f;

		private static Material? engraving;

		private static Texture2D? mask;

		private readonly List<Mesh> meshes = new List<Mesh>();

		private readonly List<GameObject> visuals = new List<GameObject>();

		private MeshRenderer? boundHull;

		private bool built;

		private float retryAt;

		internal static void EnsureAvailable(Ship ship)
		{
			Material();
			int[] array = new int[2] { -1, 1 };
			foreach (int side in array)
			{
				if (FindAnchor(ship, side, out var _))
				{
					return;
				}
			}
			InputAndFeedback.Require(condition: false, "No suitable hull surface beside the helm for the rune engraving.");
		}

		private static Material Material()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Expected O, but got Unknown
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)engraving))
			{
				return engraving;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("dvergrtown_secretdoor");
			object obj;
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				obj = null;
			}
			else
			{
				Transform obj2 = prefab.transform.Find("secretdoor/hgih");
				obj = ((obj2 != null) ? ((Component)obj2).GetComponent<MeshRenderer>() : null);
			}
			MeshRenderer val = (MeshRenderer)obj;
			Texture2D val2 = (Texture2D)(Object.op_Implicit((Object)(object)val) ? /*isinst with value type is only supported in some contexts*/: null);
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)val2), "Infested-mine secret-door rune asset unavailable; no upgrade materials were spent.");
			Shader val3 = Shader.Find("Unlit/Transparent") ?? Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default");
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)val3), "Rune engraving shader unavailable; no upgrade materials were spent.");
			Texture2D val4 = AssetUtils.DuplicateTexture(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height));
			try
			{
				Color[] pixels = val4.GetPixels();
				int num = ((Texture)val4).width;
				int num2 = ((Texture)val4).height;
				int num3 = -1;
				int num4 = -1;
				for (int i = 0; i < ((Texture)val4).height; i++)
				{
					for (int j = 0; j < ((Texture)val4).width; j++)
					{
						if (((Color)(ref pixels[i * ((Texture)val4).width + j])).maxColorComponent > 0.03f)
						{
							num = Math.Min(num, j);
							num3 = Math.Max(num3, j);
							num2 = Math.Min(num2, i);
							num4 = Math.Max(num4, i);
						}
					}
				}
				InputAndFeedback.Require(num3 >= num && num4 >= num2, "Secret-door rune mask is empty; upgrade cancelled.");
				int num5 = num3 - num + 5;
				int num6 = num4 - num2 + 5;
				mask = new Texture2D(num5, num6, (TextureFormat)4, true)
				{
					name = "PortableShips.BoonRuneMask",
					wrapMode = (TextureWrapMode)1,
					filterMode = (FilterMode)2,
					anisoLevel = 8,
					hideFlags = (HideFlags)32
				};
				Color[] array = Enumerable.Repeat<Color>(new Color(0.58f, 0.42f, 0.24f, 0f), num5 * num6).ToArray();
				for (int k = 2; k < num6 - 2; k++)
				{
					for (int l = 2; l < num5 - 2; l++)
					{
						float maxColorComponent = ((Color)(ref pixels[(num2 + k - 2) * ((Texture)val4).width + num + l - 2])).maxColorComponent;
						array[k * num5 + l] = new Color(0.58f, 0.42f, 0.24f, maxColorComponent);
					}
				}
				mask.SetPixels(array);
				mask.Apply(true, true);
				engraving = new Material(val3)
				{
					name = "PortableShips.BoonEngraving",
					mainTexture = (Texture)(object)mask,
					hideFlags = (HideFlags)32
				};
				engraving.renderQueue = 3000;
				if (engraving.HasProperty("_Color"))
				{
					engraving.SetColor("_Color", Color.white);
				}
				return engraving;
			}
			finally
			{
				Object.Destroy((Object)(object)val4);
			}
		}

		internal static MeshRenderer? VisibleHull(Ship ship)
		{
			return ((IEnumerable<MeshRenderer>)((Component)ship).GetComponentsInChildren<MeshRenderer>()).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer r) => ((Renderer)r).enabled && ((Object)r).name == "hull" && Object.op_Implicit((Object)(object)((Component)r).transform.parent) && (((Object)((Component)r).transform.parent).name.StartsWith("hull_", StringComparison.Ordinal) || ((Object)((Component)r).transform.parent).name.StartsWith("visual_", StringComparison.Ordinal))));
		}

		internal static bool RayHull(Collider[] hull, Ray ray, float distance, out RaycastHit nearest)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			nearest = default(RaycastHit);
			bool flag = false;
			RaycastHit val = default(RaycastHit);
			for (int i = 0; i < hull.Length; i++)
			{
				if (hull[i].Raycast(ray, ref val, distance) && (!flag || ((RaycastHit)(ref val)).distance < ((RaycastHit)(ref nearest)).distance))
				{
					nearest = val;
					flag = true;
				}
			}
			return flag;
		}

		private static bool FindAnchor(Ship ship, int side, out RaycastHit hit)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			hit = default(RaycastHit);
			if (!Object.op_Implicit((Object)(object)ship.m_shipControlls) || !Object.op_Implicit((Object)(object)ship.m_shipControlls.m_attachPoint))
			{
				return false;
			}
			Vector3 val = ((Component)ship).transform.InverseTransformPoint(ship.m_shipControlls.m_attachPoint.position);
			using HullSurface hullSurface = new HullSurface(ship);
			Collider[] colliders = hullSurface.Colliders;
			for (float num = val.y + 2.2f; num >= val.y - 0.25f; num -= 0.08f)
			{
				float[] array = new float[5] { -0.35f, 0f, 0.5f, 1f, 1.6f };
				foreach (float num2 in array)
				{
					Vector3 val2 = ((Component)ship).transform.TransformPoint(new Vector3((float)side * 30f, num, val.z + num2));
					if (RayHull(colliders, new Ray(val2, ((Component)ship).transform.right * (float)(-side)), 30f, out hit) && Vector3.Dot(((RaycastHit)(ref hit)).normal, ((Component)ship).transform.right * (float)side) > 0.3f && SkidbladnirBoon.NearHelm(ship, ((RaycastHit)(ref hit)).point) && Project(ship, hit, colliders, out Vector3[] _, out Vector2[] _, out int[] _))
					{
						return true;
					}
				}
			}
			return false;
		}

		private void Update()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < retryAt || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			retryAt = Time.time + 3f;
			Ship component = ((Component)this).GetComponent<Ship>();
			if (!SkidbladnirBoon.IsInstalled(((Component)this).GetComponent<ZNetView>()))
			{
				return;
			}
			MeshRenderer val = VisibleHull(component);
			if (built && (Object)(object)val == (Object)(object)boundHull)
			{
				return;
			}
			Clear();
			try
			{
				Material val2 = Material();
				int[] array = new int[2] { -1, 1 };
				foreach (int side in array)
				{
					if (FindAnchor(component, side, out var hit))
					{
						Build(component, hit, val2);
					}
				}
				built = meshes.Count > 0;
				if (!built)
				{
					throw new InvalidOperationException("No rune engraving anchor found beside the helm.");
				}
				boundHull = val;
				PortableShipsPlugin.Instance.LogInfo($"Boon runes created: ship={((Object)component).name} sides={meshes.Count} hull={((Object)((Component)val).transform.parent).name} shader={((Object)val2.shader).name}");
			}
			catch (Exception ex)
			{
				PortableShipsPlugin.Instance.Error("Boon rune display: " + ex.Message);
			}
		}

		private void Build(Ship ship, RaycastHit anchor, Material material)
		{
			//IL_0008: 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_0033: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			using HullSurface hullSurface = new HullSurface(ship);
			if (Project(ship, anchor, hullSurface.Colliders, out Vector3[] vertices, out Vector2[] uv, out int[] indices))
			{
				Mesh val = new Mesh
				{
					name = "PortableShips.SkidbladnirRunes"
				};
				val.vertices = vertices;
				val.uv = uv;
				val.triangles = indices;
				val.RecalculateNormals();
				val.RecalculateBounds();
				meshes.Add(val);
				GameObject val2 = new GameObject("SkidbladnirBoon_Engraving");
				val2.transform.SetParent(((Component)ship).transform, false);
				val2.AddComponent<MeshFilter>().sharedMesh = val;
				MeshRenderer obj = val2.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = material;
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)obj).receiveShadows = false;
				visuals.Add(val2);
			}
		}

		private static bool Project(Ship ship, RaycastHit anchor, Collider[] hull, out Vector3[] vertices, out Vector2[] uv, out int[] indices)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_002e: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 normal = ((RaycastHit)(ref anchor)).normal;
			Vector3 val = Vector3.Cross(((Component)ship).transform.up, normal);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			val = Vector3.Cross(normal, normalized);
			Vector3 normalized2 = ((Vector3)(ref val)).normalized;
			vertices = (Vector3[])(object)new Vector3[429];
			uv = (Vector2[])(object)new Vector2[vertices.Length];
			indices = Array.Empty<int>();
			List<int> list = new List<int>();
			for (int i = 0; i <= 12; i++)
			{
				for (int j = 0; j <= 32; j++)
				{
					int num = i * 33 + j;
					uv[num] = new Vector2((float)j / 32f, (float)i / 12f);
					Vector3 val2 = ((RaycastHit)(ref anchor)).point + normalized * ((uv[num].x - 0.5f) * 1.1f) + normalized2 * ((uv[num].y - 0.5f) * 0.44f);
					if (!RayHull(hull, new Ray(val2 + normal, -normal), 2f, out var nearest))
					{
						return false;
					}
					vertices[num] = ((Component)ship).transform.InverseTransformPoint(((RaycastHit)(ref nearest)).point + ((RaycastHit)(ref nearest)).normal * 0.022f);
					if (j < 32 && i < 12)
					{
						list.AddRange(new int[6]
						{
							num,
							num + 1,
							num + 32 + 2,
							num,
							num + 32 + 2,
							num + 32 + 1
						});
					}
				}
			}
			indices = list.ToArray();
			return true;
		}

		private void Clear()
		{
			foreach (GameObject visual in visuals)
			{
				if (Object.op_Implicit((Object)(object)visual))
				{
					visual.SetActive(false);
					Object.Destroy((Object)(object)visual);
				}
			}
			foreach (Mesh mesh in meshes)
			{
				if (Object.op_Implicit((Object)(object)mesh))
				{
					Object.Destroy((Object)(object)mesh);
				}
			}
			visuals.Clear();
			meshes.Clear();
			built = false;
			boundHull = null;
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
	internal static class DeploymentRecovery
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			internal void <Register>b__0_0(ConsoleEventArgs _)
			{
				PortableShipsPlugin.Instance.Run(Begin);
			}
		}

		internal static void Register()
		{
			//IL_0033: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate
				{
					PortableShipsPlugin.Instance.Run(Begin);
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("portableships_recover", "Aim at an interrupted summoned ship with its pending item in your inventory. Verifies it and completes deployment; never spawns another ship.", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static void Begin()
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			Player player = Player.m_localPlayer;
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)ZNet.instance) && Object.op_Implicit((Object)(object)ZNetScene.instance), "Enter the world containing the interrupted ship first.");
			CheckPlayer(player);
			Ship ship = ShipPackingService.AimedShip(player);
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)ship), "Stand outside and aim at the interrupted ship's hull.");
			ZNetView view = ((Component)ship).GetComponent<ZNetView>();
			ShipType type = ShipIdentification.FromShip(ship);
			ItemData[] array = (from i in ((Humanoid)player).GetInventory().GetAllItems()
				where ShipIdentification.FromItem(i) == type && DeploymentRecoveryPolicy.Matches(i.m_customData, i.m_stack, type.Prefab, type.Prefab, view.GetZDO().GetString("PortableShips.Transaction", ""))
				select i).ToArray();
			InputAndFeedback.Require(array.Length == 1, "Need exactly one matching pending item and its locked ship in this world. Nothing changed.");
			ItemData item = array[0];
			InputAndFeedback.Require(PackedShipPayload.TryRead(new Dictionary<string, string>(item.m_customData) { ["PortableShips.State"] = "ready" }, type.Prefab, item.m_stack, out float _, out string error), error);
			ShipAddonAPI.Validate(item);
			UpgradePayload upgrades = LongshipUpgradesCompatibility.Read(item, type);
			InputAndFeedback.Require(PrivateArea.CheckAccess(((Component)ship).transform.position, 0f, true, false), "A ward prevents recovery here.");
			ShipPackingAccess access = ((Component)ship).GetComponent<ShipPackingAccess>();
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)access), "Ship still initializing.");
			string tx = item.m_customData["PortableShips.Transaction"];
			ShipCast.Start(Resume(), delegate
			{
				try
				{
					if (Object.op_Implicit((Object)(object)access))
					{
						access.Release(tx);
					}
				}
				finally
				{
					PortableShipsPlugin.Instance.Busy = false;
				}
			});
			IEnumerator Resume()
			{
				TransactionJournal.Write(tx, "deploy-recovery-request", ((object)Unsafe.As<ZDOID, ZDOID>(ref view.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString());
				access.BeginRecoveryRequest(tx);
				float deadline = Time.realtimeSinceStartup + 5f;
				while (!ShipPackingAccess.OwnsReservation(view, tx))
				{
					CheckPlayer(player);
					InputAndFeedback.Require(Object.op_Implicit((Object)(object)ship) && (Object)(object)ShipPackingService.AimedShip(player) == (Object)(object)ship, "Keep aiming at the same hull during recovery.");
					InputAndFeedback.Require(string.IsNullOrEmpty(access.Rejection), access.Rejection);
					InputAndFeedback.Require(Time.realtimeSinceStartup < deadline, "Recovery authority timed out. Nothing consumed.");
					yield return null;
				}
				IEnumerator completion = ShipDeploymentService.Complete(player, ((Humanoid)player).GetInventory(), item, view, upgrades, type, tx);
				while (completion.MoveNext())
				{
					yield return completion.Current;
				}
			}
		}

		private static void CheckPlayer(Player player)
		{
			InputAndFeedback.Require(Object.op_Implicit((Object)(object)player) && (Object)(object)player == (Object)(object)Player.m_localPlayer && !((Character)player).IsDead() && !((Character)player).IsTeleporting() && !((Character)player).InAttack() && !((Character)player).InDodge() && player.GetActionQueueCount() == 0, "Finish your current action before recovering the ship.");
		}
	}
	internal static class DeploymentRecoveryPolicy
	{
		internal static bool Matches(IDictionary<string, string> data, int stack, string prefab, string actualPrefab, string shipLock)
		{
			if (stack == 1 && data.TryGetValue("PortableShips.State", out string value) && value == "deploying" && data.TryGetValue("PortableShips.Transaction", out string value2) && Guid.TryParseExact(value2, "N", out var _) && data.TryGetValue("PortableShips.Ship", out string value3) && value3 == prefab && actualPrefab == prefab)
			{
				return shipLock == "deploy:" + value2;
			}
			return false;
		}
	}
	internal sealed class HullInscription : MonoBehaviour
	{
		internal TMP_FontAsset Font;

		internal MeshFilter BoardSource;

		private TextMeshPro? generator;

		private readonly List<GameObject> parts = new List<GameObject>();

		private readonly List<Mesh> meshes = new List<Mesh>();

		private readonly List<Material> materials = new List<Material>();

		private string? lastName;

		private MeshRenderer? lastHull;