Decompiled source of CustomCreatureCarry v0.2.0

plugins/CustomCreatureCarry/CustomCreatureCarry.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomCreatureCarry")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+96427bc0453b43195d02e1fe34f69827c1acb934")]
[assembly: AssemblyProduct("CustomCreatureCarry")]
[assembly: AssemblyTitle("CustomCreatureCarry")]
[assembly: AssemblyVersion("0.2.0.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 CustomCreatureCarry
{
	internal static class BreedingHover
	{
		private static Procreation? cachedSubject;

		private static float nextScan;

		private static string nearbyStatus = "Checking nearby creatures";

		internal static string GetText(Tameable tameable)
		{
			if (!Plugin.ShowBreedingStatus.Value || !tameable.IsTamed() || !Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return "";
			}
			Procreation component = ((Component)tameable).GetComponent<Procreation>();
			ZNetView component2 = ((Component)tameable).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || !component2.IsValid())
			{
				return "";
			}
			ZDO zDO = component2.GetZDO();
			bool flag = Plugin.Network.IsCarried(zDO);
			long num = zDO.GetLong(ZDOVars.s_pregnant, 0L);
			if (num != 0L)
			{
				string text = "Yes";
				double num2 = component.m_pregnancyDuration;
				if (num2 > 0.0 && !double.IsInfinity(num2) && !double.IsNaN(num2))
				{
					int num3 = Percentage(((double)ZNet.instance.GetTime().Ticks - (double)num) / 10000000.0, num2);
					text += ((num3 >= 100) ? " (100% - birth pending)" : $" ({num3}%)");
				}
				return "\nPregnant: <color=#FFC0CB>" + text + "</color>" + (flag ? "\nBreeding: Birth paused while carried" : "");
			}
			int num4 = Math.Max(0, zDO.GetInt(ZDOVars.s_lovePoints, 0));
			int requiredLovePoints = component.m_requiredLovePoints;
			string text2 = ((requiredLovePoints > 0) ? $"{Percentage(num4, requiredLovePoints)}% ({num4}/{requiredLovePoints})" : $"{num4} love points");
			string text3 = (flag ? "Paused while carried" : (zDO.GetBool(ZDOVars.s_alert, false) ? "Frightened" : ((!tameable.IsHungry()) ? NearbyStatus(component, zDO) : "Hungry - needs food")));
			string text4 = ((text3 == "Ready - waiting for mating") ? "#98E698" : "#FFD479");
			return "\nPregnant: No\nMating: <color=#FFD479>" + text2 + "</color>\nBreeding: <color=" + text4 + ">" + text3 + "</color>";
		}

		private static int Percentage(double amount, double total)
		{
			return (int)Math.Floor(Math.Max(0.0, Math.Min(100.0, amount / total * 100.0)));
		}

		private static string NearbyStatus(Procreation subject, ZDO zdo)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00b7: 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)
			if ((Object)(object)cachedSubject == (Object)(object)subject && Time.unscaledTime < nextScan)
			{
				return nearbyStatus;
			}
			cachedSubject = subject;
			nextScan = Time.unscaledTime + 0.5f;
			nearbyStatus = "Status unavailable";
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)subject.m_offspring))
			{
				return nearbyStatus;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab());
			GameObject prefab2 = ZNetScene.instance.GetPrefab(Utils.GetPrefabName(subject.m_offspring));
			if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab2))
			{
				return nearbyStatus;
			}
			Vector3 position = ((Component)subject).transform.position;
			int num = SpawnSystem.GetNrOfInstances(prefab, position, subject.m_totalCheckRange, false, false) + SpawnSystem.GetNrOfInstances(prefab2, position, subject.m_totalCheckRange, false, false);
			if (num >= subject.m_maxCreatures)
			{
				return nearbyStatus = $"Crowded ({num}/{subject.m_maxCreatures} nearby)";
			}
			if (!Object.op_Implicit((Object)(object)subject.m_noPartnerOffspring))
			{
				int nrOfInstances = SpawnSystem.GetNrOfInstances(Object.op_Implicit((Object)(object)subject.m_seperatePartner) ? subject.m_seperatePartner : prefab, position, subject.m_partnerCheckRange, false, true);
				int num2 = (Object.op_Implicit((Object)(object)subject.m_seperatePartner) ? 1 : 2);
				if (nrOfInstances < num2)
				{
					return nearbyStatus = "No fed, non-pregnant partner nearby";
				}
			}
			return nearbyStatus = "Ready - waiting for mating";
		}
	}
	public sealed class CarriedCreature : MonoBehaviour
	{
		private static readonly HashSet<CarriedCreature> instances = new HashSet<CarriedCreature>();

		private readonly List<Behaviour> disabled = new List<Behaviour>();

		private readonly List<Collider> colliders = new List<Collider>();

		private ZNetView view;

		private Character character;

		private Rigidbody? body;

		private bool frozen;

		private bool wasKinematic;

		private bool usedGravity;

		private bool wasDetectingCollisions;

		internal Vector3 OriginalScale { get; private set; }

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			view = ((Component)this).GetComponent<ZNetView>();
			character = ((Component)this).GetComponent<Character>();
			body = ((Component)this).GetComponent<Rigidbody>();
			OriginalScale = ((Component)this).transform.localScale;
			instances.Add(this);
		}

		private void Start()
		{
			Apply();
		}

		private void LateUpdate()
		{
			Apply();
		}

		internal void Apply()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0072: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid() || Plugin.Network == null)
			{
				return;
			}
			ZDO zDO = view.GetZDO();
			if (!Plugin.Network.IsCarried(zDO))
			{
				if (frozen)
				{
					CarryState state = Plugin.Network.GetState(zDO.m_uid);
					((Component)this).transform.SetPositionAndRotation((state != null && !state.Active) ? state.Position : zDO.GetPosition(), (state != null && !state.Active) ? state.Rotation : zDO.GetRotation());
					Restore();
				}
				return;
			}
			if (!frozen)
			{
				Freeze();
			}
			ZDOID val = Plugin.Network.GetState(zDO.m_uid)?.Player ?? zDO.GetZDOID("CCC_carrier_v1");
			GameObject val2 = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(val) : null);
			Vector3 val3 = (Object.op_Implicit((Object)(object)val2) ? (val2.transform.position + Vector3.up * 2.2f + val2.transform.forward * 0.2f) : zDO.GetPosition());
			Quaternion val4 = (Object.op_Implicit((Object)(object)val2) ? val2.transform.rotation : zDO.GetRotation());
			((Component)this).transform.SetPositionAndRotation(val3, val4);
			if (Object.op_Implicit((Object)(object)body))
			{
				body.position = val3;
				body.rotation = val4;
			}
		}

		private void Freeze()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			frozen = true;
			OriginalScale = ((Component)this).transform.localScale;
			disabled.Clear();
			colliders.Clear();
			Disable((Behaviour)(object)character);
			BaseAI[] components = ((Component)this).GetComponents<BaseAI>();
			foreach (BaseAI component in components)
			{
				Disable((Behaviour)(object)component);
			}
			Disable((Behaviour)(object)((Component)this).GetComponent<ZSyncTransform>());
			Disable((Behaviour)(object)((Component)this).GetComponent<Tameable>());
			if (Object.op_Implicit((Object)(object)body))
			{
				wasKinematic = body.isKinematic;
				usedGravity = body.useGravity;
				wasDetectingCollisions = body.detectCollisions;
				if (!body.isKinematic)
				{
					body.linearVelocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
				}
				body.isKinematic = true;
				body.useGravity = false;
				body.detectCollisions = false;
			}
			Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if (val.enabled)
				{
					colliders.Add(val);
					val.enabled = false;
				}
			}
			((Component)this).transform.localScale = OriginalScale * 0.25f;
		}

		private void Disable(Behaviour component)
		{
			if (Object.op_Implicit((Object)(object)component) && component.enabled)
			{
				disabled.Add(component);
				component.enabled = false;
			}
		}

		private void Restore()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!frozen)
			{
				return;
			}
			frozen = false;
			((Component)this).transform.localScale = OriginalScale;
			if (Object.op_Implicit((Object)(object)body))
			{
				body.position = ((Component)this).transform.position;
				body.rotation = ((Component)this).transform.rotation;
				body.isKinematic = wasKinematic;
				body.useGravity = usedGravity;
				body.detectCollisions = wasDetectingCollisions;
				if (!body.isKinematic)
				{
					body.linearVelocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
				}
			}
			foreach (Collider collider in colliders)
			{
				if (Object.op_Implicit((Object)(object)collider))
				{
					collider.enabled = true;
				}
			}
			foreach (Behaviour item in disabled)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					item.enabled = true;
				}
			}
			colliders.Clear();
			disabled.Clear();
		}

		internal static void RefreshAll()
		{
			CarriedCreature[] array = instances.ToArray();
			foreach (CarriedCreature carriedCreature in array)
			{
				if (Object.op_Implicit((Object)(object)carriedCreature))
				{
					carriedCreature.Apply();
				}
			}
		}

		internal static void RestoreAll()
		{
			CarriedCreature[] array = instances.ToArray();
			foreach (CarriedCreature carriedCreature in array)
			{
				if (Object.op_Implicit((Object)(object)carriedCreature))
				{
					carriedCreature.Restore();
				}
			}
		}

		private void OnDestroy()
		{
			instances.Remove(this);
		}
	}
	internal sealed class CarryState
	{
		internal ZDOID Creature;

		internal ZDOID Player;

		internal Vector3 Position;

		internal Quaternion Rotation;

		internal bool Active;

		internal float ReleasedAt;
	}
	internal sealed class CarryNetwork
	{
		internal const int Protocol = 1;

		internal static readonly int ActiveKey = StringExtensionMethods.GetStableHashCode("CCC_active_v1");

		internal static readonly int SafeKey = StringExtensionMethods.GetStableHashCode("CCC_safe_v1");

		internal const string CarrierKey = "CCC_carrier_v1";

		private const string HelloRpc = "CCC_Hello_v1";

		private const string RequestRpc = "CCC_Request_v1";

		private const string SnapshotRpc = "CCC_Snapshot_v1";

		private const string MessageRpc = "CCC_Message_v1";

		private readonly CarryRegistry<ZDOID> registry = new CarryRegistry<ZDOID>();

		private readonly Dictionary<ZDOID, CarryState> states = new Dictionary<ZDOID, CarryState>();

		private readonly HashSet<long> compatiblePeers = new HashSet<long>();

		private readonly Dictionary<long, float> lastRequests = new Dictionary<long, float>();

		private ZRoutedRpc? rpc;

		private long revision;

		private long receivedRevision = -1L;

		private float nextHello;

		private float nextTick;

		private float nextSnapshot;

		private bool worldLoaded;

		internal bool Ready { get; private set; }

		internal float PickupRange { get; private set; } = 5f;

		internal float SpeedMultiplier { get; private set; } = 0.8f;

		internal bool PortalsAllowed { get; private set; } = true;

		internal static bool IsServer
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		internal static long ServerId
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					if (!IsServer)
					{
						return ZNet.instance.GetServerPeer()?.m_uid ?? 0;
					}
					return ZNet.GetUID();
				}
				return 0L;
			}
		}

		internal void Bind()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null || rpc == instance)
			{
				return;
			}
			rpc = instance;
			registry.Clear();
			states.Clear();
			compatiblePeers.Clear();
			lastRequests.Clear();
			revision = 0L;
			receivedRevision = -1L;
			Ready = false;
			worldLoaded = false;
			nextHello = (nextTick = (nextSnapshot = 0f));
			rpc.Register<ZPackage>("CCC_Hello_v1", (Action<long, ZPackage>)OnHello);
			rpc.Register<ZPackage>("CCC_Request_v1", (Action<long, ZPackage>)OnRequest);
			rpc.Register<ZPackage>("CCC_Snapshot_v1", (Action<long, ZPackage>)OnSnapshot);
			rpc.Register<string>("CCC_Message_v1", (Action<long, string>)delegate(long sender, string message)
			{
				if (sender == ServerId)
				{
					Plugin.Message(message);
				}
			});
			Plugin.Log("[network.ready] Registered carry protocol.");
		}

		internal void WorldLoaded()
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_00a1: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			Bind();
			if (!IsServer || worldLoaded || ZDOMan.instance == null)
			{
				return;
			}
			worldLoaded = true;
			ZDOID[] array = ZDOExtraData.GetAllZDOIDsWithHash((Type)3, ActiveKey).ToArray();
			foreach (ZDOID val in array)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(val);
				if (zDO != null && zDO.GetInt(ActiveKey, 0) == 1)
				{
					Vector3 vec = zDO.GetVec3(SafeKey, zDO.GetPosition());
					zDO.Set(ActiveKey, 0, false);
					zDO.Set("CCC_carrier_v1", ZDOID.None);
					zDO.SetOwner(ZNet.GetUID());
					zDO.SetPosition(vec + Vector3.up * 0.5f);
					ZDOMan.instance.ForceSendZDO(val);
					Plugin.Log($"[recovery.restart] Released saved creature {val}.");
				}
			}
			Ready = true;
			RefreshSettings();
		}

		internal void Update()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZRoutedRpc.instance == null || ZDOMan.instance == null)
			{
				Ready = false;
				return;
			}
			Bind();
			if (IsServer)
			{
				if (worldLoaded)
				{
					RefreshSettings();
					if (Time.unscaledTime >= nextTick)
					{
						nextTick = Time.unscaledTime + 0.1f;
						TickServer();
					}
					if (Time.unscaledTime >= nextSnapshot)
					{
						nextSnapshot = Time.unscaledTime + 1f;
						Broadcast();
					}
				}
			}
			else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Time.unscaledTime >= nextHello && ServerId != 0L)
			{
				nextHello = Time.unscaledTime + 3f;
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write("0.2.0");
				rpc.InvokeRoutedRPC(ServerId, "CCC_Hello_v1", new object[1] { val });
			}
		}

		private void RefreshSettings()
		{
			PickupRange = Plugin.Range.Value;
			SpeedMultiplier = Plugin.Speed.Value;
			PortalsAllowed = Plugin.AllowPortals.Value;
		}

		private void OnHello(long sender, ZPackage package)
		{
			if (!IsServer || ZNet.instance.GetPeer(sender) == null)
			{
				return;
			}
			try
			{
				if (package.ReadInt() == 1 && package.ReadString() == "0.2.0")
				{
					compatiblePeers.Add(sender);
					SendSnapshot(sender);
				}
				else
				{
					compatiblePeers.Remove(sender);
					Tell(sender, "Install CustomCreatureCarry 0.2.0 to carry creatures on this host.");
				}
			}
			catch (Exception ex)
			{
				Plugin.Warn("[protocol.hello] Invalid message: " + ex.Message);
			}
		}

		private bool AllPeersCompatible()
		{
			return ZNet.instance.GetPeers().All((ZNetPeer p) => !p.IsReady() || compatiblePeers.Contains(p.m_uid));
		}

		private ZDOID PlayerForPeer(long peer)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			if (peer != ZNet.GetUID())
			{
				return ZNet.instance.GetPeer(peer)?.m_characterID ?? ZDOID.None;
			}
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return ZDOID.None;
			}
			return ((Character)Player.m_localPlayer).GetZDOID();
		}

		internal CarryState? ForPlayer(ZDOID player)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return states.Values.FirstOrDefault((CarryState s) => s.Active && s.Player == player);
		}

		internal CarryState? GetState(ZDOID creature)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!states.TryGetValue(creature, out CarryState value))
			{
				return null;
			}
			return value;
		}

		internal bool IsCarried(ZDO? zdo)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null)
			{
				return false;
			}
			if (IsServer && worldLoaded)
			{
				return registry.Contains(zdo.m_uid);
			}
			if (!states.TryGetValue(zdo.m_uid, out CarryState value))
			{
				return zdo.GetInt(ActiveKey, 0) == 1;
			}
			return value.Active;
		}

		internal void Request(bool pickup, ZDOID creature, Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(1);
			val.Write(pickup);
			val.Write(creature);
			val.Write(point);
			rpc.InvokeRoutedRPC(ServerId, "CCC_Request_v1", new object[1] { val });
		}

		private void OnRequest(long sender, ZPackage package)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: 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_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: 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_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: 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_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			if (!IsServer || !worldLoaded)
			{
				return;
			}
			try
			{
				if ((sender != ZNet.GetUID() && !compatiblePeers.Contains(sender)) || (lastRequests.TryGetValue(sender, out var value) && Time.unscaledTime - value < 0.25f))
				{
					return;
				}
				lastRequests[sender] = Time.unscaledTime;
				if (package.ReadInt() != 1)
				{
					return;
				}
				bool flag = package.ReadBool();
				ZDOID val = package.ReadZDOID();
				Vector3 val2 = package.ReadVector3();
				ZDOID val3 = PlayerForPeer(sender);
				ZDO zDO = ZDOMan.instance.GetZDO(val3);
				if (zDO == null || zDO.GetBool(ZDOVars.s_dead, false))
				{
					Tell(sender, "Wait until your character has finished spawning.");
					return;
				}
				if (!flag)
				{
					CarryRegistry<ZDOID>.Entry entry = registry.ForPeer(sender);
					if (entry != null && !(entry.Creature != val) && !(entry.Player != val3))
					{
						Vector3 val4 = val2 - zDO.GetPosition();
						if (!CarryRules.DropWithinReach(val4.x, val4.y, val4.z))
						{
							Tell(sender, "Drop position is too far away. Try again after the world loads.");
						}
						else if (ZNetScene.InActiveArea(val2, ZNet.instance.GetReferencePosition()) && !Placement.ClearAt(val, val2))
						{
							Tell(sender, "There is not enough space for the creature here.");
						}
						else
						{
							Release(entry, val2, "Released creature.");
						}
					}
					return;
				}
				if (!AllPeersCompatible())
				{
					Tell(sender, "Every connected player must install the same CustomCreatureCarry version before pickup.");
					return;
				}
				ZDO zDO2 = ZDOMan.instance.GetZDO(val);
				if (zDO2 == null || !zDO2.Persistent || !zDO2.GetBool(ZDOVars.s_tamed, false) || zDO2.GetFloat(ZDOVars.s_health, 1f) <= 0f || Vector3.Distance(zDO.GetPosition(), zDO2.GetPosition()) > PickupRange + 1.5f)
				{
					Tell(sender, "Creature is not eligible or is out of range.");
					return;
				}
				GameObject prefab = ZNetScene.instance.GetPrefab(zDO2.GetPrefab());
				Character val5 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Character>() : null);
				if (!Object.op_Implicit((Object)(object)val5) || val5 is Player || !EligiblePrefab(((Object)prefab).name))
				{
					Tell(sender, "This creature type is not enabled for carrying.");
					return;
				}
				if (zDO2.GetBool(ZDOVars.s_haveSaddleHash, false))
				{
					Tell(sender, "Remove the saddle before carrying this creature.");
					return;
				}
				if (!registry.TryAcquire(sender, val3, val))
				{
					Tell(sender, "You or this creature are already carrying/being carried.");
					return;
				}
				zDO2.SetOwner(ZNet.GetUID());
				zDO2.Set(SafeKey, zDO.GetPosition());
				zDO2.Set("CCC_carrier_v1", val3);
				zDO2.Set(ActiveKey, 1, false);
				states[val] = new CarryState
				{
					Creature = val,
					Player = val3,
					Active = true,
					Position = zDO2.GetPosition(),
					Rotation = zDO2.GetRotation()
				};
				ZDOMan.instance.ForceSendZDO(val);
				Broadcast();
				Tell(sender, "Picked up creature.");
				Plugin.Log($"[carry.pickup] peer={sender}; creature={val}; prefab={((Object)prefab).name}");
			}
			catch (Exception arg)
			{
				Plugin.Warn($"[protocol.request] Rejected request: {arg}");
			}
		}

		private bool EligiblePrefab(string name)
		{
			string value = Plugin.AllowedPrefabs.Value;
			if (!string.IsNullOrWhiteSpace(value))
			{
				return value.Split(',').Any((string p) => string.Equals(p.Trim(), name, StringComparison.OrdinalIgnoreCase));
			}
			return true;
		}

		private void TickServer()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_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_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			long[] array = compatiblePeers.Where((long id) => ZNet.instance.GetPeer(id) == null).ToArray();
			foreach (long num2 in array)
			{
				compatiblePeers.Remove(num2);
				lastRequests.Remove(num2);
			}
			CarryRegistry<ZDOID>.Entry[] array2 = registry.Entries.ToArray();
			foreach (CarryRegistry<ZDOID>.Entry entry in array2)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(entry.Creature);
				ZDO zDO2 = ZDOMan.instance.GetZDO(entry.Player);
				if (zDO == null)
				{
					registry.TryRelease(entry.Peer, entry.Creature);
					states.Remove(entry.Creature);
					continue;
				}
				if (PlayerForPeer(entry.Peer) != entry.Player || zDO2 == null || zDO2.GetBool(ZDOVars.s_dead, false) || !AllPeersCompatible())
				{
					Release(entry, zDO.GetVec3(SafeKey, zDO.GetPosition()) + Vector3.up * 0.5f, "Creature released safely because the carry session ended.");
					continue;
				}
				CarryState carryState = states[entry.Creature];
				Vector3 position = zDO2.GetPosition();
				if (CarryRules.Finite(position.x) && CarryRules.Finite(position.y) && CarryRules.Finite(position.z))
				{
					zDO.SetOwner(ZNet.GetUID());
					zDO.Set(ActiveKey, 1, false);
					zDO.Set("CCC_carrier_v1", entry.Player);
					zDO.Set(SafeKey, position);
					carryState.Position = position + Vector3.up * 2.2f;
					carryState.Rotation = zDO2.GetRotation();
					zDO.SetPosition(carryState.Position);
					zDO.SetRotation(carryState.Rotation);
				}
			}
			ZDOID[] array3 = (from p in states
				where !p.Value.Active && Time.unscaledTime - p.Value.ReleasedAt > 15f
				select p.Key).ToArray();
			foreach (ZDOID key in array3)
			{
				states.Remove(key);
			}
		}

		private void Release(CarryRegistry<ZDOID>.Entry entry, Vector3 position, string message)
		{
			//IL_0006: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00ae: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ZDOMan.instance.GetZDO(entry.Creature);
			if (!registry.TryRelease(entry.Peer, entry.Creature))
			{
				return;
			}
			if (zDO != null)
			{
				zDO.Set(ActiveKey, 0, false);
				zDO.Set("CCC_carrier_v1", ZDOID.None);
				zDO.SetOwner(ZNet.GetUID());
				zDO.SetPosition(position);
				zDO.Set(ZDOVars.s_velHash, Vector3.zero);
				zDO.Set(ZDOVars.s_bodyVelHash, Vector3.zero);
				zDO.Set(ZDOVars.s_bodyAVelHash, Vector3.zero);
				states[entry.Creature] = new CarryState
				{
					Creature = entry.Creature,
					Position = position,
					Rotation = zDO.GetRotation(),
					Active = false,
					ReleasedAt = Time.unscaledTime
				};
				GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(entry.Creature) : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					val.GetComponent<CarriedCreature>()?.Apply();
				}
				ZDOMan.instance.ForceSendZDO(entry.Creature);
			}
			Broadcast();
			Tell(entry.Peer, message);
			Plugin.Log($"[carry.release] peer={entry.Peer}; creature={entry.Creature}");
		}

		private void Tell(long peer, string message)
		{
			Plugin.Log($"[carry.notice] peer={peer}; {message}");
			if (peer == ZNet.GetUID())
			{
				Plugin.Message(message);
			}
			else if (ZNet.instance.GetPeer(peer) != null)
			{
				rpc.InvokeRoutedRPC(peer, "CCC_Message_v1", new object[1] { message });
			}
		}

		private ZPackage BuildSnapshot()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(1);
			val.Write("0.2.0");
			val.Write(++revision);
			val.Write(PickupRange);
			val.Write(SpeedMultiplier);
			val.Write(PortalsAllowed);
			val.Write(states.Count);
			foreach (CarryState value in states.Values)
			{
				val.Write(value.Creature);
				val.Write(value.Player);
				val.Write(value.Active);
				val.Write(value.Position);
				val.Write(value.Rotation);
			}
			return val;
		}

		private void SendSnapshot(long peer)
		{
			rpc.InvokeRoutedRPC(peer, "CCC_Snapshot_v1", new object[1] { BuildSnapshot() });
		}

		private void Broadcast()
		{
			if (rpc == null || !IsServer)
			{
				return;
			}
			ZPackage val = BuildSnapshot();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer.IsReady() && compatiblePeers.Contains(peer.m_uid))
				{
					rpc.InvokeRoutedRPC(peer.m_uid, "CCC_Snapshot_v1", new object[1] { val });
				}
			}
		}

		private void OnSnapshot(long sender, ZPackage package)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			if (IsServer || sender != ServerId || sender == 0L)
			{
				return;
			}
			try
			{
				if (package.ReadInt() != 1 || package.ReadString() != "0.2.0")
				{
					Ready = false;
					return;
				}
				long num = package.ReadLong();
				if (num <= receivedRevision)
				{
					return;
				}
				float pickupRange = package.ReadSingle();
				float speedMultiplier = package.ReadSingle();
				bool portalsAllowed = package.ReadBool();
				int num2 = package.ReadInt();
				if (num2 < 0 || num2 > 256)
				{
					return;
				}
				Dictionary<ZDOID, CarryState> dictionary = new Dictionary<ZDOID, CarryState>();
				for (int i = 0; i < num2; i++)
				{
					CarryState carryState = new CarryState
					{
						Creature = package.ReadZDOID(),
						Player = package.ReadZDOID(),
						Active = package.ReadBool(),
						Position = package.ReadVector3(),
						Rotation = package.ReadQuaternion()
					};
					dictionary.Add(carryState.Creature, carryState);
				}
				receivedRevision = num;
				PickupRange = pickupRange;
				SpeedMultiplier = speedMultiplier;
				PortalsAllowed = portalsAllowed;
				states.Clear();
				foreach (KeyValuePair<ZDOID, CarryState> item in dictionary)
				{
					states.Add(item.Key, item.Value);
				}
				Ready = true;
				CarriedCreature.RefreshAll();
			}
			catch (Exception ex)
			{
				Plugin.Warn("[protocol.snapshot] Invalid snapshot: " + ex.Message);
			}
		}

		internal void Shutdown()
		{
			//IL_0036: 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)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (IsServer && ZDOMan.instance != null)
			{
				CarryRegistry<ZDOID>.Entry[] array = registry.Entries.ToArray();
				foreach (CarryRegistry<ZDOID>.Entry entry in array)
				{
					ZDO zDO = ZDOMan.instance.GetZDO(entry.Creature);
					Vector3? val = ((zDO != null) ? new Vector3?(zDO.GetVec3(SafeKey, zDO.GetPosition())) : ((Vector3?)null));
					Vector3 val2 = Vector3.up * 0.5f;
					Release(entry, (Vector3)(((??)(val.HasValue ? new Vector3?(val.GetValueOrDefault() + val2) : ((Vector3?)null))) ?? Vector3.zero), "Creature released before world shutdown.");
				}
			}
			CarriedCreature.RestoreAll();
			Ready = false;
		}
	}
	internal sealed class CarryRegistry<T> where T : notnull
	{
		internal sealed class Entry
		{
			internal readonly long Peer;

			internal readonly T Player;

			internal readonly T Creature;

			internal Entry(long peer, T player, T creature)
			{
				Peer = peer;
				Player = player;
				Creature = creature;
			}
		}

		private readonly Dictionary<T, Entry> creatures = new Dictionary<T, Entry>();

		private readonly Dictionary<long, Entry> peers = new Dictionary<long, Entry>();

		internal IEnumerable<Entry> Entries => creatures.Values;

		internal int Count => creatures.Count;

		internal bool Contains(T id)
		{
			return creatures.ContainsKey(id);
		}

		internal Entry? ForPeer(long peer)
		{
			if (!peers.TryGetValue(peer, out Entry value))
			{
				return null;
			}
			return value;
		}

		internal bool TryAcquire(long peer, T player, T creature)
		{
			if (peer == 0L || peers.ContainsKey(peer) || creatures.ContainsKey(creature))
			{
				return false;
			}
			Entry value = new Entry(peer, player, creature);
			peers.Add(peer, value);
			creatures.Add(creature, value);
			return true;
		}

		internal bool TryRelease(long peer, T creature)
		{
			if (!creatures.TryGetValue(creature, out Entry value) || value.Peer != peer)
			{
				return false;
			}
			creatures.Remove(creature);
			peers.Remove(peer);
			return true;
		}

		internal void Clear()
		{
			creatures.Clear();
			peers.Clear();
		}
	}
	internal static class CarryRules
	{
		internal static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		internal static bool DropWithinReach(float dx, float dy, float dz)
		{
			if (Finite(dx) && Finite(dy) && Finite(dz) && dx * dx + dz * dz <= 36f)
			{
				return Math.Abs(dy) <= 8f;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	internal static class NetworkAwakePatch
	{
		private static void Postfix()
		{
			Plugin.Network.Bind();
		}
	}
	[HarmonyPatch(typeof(ZNet), "Start")]
	internal static class WorldLoadedPatch
	{
		private static void Postfix()
		{
			Plugin.Network.WorldLoaded();
		}
	}
	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	internal static class NetworkShutdownPatch
	{
		private static void Prefix()
		{
			Plugin.Network.Shutdown();
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class CharacterAwakePatch
	{
		private static void Postfix(Character __instance)
		{
			if (!(__instance is Player) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CarriedCreature>()))
			{
				((Component)__instance).gameObject.AddComponent<CarriedCreature>();
			}
		}
	}
	[HarmonyPatch(typeof(ZDO), "SetOwner")]
	internal static class CarryOwnershipPatch
	{
		private static bool Prefix(ZDO __instance, long uid)
		{
			if (Plugin.Network != null && Plugin.Network.IsCarried(__instance) && CarryNetwork.ServerId != 0L)
			{
				return uid == CarryNetwork.ServerId;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class CarriedDamagePatch
	{
		private static bool Prefix(Character __instance)
		{
			return !IsCarried((Component)(object)__instance);
		}

		internal static bool IsCarried(Component component)
		{
			ZNetView component2 = component.GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component2) && component2.IsValid())
			{
				return Plugin.Network.IsCarried(component2.GetZDO());
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class CarriedLocalDamagePatch
	{
		private static bool Prefix(Character __instance)
		{
			return !CarriedDamagePatch.IsCarried((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Growup), "GrowUpdate")]
	internal static class CarriedGrowthPatch
	{
		private static bool Prefix(Growup __instance)
		{
			return !CarriedDamagePatch.IsCarried((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class CarriedBreedingPatch
	{
		private static bool Prefix(Procreation __instance)
		{
			return !CarriedDamagePatch.IsCarried((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Tameable), "TamingUpdate")]
	internal static class CarriedTamingPatch
	{
		private static bool Prefix(Tameable __instance)
		{
			return !CarriedDamagePatch.IsCarried((Component)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "GetRunSpeedFactor")]
	internal static class CarrySpeedPatch
	{
		private static void Postfix(Player __instance, ref float __result)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Network.ForPlayer(((Character)__instance).GetZDOID()) != null)
			{
				__result *= Plugin.Network.SpeedMultiplier;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "TeleportTo")]
	internal static class CarryPortalPatch
	{
		private static bool Prefix(Player __instance, ref bool __result)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Network.PortalsAllowed || Plugin.Network.ForPlayer(((Character)__instance).GetZDOID()) == null)
			{
				return true;
			}
			__result = false;
			if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				Plugin.Message("Release the creature before teleporting; this host disabled carry portals.");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	internal static class CarryHoverPatch
	{
		private static void Postfix(Tameable __instance, ref string __result)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			Character component = ((Component)__instance).GetComponent<Character>();
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)component) && component.IsTamed())
			{
				__result += BreedingHover.GetText(__instance);
				if (Plugin.Network.ForPlayer(((Character)localPlayer).GetZDOID()) == null && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)component).transform.position) <= Plugin.Network.PickupRange)
				{
					__result += $"\n[<color=yellow>{Plugin.Hotkey.Value}</color>] Carry creature";
				}
			}
		}
	}
	internal static class Placement
	{
		private static int SolidMask => LayerMask.GetMask(new string[9] { "Default", "Default_small", "static_solid", "piece", "terrain", "vehicle", "character", "character_net", "character_ghost" });

		internal static Character? FindTarget(Player player, float range)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)GameCamera.instance))
			{
				return null;
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			float num = range + Vector3.Distance(transform.position, ((Component)player).transform.position);
			foreach (RaycastHit item in from h in Physics.RaycastAll(transform.position, transform.forward, num, SolidMask, (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref h)).distance
				select h)
			{
				RaycastHit current = item;
				Character componentInParent = ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Character>();
				if (!((Object)(object)componentInParent == (Object)(object)player))
				{
					return (Object.op_Implicit((Object)(object)componentInParent) && !componentInParent.IsPlayer() && componentInParent.IsTamed() && !componentInParent.IsDead() && Vector3.Distance(((Component)componentInParent).transform.position, ((Component)player).transform.position) <= range) ? componentInParent : null;
				}
			}
			return null;
		}

		internal static bool TryGetDrop(Player player, ZDOID creature, out Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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)
			//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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			GetDimensions(creature, out var radius, out var _);
			point = ((Component)player).transform.position + ((Component)player).transform.forward * Mathf.Clamp(radius + 1.4f, 2f, 5f);
			foreach (RaycastHit item in from h in Physics.RaycastAll(point + Vector3.up * 4f, Vector3.down, 10f, SolidMask, (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref h)).distance
				select h)
			{
				RaycastHit current = item;
				if (!Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Character>()))
				{
					if (((RaycastHit)(ref current)).normal.y < 0.65f)
					{
						return false;
					}
					point = ((RaycastHit)(ref current)).point + Vector3.up * 0.12f;
					Vector3 val = point - ((Component)player).transform.position;
					return CarryRules.DropWithinReach(val.x, val.y, val.z) && ClearAt(creature, point);
				}
			}
			return false;
		}

		internal static bool ClearAt(ZDOID creature, Vector3 point)
		{
			//IL_0000: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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)
			GetDimensions(creature, out var radius, out var height);
			radius *= 0.9f;
			Vector3 val = point + Vector3.up * (radius + 0.05f);
			Vector3 val2 = point + Vector3.up * Mathf.Max(radius + 0.05f, height - radius);
			Collider[] array = Physics.OverlapCapsule(val, val2, radius, SolidMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				ZNetView componentInParent = ((Component)array[i]).GetComponentInParent<ZNetView>();
				if (!Object.op_Implicit((Object)(object)componentInParent) || !componentInParent.IsValid() || !(componentInParent.GetZDO().m_uid == creature))
				{
					return false;
				}
			}
			return true;
		}

		private static void GetDimensions(ZDOID creature, out float radius, out float height)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_0099: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			radius = 0.5f;
			height = 1f;
			ZDOMan instance = ZDOMan.instance;
			ZDO val = ((instance != null) ? instance.GetZDO(creature) : null);
			GameObject val2 = ((val != null && Object.op_Implicit((Object)(object)ZNetScene.instance)) ? ZNetScene.instance.GetPrefab(val.GetPrefab()) : null);
			if (Object.op_Implicit((Object)(object)val2))
			{
				CapsuleCollider component = val2.GetComponent<CapsuleCollider>();
				if (Object.op_Implicit((Object)(object)component))
				{
					GameObject val3 = ZNetScene.instance.FindInstance(creature);
					CarriedCreature carriedCreature = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<CarriedCreature>() : null);
					Vector3 val4 = (Object.op_Implicit((Object)(object)carriedCreature) ? carriedCreature.OriginalScale : val2.transform.localScale);
					radius = Mathf.Max(0.15f, component.radius * Mathf.Max(Mathf.Abs(val4.x), Mathf.Abs(val4.z)));
					height = Mathf.Max(2f * radius, component.height * Mathf.Abs(val4.y));
				}
			}
		}
	}
	internal sealed class DropIndicator : IDisposable
	{
		private readonly GameObject root;

		private readonly LineRenderer line;

		private readonly Material? material;

		internal DropIndicator()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0098: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			root = new GameObject("CustomCreatureCarry_DropIndicator");
			line = root.AddComponent<LineRenderer>();
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Particles/Standard Unlit");
			if (Object.op_Implicit((Object)(object)val))
			{
				material = new Material(val);
				((Renderer)line).sharedMaterial = material;
			}
			line.useWorldSpace = true;
			LineRenderer obj = line;
			LineRenderer obj2 = line;
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.2f, 1f, 0.3f, 0.8f);
			obj2.endColor = val2;
			obj.startColor = val2;
			line.startWidth = (line.endWidth = 0.05f);
			line.positionCount = 33;
			line.loop = false;
			((Renderer)line).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)line).receiveShadows = false;
		}

		internal void Show(Vector3 position)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			root.SetActive(true);
			for (int i = 0; i <= 32; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / 32f;
				line.SetPosition(i, position + new Vector3(Mathf.Cos(num) * 0.6f, 0.02f, Mathf.Sin(num) * 0.6f));
			}
		}

		internal void Hide()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				root.SetActive(false);
			}
		}

		public void Dispose()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				Object.Destroy((Object)(object)root);
			}
			if (Object.op_Implicit((Object)(object)material))
			{
				Object.Destroy((Object)(object)material);
			}
		}
	}
	[BepInPlugin("com.ras10.customcreaturecarry", "CustomCreatureCarry", "0.2.0")]
	[BepInIncompatibility("com.claude.creaturecarry")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.ras10.customcreaturecarry";

		public const string Name = "CustomCreatureCarry";

		public const string ModVersion = "0.2.0";

		internal static Plugin Instance;

		internal static CarryNetwork Network;

		internal static ConfigEntry<KeyboardShortcut> Hotkey;

		internal static ConfigEntry<float> Range;

		internal static ConfigEntry<float> Speed;

		internal static ConfigEntry<bool> AllowPortals;

		internal static ConfigEntry<string> AllowedPrefabs;

		internal static ConfigEntry<bool> ShowIndicator;

		internal static ConfigEntry<bool> ShowBreedingStatus;

		private Harmony? harmony;

		private float nextRequest;

		private DropIndicator? indicator;

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			Instance = this;
			Hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "PickupHotkey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Pick up the creature under your crosshair, or release the carried creature.");
			Range = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "PickupRange", 5f, new ConfigDescription("Maximum pickup distance. Host setting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			Speed = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "CarrySpeedMultiplier", 0.8f, new ConfigDescription("Running speed while carrying. Host setting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			AllowPortals = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "AllowPortals", true, "Allow portal travel while carrying. Host setting.");
			AllowedPrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "AllowedPrefabs", "", "Optional comma-separated creature prefab names. Empty allows eligible tamed creatures. Host setting.");
			ShowIndicator = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowDropIndicator", true, "Show a green placement circle for valid drop locations.");
			ShowBreedingStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowBreedingStatus", true, "Show pregnancy, mating progress and breeding conditions in the hover text of tamed breeding creatures. Display only; breeding rules are unchanged.");
			Network = new CarryNetwork();
			try
			{
				harmony = new Harmony("com.ras10.customcreaturecarry");
				harmony.PatchAll(typeof(Plugin).Assembly);
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[startup.ok] {0} {1}; game={2}; unity={3}; protocol={4}", "CustomCreatureCarry", "0.2.0", Version.GetVersionString(false), Application.unityVersion, 1));
			}
			catch (Exception arg)
			{
				Harmony? obj = harmony;
				if (obj != null)
				{
					obj.UnpatchSelf();
				}
				((Behaviour)this).enabled = false;
				((BaseUnityPlugin)this).Logger.LogError((object)$"[startup.failed] Game API patch failed; carrying is disabled. {arg}");
			}
		}

		private void Update()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Network.Update();
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || !Object.op_Implicit((Object)(object)ZNet.instance) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InIntro())
			{
				return;
			}
			KeyboardShortcut value = Hotkey.Value;
			if (!((KeyboardShortcut)(ref value)).IsDown() || Time.unscaledTime < nextRequest || InputBlocked() || ((Character)localPlayer).IsTeleporting())
			{
				return;
			}
			nextRequest = Time.unscaledTime + 0.5f;
			if (!Network.Ready)
			{
				Message("Waiting for CustomCreatureCarry on the host. All players need the same version.");
				return;
			}
			CarryState carryState = Network.ForPlayer(((Character)localPlayer).GetZDOID());
			if (carryState != null)
			{
				if (Placement.TryGetDrop(localPlayer, carryState.Creature, out var point))
				{
					Network.Request(pickup: false, carryState.Creature, point);
				}
				else
				{
					Message("No clear ground or floor here. Move to an open spot.");
				}
				return;
			}
			Character val = Placement.FindTarget(localPlayer, Network.PickupRange);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Message("Aim at a nearby tamed creature.");
			}
			else
			{
				Network.Request(pickup: true, val.GetZDOID(), Vector3.zero);
			}
		}

		private void LateUpdate()
		{
			//IL_0017: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			CarryState carryState = (Object.op_Implicit((Object)(object)localPlayer) ? Network.ForPlayer(((Character)localPlayer).GetZDOID()) : null);
			if (carryState == null || !ShowIndicator.Value || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting())
			{
				indicator?.Hide();
				return;
			}
			if (indicator == null)
			{
				indicator = new DropIndicator();
			}
			if (Placement.TryGetDrop(localPlayer, carryState.Creature, out var point))
			{
				indicator.Show(point);
			}
			else
			{
				indicator.Hide();
			}
		}

		internal static bool InputBlocked()
		{
			if (!Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible())
			{
				if (Object.op_Implicit((Object)(object)Chat.instance))
				{
					return Chat.instance.HasFocus();
				}
				return false;
			}
			return true;
		}

		internal static void Message(string message)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false);
			}
		}

		internal static void Log(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}

		internal static void Warn(string message)
		{
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)message);
		}

		private void OnDestroy()
		{
			Network?.Shutdown();
			indicator?.Dispose();
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}