Decompiled source of PresentMimic v0.4.1

BepInEx/plugins/PresentMimic/WyattMorse.PresentMimic.dll

Decompiled 12 hours 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using PresentMimic.Visuals;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WyattMorse.PresentMimic")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0")]
[assembly: AssemblyProduct("PresentMimic")]
[assembly: AssemblyTitle("WyattMorse.PresentMimic")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.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 PresentMimic
{
	internal static class MimicAssets
	{
		internal static GameObject Prefab;

		internal static GameObject OpenedPrefab;

		internal static Item Definition;

		internal static AudioClip Creak;

		internal static AudioClip Reveal;

		internal static AudioClip Bite;

		internal static AudioClip Growl;

		internal static AudioClip Footstep;

		internal static void Build()
		{
			//IL_0091: 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)
			Definition = ScriptableObject.CreateInstance<Item>();
			((Object)Definition).name = "PresentMimicItem";
			Definition.itemId = 940502;
			Definition.itemName = "Present";
			Definition.isScrap = false;
			Definition.minValue = (Definition.maxValue = 0);
			Definition.requiresBattery = false;
			Definition.weight = 1.04f;
			Definition.canBeInspected = false;
			Definition.itemSpawnsOnGround = true;
			Definition.restingRotation = Vector3.zero;
			Definition.verticalOffset = 0.02f;
			Definition.syncGrabFunction = false;
			Definition.syncUseFunction = false;
			Definition.syncDiscardFunction = false;
			Definition.toolTips = new string[1] { "Something shifts inside..." };
			Definition.grabAnimationTime = 0.25f;
			Prefab = BuildPrefab("WyattMorse.PresentMimic.Gift.v1", opened: false);
			OpenedPrefab = BuildPrefab("WyattMorse.PresentMimic.OpenedGift.v1", opened: true);
			Definition.spawnPrefab = Prefab;
			Creak = Sound("Original cardboard creak", 0.45f, 155f, 0.15f);
			Reveal = CreatureSound("Mimic fallback chest roar", 2.1f, loop: false, 712);
			Growl = CreatureSound("Mimic fallback breathing growl", 3.6f, loop: true, 918);
			Bite = CreatureSound("Mimic fallback jaw impact", 0.22f, loop: false, 310);
			Footstep = Sound("Mimic footfall", 0.12f, 48f, 0.6f);
			Items.RegisterItem(Definition);
		}

		private static GameObject BuildPrefab(string name, bool opened)
		{
			//IL_003f: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00d4: 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)
			GameObject val = NetworkPrefabs.CreateNetworkPrefab(name);
			val.GetComponent<NetworkObject>().AutoObjectParentSync = false;
			val.layer = 6;
			val.tag = "PhysicsProp";
			BoxCollider val2 = val.AddComponent<BoxCollider>();
			val2.size = new Vector3(0.55f, 0.55f, 0.55f);
			val2.center = new Vector3(0f, 0.27f, 0f);
			Rigidbody val3 = val.AddComponent<Rigidbody>();
			val3.isKinematic = true;
			val3.useGravity = false;
			MimicGift mimicGift = val.AddComponent<MimicGift>();
			((GrabbableObject)mimicGift).itemProperties = Definition;
			((GrabbableObject)mimicGift).grabbable = !opened;
			((GrabbableObject)mimicGift).grabbableToEnemies = false;
			((GrabbableObject)mimicGift).propBody = val3;
			mimicGift.RevealOnSpawn = opened;
			GameObject val4 = new GameObject("Suspicious scanner tell");
			val4.transform.SetParent(val.transform, false);
			val4.transform.localPosition = Vector3.up * 0.28f;
			val4.layer = 22;
			val4.tag = "DoNotSet";
			SphereCollider val5 = val4.AddComponent<SphereCollider>();
			val5.radius = 0.3f;
			((Collider)val5).isTrigger = true;
			ScanNodeProperties val6 = val4.AddComponent<ScanNodeProperties>();
			val6.headerText = "Unsettling present";
			val6.subText = "No sale value";
			val6.nodeType = 0;
			val6.scrapValue = 0;
			val6.minRange = 1;
			val6.maxRange = 12;
			val6.requiresLineOfSight = true;
			AudioSource val7 = val.AddComponent<AudioSource>();
			val7.spatialBlend = 1f;
			val7.minDistance = 1f;
			val7.maxDistance = 13f;
			val7.rolloffMode = (AudioRolloffMode)1;
			return val;
		}

		internal static Item VanillaGift()
		{
			AllItemsList val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.allItemsList : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			foreach (Item items in val.itemsList)
			{
				if ((Object)(object)items != (Object)null && (Object)(object)items.spawnPrefab != (Object)null && (Object)(object)items.spawnPrefab.GetComponent<GiftBoxItem>() != (Object)null)
				{
					return items;
				}
			}
			return null;
		}

		private static AudioClip Sound(string name, float duration, float frequency, float volume)
		{
			float[] array = new float[(int)(duration * 22050f)];
			Random random = new Random(1709);
			for (int i = 0; i < array.Length; i++)
			{
				float num = (float)i / 22050f;
				float num2 = Mathf.Sin(MathF.PI * (float)i / (float)array.Length);
				array[i] = (Mathf.Sin(num * frequency * MathF.PI * 2f * (1f - num * 0.25f)) * 0.5f + ((float)random.NextDouble() * 2f - 1f) * 0.28f) * num2 * volume;
			}
			AudioClip val = AudioClip.Create(name, array.Length, 1, 22050, false);
			val.SetData(array, 0);
			return val;
		}

		private static AudioClip CreatureSound(string name, float duration, bool loop, int seed)
		{
			float[] array = new float[(int)(duration * 22050f)];
			Random random = new Random(seed);
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			for (int i = 0; i < array.Length; i++)
			{
				float num4 = (float)i / 22050f;
				float num5 = num4 / duration;
				float num6 = (float)random.NextDouble() * 2f - 1f;
				num += 0.06f * (num6 - num);
				num2 += 0.3f * (num6 - num2);
				float num7 = (float)(loop ? 46 : 68) + 13f * Mathf.Sin(num4 * 2.7f) + num * 23f;
				num3 += MathF.PI * 2f * num7 / 22050f;
				float num8 = Mathf.Sin(num3) + 0.55f * Mathf.Sin(num3 * 2f + num) + 0.22f * Mathf.Sin(num3 * 3.03f);
				float num9 = (loop ? ((0.56f + 0.23f * Mathf.Sin(MathF.PI * 2f * num5)) * Mathf.Clamp01(Mathf.Min(num5, 1f - num5) * 80f)) : Mathf.Pow(Mathf.Sin(MathF.PI * num5), 0.65f));
				array[i] = Mathf.Clamp((num8 * (0.18f + Mathf.Abs(num)) + num2 * 0.35f) * num9, -0.85f, 0.85f);
			}
			AudioClip val = AudioClip.Create(name, array.Length, 1, 22050, false);
			val.SetData(array, 0);
			return val;
		}
	}
	public sealed class MimicGift : GrabbableObject, IHittable
	{
		public bool RevealOnSpawn;

		internal int Phase;

		internal int Health;

		internal double RevealedAt;

		internal double PhaseAt;

		internal double AttackAt;

		internal double NextAttack;

		internal double NextPath;

		internal ulong Target = ulong.MaxValue;

		internal Vector3 LastGroundPosition;

		internal Vector3 ServerPosition;

		internal Quaternion ServerRotation;

		internal float BoxGrowth = 2.4f;

		internal float RevealDuration = 1.8f;

		internal float PursuitSpeed = 3f;

		internal float TravelDistance;

		internal float MoveSpeed;

		internal float SnapshotAt;

		internal bool AttackLanded;

		internal NavMeshAgent Agent;

		private PresentMimicVisual visual;

		private AudioSource voice;

		private MimicVoice vocals;

		private BoxCollider hitbox;

		private float nextCreak;

		private float nextRequest;

		private float visualDistance;

		private float visualSpeed;

		public override void Start()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_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_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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			((GrabbableObject)this).Start();
			LastGroundPosition = (ServerPosition = ((Component)this).transform.position);
			ServerRotation = ((Component)this).transform.rotation;
			if (RevealOnSpawn)
			{
				LastGroundPosition = ((GrabbableObject)this).GetItemFloorPosition(((Component)this).transform.position);
			}
			hitbox = ((Component)this).GetComponent<BoxCollider>();
			voice = ((Component)this).GetComponent<AudioSource>();
			nextCreak = Time.time + 15f;
			vocals = ((Component)this).gameObject.AddComponent<MimicVoice>();
			vocals.Initialize(voice);
			try
			{
				Item val = MimicAssets.VanillaGift();
				if ((Object)(object)val == (Object)null)
				{
					throw new InvalidOperationException("Vanilla present prefab was not found.");
				}
				base.itemProperties.itemIcon = val.itemIcon;
				GameObject val2 = new GameObject("Present mimic visual");
				val2.transform.SetParent(((Component)this).transform, false);
				visual = val2.AddComponent<PresentMimicVisual>();
				visual.Initialize(val.spawnPrefab, Quaternion.Euler(val.restingRotation), BoxGrowth);
				base.mainObjectRenderer = val2.GetComponentInChildren<MeshRenderer>();
				Bounds bounds = ((Renderer)base.mainObjectRenderer).bounds;
				MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>();
				foreach (MeshRenderer val3 in componentsInChildren)
				{
					((Bounds)(ref bounds)).Encapsulate(((Renderer)val3).bounds);
				}
				hitbox.size = ((Bounds)(ref bounds)).size;
				hitbox.center = ((Component)this).transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
				if (((NetworkBehaviour)this).IsServer)
				{
					Agent = ((Component)this).gameObject.AddComponent<NavMeshAgent>();
					((Behaviour)Agent).enabled = false;
					Agent.radius = 0.35f;
					Agent.height = 2.1f;
					Agent.speed = 3f;
					Agent.acceleration = 18f;
					Agent.angularSpeed = 300f;
					Agent.stoppingDistance = 1.15f;
					Agent.updatePosition = false;
					Agent.updateRotation = false;
					Health = Mathf.Clamp(Plugin.Health.Value, 1, 8);
				}
				MimicService.Instance?.Register(this);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Mimic visual could not initialize; disabling this mimic: " + ex));
				base.grabbable = false;
				((Collider)hitbox).enabled = false;
				if (((NetworkBehaviour)this).IsServer && ((NetworkBehaviour)this).IsSpawned)
				{
					((NetworkBehaviour)this).NetworkObject.Despawn(true);
				}
			}
		}

		public override void GrabItem()
		{
			if (((NetworkBehaviour)this).IsOwner && (Object)(object)base.playerHeldBy != (Object)null)
			{
				MimicService.Instance?.RequestReveal(this);
			}
		}

		public override void Update()
		{
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			if (Phase == 0)
			{
				((GrabbableObject)this).Update();
				if (!base.isHeld && !RevealOnSpawn)
				{
					LastGroundPosition = ((Component)this).transform.position;
				}
				if (base.isHeld && ((NetworkBehaviour)this).IsOwner && Time.time >= nextRequest)
				{
					nextRequest = Time.time + 0.3f;
					MimicService.Instance?.RequestReveal(this);
				}
				if (Time.time >= nextCreak)
				{
					nextCreak = Time.time + 18f + (float)(((NetworkBehaviour)this).NetworkObjectId % 7);
					AudioSource obj = voice;
					if (obj != null)
					{
						obj.PlayOneShot(MimicAssets.Creak, 0.3f);
					}
				}
				return;
			}
			base.grabbable = false;
			base.grabbableToEnemies = false;
			if (base.isHeld && ((NetworkBehaviour)this).IsOwner && (Object)(object)base.playerHeldBy != (Object)null && (Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)base.playerHeldBy == (Object)(object)StartOfRound.Instance.localPlayerController && (Object)(object)base.playerHeldBy.currentlyHeldObjectServer == (Object)(object)this)
			{
				base.playerHeldBy.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true);
			}
			if (!((NetworkBehaviour)this).IsServer && !base.isHeld)
			{
				((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, ServerPosition, 1f - Mathf.Exp((0f - Time.deltaTime) * 18f));
				((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, ServerRotation, 1f - Mathf.Exp((0f - Time.deltaTime) * 18f));
			}
			double num;
			if (!((Object)(object)NetworkManager.Singleton != (Object)null))
			{
				num = Time.timeAsDouble;
			}
			else
			{
				NetworkTime serverTime = NetworkManager.Singleton.ServerTime;
				num = ((NetworkTime)(ref serverTime)).Time;
			}
			double num2 = num;
			float num3 = (float)Math.Max(0.0, num2 - RevealedAt);
			float num4 = (((NetworkBehaviour)this).IsServer ? 0f : Mathf.Clamp(Time.unscaledTime - SnapshotAt, 0f, 0.15f));
			visualDistance = Mathf.Lerp(visualDistance, TravelDistance + MoveSpeed * num4, 1f - Mathf.Exp((0f - Time.deltaTime) * 18f));
			visualSpeed = Mathf.Lerp(visualSpeed, (Phase == 2 && AttackAt <= 0.0) ? MoveSpeed : 0f, 1f - Mathf.Exp((0f - Time.deltaTime) * 12f));
			visual?.SetMotion(visualDistance, visualSpeed, (AttackAt > 0.0) ? ((float)(num2 - AttackAt)) : (-1f));
			visual?.SetPose(Mathf.Clamp01(num3 / RevealDuration), num3);
			if (Phase == 4 && (Object)(object)visual != (Object)null)
			{
				((Component)visual).transform.localRotation = Quaternion.Euler(0f, 0f, 65f);
			}
			vocals?.Animate(Phase, AttackAt, num2, visualDistance, visualSpeed);
		}

		public override void LateUpdate()
		{
			if (Phase == 0 || base.isHeld)
			{
				((GrabbableObject)this).LateUpdate();
			}
		}

		internal void BeginReveal(Vector3 position, double time, float growth, float duration)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (Phase == 0)
			{
				Phase = 1;
				RevealedAt = (PhaseAt = time);
				BoxGrowth = growth;
				RevealDuration = duration;
				visual?.SetGrowth(growth);
				ServerPosition = position;
				ServerRotation = Quaternion.Euler(0f, ((Component)this).transform.eulerAngles.y, 0f);
				base.grabbable = false;
				base.grabbableToEnemies = false;
				if (!base.isHeld)
				{
					((Component)this).transform.position = position;
					((Component)this).transform.rotation = ServerRotation;
				}
				((Component)this).gameObject.layer = 19;
				((Component)this).gameObject.tag = "Enemy";
				hitbox.center = Vector3.up * 1.35f;
				hitbox.size = new Vector3(1f, 2.7f, 0.9f);
				((Collider)hitbox).isTrigger = false;
				((Collider)hitbox).enabled = true;
				ScanNodeProperties componentInChildren = ((Component)this).GetComponentInChildren<ScanNodeProperties>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.headerText = "Present mimic";
					componentInChildren.subText = "Ambush predator";
					componentInChildren.nodeType = 1;
				}
				vocals?.Roar(time);
			}
		}

		bool IHittable.Hit(int force, Vector3 direction, PlayerControllerB attacker, bool playHitSFX, int hitID)
		{
			if (Phase == 0 || Phase == 4 || (Object)(object)attacker == (Object)null || (Object)(object)attacker != (Object)(object)StartOfRound.Instance.localPlayerController)
			{
				return false;
			}
			MimicService.Instance?.RequestHit(this);
			return true;
		}

		public override void OnDestroy()
		{
			MimicService.Instance?.Unregister(this);
			((GrabbableObject)this).OnDestroy();
		}
	}
	internal static class MimicRules
	{
		internal const float BiteContact = 0.38f;

		internal const float BiteDuration = 0.8f;

		internal const float BiteInterval = 1.05f;

		internal const float BiteRange = 1.8f;

		internal static bool CanBite(double now, double revealedAt, double revealDuration, double attackAt, float distance, bool liveIndoorPlayer, bool clearLine)
		{
			return liveIndoorPlayer && clearLine && double.IsFinite(now) && double.IsFinite(revealedAt) && double.IsFinite(revealDuration) && double.IsFinite(attackAt) && float.IsFinite(distance) && distance >= 0f && distance <= 1.8f && revealDuration >= 0.5 && now - revealedAt >= revealDuration + 0.8 && attackAt > 0.0 && now - attackAt >= 0.3799999952316284 && now - attackAt <= 0.800000011920929;
		}
	}
	internal sealed class MimicService : MonoBehaviour
	{
		[Serializable]
		private sealed class Packet
		{
			public int version = 2;

			public int kind;

			public int phase;

			public int health;

			public int damage;

			public ulong id;

			public ulong target;

			public uint sequence;

			public Vector3 position;

			public Quaternion rotation;

			public double revealed;

			public double phaseAt;

			public double attackAt;

			public float growth;

			public float duration;

			public float travel;

			public float speed;
		}

		internal static MimicService Instance;

		private const string Channel = "WyattMorse.PresentMimic.v2";

		private readonly HashSet<MimicGift> gifts = new HashSet<MimicGift>();

		private readonly Dictionary<ulong, float> strikes = new Dictionary<ulong, float>();

		private readonly Dictionary<ulong, uint> latest = new Dictionary<ulong, uint>();

		private readonly Dictionary<ulong, float> helloTimes = new Dictionary<ulong, float>();

		private NetworkManager manager;

		private StartOfRound round;

		private bool rolled;

		private float nextSnapshot;

		private float nextHello;

		private uint sequence;

		private uint attackSequence;

		private uint lastAttack;

		private void Awake()
		{
			Instance = this;
		}

		internal void Register(MimicGift gift)
		{
			gifts.Add(gift);
		}

		internal void Unregister(MimicGift gift)
		{
			gifts.Remove(gift);
		}

		private void Update()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.ShutdownInProgress)
			{
				Disconnect();
				return;
			}
			if ((Object)(object)manager != (Object)(object)singleton)
			{
				Disconnect();
				manager = singleton;
				manager.CustomMessagingManager.RegisterNamedMessageHandler("WyattMorse.PresentMimic.v2", new HandleNamedMessageDelegate(Receive));
				MimicGift[] array = Object.FindObjectsOfType<MimicGift>();
				foreach (MimicGift mimicGift in array)
				{
					if (((NetworkBehaviour)mimicGift).IsSpawned)
					{
						gifts.Add(mimicGift);
					}
				}
			}
			if ((Object)(object)round != (Object)(object)StartOfRound.Instance)
			{
				round = StartOfRound.Instance;
				rolled = false;
			}
			if ((Object)(object)round == (Object)null)
			{
				return;
			}
			if (manager.IsServer)
			{
				PresentCommand.TickPickupAmbushes();
				if (round.inShipPhase)
				{
					rolled = false;
				}
				if (!rolled && Plugin.Enabled.Value && round.shipHasLanded && !round.inShipPhase && (Object)(object)RoundManager.Instance != (Object)null && RoundManager.Instance.dungeonFinishedGeneratingForAllPlayers)
				{
					rolled = true;
					TrySpawn();
				}
				MimicGift[] array2 = gifts.ToArray();
				foreach (MimicGift mimicGift2 in array2)
				{
					if ((Object)(object)mimicGift2 == (Object)null || !((NetworkBehaviour)mimicGift2).IsSpawned)
					{
						gifts.Remove(mimicGift2);
					}
					else if ((!Plugin.Enabled.Value || round.shipIsLeaving || (round.inShipPhase && !mimicGift2.RevealOnSpawn)) && !((GrabbableObject)mimicGift2).isHeld)
					{
						((NetworkBehaviour)mimicGift2).NetworkObject.Despawn(true);
					}
					else
					{
						Tick(mimicGift2);
					}
				}
				if (Time.unscaledTime >= nextSnapshot)
				{
					nextSnapshot = Time.unscaledTime + 0.12f;
					Broadcast();
				}
			}
			else if (Time.unscaledTime >= nextHello)
			{
				nextHello = Time.unscaledTime + 5f;
				Send(0uL, new Packet
				{
					kind = 0
				});
			}
		}

		private void TrySpawn()
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			Random random = new Random(round.randomMapSeed ^ 0x4D1A934);
			if (random.NextDouble() >= (double)Mathf.Clamp01(Plugin.SpawnChance.Value))
			{
				Plugin.Log.LogInfo((object)"This round's rare mimic spawn roll did not pass.");
			}
			else
			{
				if (gifts.Any((MimicGift g) => (Object)(object)g != (Object)null && ((NetworkBehaviour)g).IsSpawned))
				{
					return;
				}
				List<RandomScrapSpawn> list = (from s in Object.FindObjectsOfType<RandomScrapSpawn>()
					where !s.spawnUsed
					orderby ((Component)s).transform.position.x, ((Component)s).transform.position.z
					select s).ToList();
				NavMeshHit hit = default(NavMeshHit);
				while (list.Count > 0)
				{
					int index = random.Next(list.Count);
					RandomScrapSpawn val = list[index];
					list.RemoveAt(index);
					if (!NavMesh.SamplePosition(((Component)val).transform.position, ref hit, 1.3f, -1) || round.allPlayerScripts.Any((PlayerControllerB p) => (Object)(object)p != (Object)null && p.isPlayerControlled && !p.isPlayerDead && Vector3.Distance(((Component)p).transform.position, ((NavMeshHit)(ref hit)).position) < 7f) || Physics.CheckCapsule(((NavMeshHit)(ref hit)).position + Vector3.up * 0.35f, ((NavMeshHit)(ref hit)).position + Vector3.up * 1.4f, 0.3f, round.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
					{
						continue;
					}
					GameObject val2 = Object.Instantiate<GameObject>(MimicAssets.Prefab, ((NavMeshHit)(ref hit)).position + Vector3.up * 0.02f, Quaternion.Euler(0f, (float)random.Next(360), 0f));
					val2.GetComponent<NetworkObject>().Spawn(false);
					Plugin.Log.LogInfo((object)"Spawned one independent indoor mimic at a loot marker.");
					return;
				}
				Plugin.Log.LogInfo((object)"Mimic spawn skipped: no clear, unoccupied indoor loot marker.");
			}
		}

		internal void RequestReveal(MimicGift gift)
		{
			Request(new Packet
			{
				kind = 1,
				id = ((NetworkBehaviour)gift).NetworkObjectId
			});
		}

		internal void RequestHit(MimicGift gift)
		{
			Request(new Packet
			{
				kind = 2,
				id = ((NetworkBehaviour)gift).NetworkObjectId
			});
		}

		private void Request(Packet packet)
		{
			if (!((Object)(object)manager == (Object)null))
			{
				if (manager.IsServer)
				{
					Handle(manager.LocalClientId, packet);
				}
				else
				{
					Send(0uL, packet);
				}
			}
		}

		private MimicGift Find(ulong id)
		{
			return gifts.FirstOrDefault((MimicGift g) => (Object)(object)g != (Object)null && ((NetworkBehaviour)g).IsSpawned && ((NetworkBehaviour)g).NetworkObjectId == id);
		}

		private PlayerControllerB Player(ulong id)
		{
			return ((IEnumerable<PlayerControllerB>)round?.allPlayerScripts).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB p) => (Object)(object)p != (Object)null && p.actualClientId == id && p.isPlayerControlled && !p.isPlayerDead));
		}

		private void Handle(ulong sender, Packet packet)
		{
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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_01d3: Unknown result type (might be due to invalid IL or missing references)
			MimicGift mimicGift = Find(packet.id);
			PlayerControllerB val = Player(sender);
			if ((Object)(object)mimicGift == (Object)null || (Object)(object)val == (Object)null || !Plugin.Enabled.Value)
			{
				return;
			}
			if (packet.kind == 1 && mimicGift.Phase == 0 && ((GrabbableObject)mimicGift).isHeld && (Object)(object)((GrabbableObject)mimicGift).playerHeldBy == (Object)(object)val && val.ItemSlots != null && val.ItemSlots.Contains((GrabbableObject)(object)mimicGift))
			{
				RevealGift(mimicGift);
			}
			if (packet.kind != 2 || mimicGift.Phase < 1 || mimicGift.Phase >= 4 || (strikes.TryGetValue(sender, out var value) && Time.unscaledTime - value < 0.5f))
			{
				return;
			}
			GrabbableObject val2 = ((val.ItemSlots != null && val.currentItemSlot >= 0 && val.currentItemSlot < val.ItemSlots.Length) ? val.ItemSlots[val.currentItemSlot] : null);
			if ((Object)(object)val2 == (Object)null || !val2.itemProperties.isDefensiveWeapon || Vector3.Distance(((Component)val).transform.position, ((Component)mimicGift).transform.position) > 3.5f || !Clear(((Component)val.gameplayCamera).transform.position, ((Component)mimicGift).transform.position + Vector3.up))
			{
				return;
			}
			strikes[sender] = Time.unscaledTime;
			if (--mimicGift.Health <= 0)
			{
				mimicGift.Phase = 4;
				NetworkTime serverTime = manager.ServerTime;
				mimicGift.PhaseAt = ((NetworkTime)(ref serverTime)).Time;
				if ((Object)(object)mimicGift.Agent != (Object)null && ((Behaviour)mimicGift.Agent).enabled)
				{
					mimicGift.Agent.isStopped = true;
				}
				((Collider)((Component)mimicGift).GetComponent<BoxCollider>()).enabled = false;
			}
			Broadcast();
		}

		private void RevealGift(MimicGift gift)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (gift.Phase == 0)
			{
				Vector3 val = gift.LastGroundPosition;
				NavMeshHit val2 = default(NavMeshHit);
				if (NavMesh.SamplePosition(val, ref val2, 2f, -1))
				{
					val = ((NavMeshHit)(ref val2)).position;
				}
				Vector3 position = val;
				NetworkTime serverTime = manager.ServerTime;
				gift.BeginReveal(position, ((NetworkTime)(ref serverTime)).Time, Mathf.Clamp(Plugin.RevealedBoxScale.Value, 1.1f, 4f), Mathf.Clamp(Plugin.RevealSeconds.Value, 0.5f, 5f));
				Broadcast();
			}
		}

		private void Tick(MimicGift gift)
		{
			//IL_008e: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: 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_033c: 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)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0774: Unknown result type (might be due to invalid IL or missing references)
			//IL_079a: Unknown result type (might be due to invalid IL or missing references)
			//IL_079f: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_073e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0743: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_074d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0783: Unknown result type (might be due to invalid IL or missing references)
			//IL_0788: Unknown result type (might be due to invalid IL or missing references)
			//IL_078d: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0618: Unknown result type (might be due to invalid IL or missing references)
			//IL_061d: Unknown result type (might be due to invalid IL or missing references)
			//IL_061f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0624: Unknown result type (might be due to invalid IL or missing references)
			//IL_0581: Unknown result type (might be due to invalid IL or missing references)
			//IL_080f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0814: Unknown result type (might be due to invalid IL or missing references)
			//IL_082a: Unknown result type (might be due to invalid IL or missing references)
			//IL_082f: Unknown result type (might be due to invalid IL or missing references)
			//IL_07dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_059a: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a1: Expected O, but got Unknown
			//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c4: Invalid comparison between Unknown and I4
			//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0641: Unknown result type (might be due to invalid IL or missing references)
			//IL_0643: Unknown result type (might be due to invalid IL or missing references)
			//IL_064d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0652: Unknown result type (might be due to invalid IL or missing references)
			//IL_065e: Unknown result type (might be due to invalid IL or missing references)
			//IL_069c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_091a: Unknown result type (might be due to invalid IL or missing references)
			//IL_091f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0929: Unknown result type (might be due to invalid IL or missing references)
			//IL_092e: Unknown result type (might be due to invalid IL or missing references)
			//IL_093f: Unknown result type (might be due to invalid IL or missing references)
			if (gift.Phase == 0)
			{
				if (gift.RevealOnSpawn || (((GrabbableObject)gift).isHeld && (Object)(object)((GrabbableObject)gift).playerHeldBy != (Object)null && !((GrabbableObject)gift).playerHeldBy.isPlayerDead))
				{
					RevealGift(gift);
				}
				return;
			}
			NetworkTime serverTime = manager.ServerTime;
			double time = ((NetworkTime)(ref serverTime)).Time;
			if (gift.Phase == 4)
			{
				if (!((GrabbableObject)gift).isHeld && time - gift.PhaseAt > 2.0)
				{
					((NetworkBehaviour)gift).NetworkObject.Despawn(true);
				}
			}
			else
			{
				if (((GrabbableObject)gift).isHeld)
				{
					return;
				}
				if (gift.Phase == 1)
				{
					((Component)gift).transform.position = gift.ServerPosition;
					((Component)gift).transform.rotation = gift.ServerRotation;
					if (time - gift.RevealedAt < (double)gift.RevealDuration + 0.8)
					{
						return;
					}
					gift.Phase = 2;
					gift.PhaseAt = time;
					gift.PursuitSpeed = 3f;
				}
				PlayerControllerB val = Player(gift.Target);
				if ((Object)(object)val == (Object)null || !val.isInsideFactory || val.isInHangarShipRoom)
				{
					val = ((gift.AttackAt > 0.0) ? null : (from p in round.allPlayerScripts
						where (Object)(object)p != (Object)null && p.isPlayerControlled && !p.isPlayerDead && p.isInsideFactory && !p.isInHangarShipRoom
						where Vector3.Distance(((Component)p).transform.position, ((Component)gift).transform.position) < 24f && Clear(((Component)gift).transform.position + Vector3.up * 1.4f, ((Component)p.gameplayCamera).transform.position)
						select p).OrderBy(delegate(PlayerControllerB p)
					{
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						//IL_0016: Unknown result type (might be due to invalid IL or missing references)
						//IL_001b: 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)
						Vector3 val11 = ((Component)p).transform.position - ((Component)gift).transform.position;
						return ((Vector3)(ref val11)).sqrMagnitude;
					}).FirstOrDefault());
					if (gift.AttackAt <= 0.0)
					{
						gift.Target = (((Object)(object)val != (Object)null) ? val.actualClientId : ulong.MaxValue);
					}
				}
				gift.Phase = (((Object)(object)val == (Object)null) ? 3 : 2);
				bool flag = gift.AttackAt > 0.0;
				bool flag2 = (Object)(object)val != (Object)null && Vector3.Distance(((Component)val).transform.position, ((Component)gift).transform.position) <= 1.8f;
				if (!flag && (Object)(object)val != (Object)null && flag2 && time >= gift.NextAttack && Clear(((Component)gift).transform.position + Vector3.up * 1.3f, ((Component)val.gameplayCamera).transform.position))
				{
					gift.AttackAt = time;
					gift.AttackLanded = false;
					flag = true;
					Broadcast();
				}
				gift.PursuitSpeed = (((Object)(object)val != (Object)null && !flag) ? Mathf.Min(Mathf.Clamp(Plugin.ChaseSpeed.Value, 3f, 12f), gift.PursuitSpeed + 1.2f * Time.deltaTime) : 3f);
				bool flag3 = (Object)(object)gift.Agent != (Object)null && ((Behaviour)gift.Agent).enabled && gift.Agent.isOnNavMesh;
				if (!flag3 && (Object)(object)gift.Agent != (Object)null && time >= gift.NextPath)
				{
					gift.NextPath = time + 1.0;
					NavMeshHit val2 = default(NavMeshHit);
					if (NavMesh.SamplePosition(((Component)gift).transform.position, ref val2, 1.5f, -1))
					{
						((Behaviour)gift.Agent).enabled = true;
						flag3 = gift.Agent.Warp(((NavMeshHit)(ref val2)).position);
						if (!flag3)
						{
							((Behaviour)gift.Agent).enabled = false;
						}
						else
						{
							gift.NextPath = 0.0;
						}
					}
				}
				Vector3 position = ((Component)gift).transform.position;
				bool flag4 = false;
				if (flag3)
				{
					gift.Agent.speed = gift.PursuitSpeed;
					gift.Agent.isStopped = flag || (Object)(object)val == (Object)null;
					if ((Object)(object)val != (Object)null && time >= gift.NextPath)
					{
						gift.NextPath = time + 0.2;
						NavMeshHit val3 = default(NavMeshHit);
						if (NavMesh.SamplePosition(((Component)val).transform.position, ref val3, 1.5f, -1))
						{
							NavMeshPath val4 = new NavMeshPath();
							if (gift.Agent.CalculatePath(((NavMeshHit)(ref val3)).position, val4) && (int)val4.status != 2)
							{
								gift.Agent.SetPath(val4);
							}
							else
							{
								gift.Agent.ResetPath();
							}
						}
						else
						{
							gift.Agent.ResetPath();
						}
					}
					Vector3 val5 = gift.Agent.nextPosition - position;
					if (!flag && ((Vector3)(ref val5)).sqrMagnitude > 1E-06f)
					{
						RaycastHit val6 = default(RaycastHit);
						flag4 = Physics.SphereCast(position + Vector3.up * 0.6f, 0.3f, ((Vector3)(ref val5)).normalized, ref val6, ((Vector3)(ref val5)).magnitude + 0.03f, round.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
						if (!flag4)
						{
							Transform transform = ((Component)gift).transform;
							transform.position += val5;
						}
					}
					gift.Agent.nextPosition = ((Component)gift).transform.position;
				}
				Vector3 val7 = Vector3.ProjectOnPlane(((Component)gift).transform.position - position, Vector3.up);
				gift.TravelDistance += ((Vector3)(ref val7)).magnitude;
				MimicGift mimicGift = gift;
				float moveSpeed;
				if (!flag3 || !((Object)(object)val != (Object)null) || flag || flag4)
				{
					moveSpeed = 0f;
				}
				else
				{
					Vector3 val8 = Vector3.ProjectOnPlane(gift.Agent.velocity, Vector3.up);
					moveSpeed = Mathf.Min(15f, ((Vector3)(ref val8)).magnitude);
				}
				mimicGift.MoveSpeed = moveSpeed;
				Vector3 val9 = ((flag && (Object)(object)val != (Object)null) ? Vector3.ProjectOnPlane(((Component)val).transform.position - position, Vector3.up) : ((flag3 && !flag4) ? Vector3.ProjectOnPlane(gift.Agent.desiredVelocity, Vector3.up) : val7));
				if (((Vector3)(ref val9)).sqrMagnitude > 1E-05f)
				{
					((Component)gift).transform.rotation = Quaternion.RotateTowards(((Component)gift).transform.rotation, Quaternion.LookRotation(val9), 300f * Time.deltaTime);
				}
				gift.ServerPosition = ((Component)gift).transform.position;
				gift.ServerRotation = ((Component)gift).transform.rotation;
				if (gift.AttackAt > 0.0 && !gift.AttackLanded && time - gift.AttackAt >= 0.3799999952316284)
				{
					gift.AttackLanded = true;
					PlayerControllerB val10 = Player(gift.Target);
					if ((Object)(object)val10 != (Object)null && MimicRules.CanBite(time, gift.RevealedAt, gift.RevealDuration, gift.AttackAt, Vector3.Distance(((Component)val10).transform.position, ((Component)gift).transform.position), val10.isInsideFactory && !val10.isPlayerDead && !val10.isInHangarShipRoom, Clear(((Component)gift).transform.position + Vector3.up * 1.3f, ((Component)val10.gameplayCamera).transform.position)))
					{
						Packet packet = new Packet
						{
							kind = 4,
							id = ((NetworkBehaviour)gift).NetworkObjectId,
							target = val10.actualClientId,
							damage = Mathf.Clamp(Plugin.Damage.Value, 5, 40),
							sequence = ++attackSequence
						};
						if (val10.actualClientId == manager.LocalClientId)
						{
							ApplyDamage(packet);
						}
						else
						{
							Send(val10.actualClientId, packet);
						}
					}
				}
				if (gift.AttackAt > 0.0 && time - gift.AttackAt >= 0.800000011920929)
				{
					gift.NextAttack = gift.AttackAt + 1.0499999523162842;
					gift.AttackAt = 0.0;
					Broadcast();
				}
			}
		}

		private bool Clear(Vector3 a, Vector3 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return !Physics.Linecast(a, b, round.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1);
		}

		private void Broadcast()
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null || !manager.IsServer || !manager.IsListening)
			{
				return;
			}
			MimicGift[] array = gifts.ToArray();
			foreach (MimicGift mimicGift in array)
			{
				if ((Object)(object)mimicGift == (Object)null || !((NetworkBehaviour)mimicGift).IsSpawned)
				{
					continue;
				}
				Packet packet = new Packet
				{
					kind = 3,
					id = ((NetworkBehaviour)mimicGift).NetworkObjectId,
					sequence = ++sequence,
					phase = mimicGift.Phase,
					health = mimicGift.Health,
					target = mimicGift.Target,
					position = ((mimicGift.Phase == 0) ? ((Component)mimicGift).transform.position : mimicGift.ServerPosition),
					rotation = ((mimicGift.Phase == 0) ? ((Component)mimicGift).transform.rotation : mimicGift.ServerRotation),
					revealed = mimicGift.RevealedAt,
					phaseAt = mimicGift.PhaseAt,
					attackAt = mimicGift.AttackAt,
					growth = mimicGift.BoxGrowth,
					duration = mimicGift.RevealDuration,
					travel = mimicGift.TravelDistance,
					speed = mimicGift.MoveSpeed
				};
				foreach (ulong connectedClientsId in manager.ConnectedClientsIds)
				{
					if (connectedClientsId != 0)
					{
						Send(connectedClientsId, packet);
					}
				}
			}
		}

		private void ApplyDamage(Packet packet)
		{
			//IL_0075: 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)
			if (packet.sequence > lastAttack && packet.target == manager.LocalClientId)
			{
				lastAttack = packet.sequence;
				PlayerControllerB localPlayerController = round.localPlayerController;
				if ((Object)(object)localPlayerController != (Object)null && !localPlayerController.isPlayerDead)
				{
					localPlayerController.DamagePlayer(Mathf.Clamp(packet.damage, 5, 40), true, true, (CauseOfDeath)6, 0, false, default(Vector3));
				}
			}
		}

		private void Receive(ulong sender, FastBufferReader reader)
		{
			//IL_0324: 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_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			if (((FastBufferReader)(ref reader)).Length > 5000 || (Object)(object)round == (Object)null)
			{
				return;
			}
			try
			{
				string text = default(string);
				((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false);
				Packet packet = JsonUtility.FromJson<Packet>(text);
				if (packet == null || packet.version != 2)
				{
					return;
				}
				if (manager.IsServer)
				{
					if (packet.kind == 0 && (!helloTimes.TryGetValue(sender, out var value) || Time.unscaledTime - value >= 3f))
					{
						helloTimes[sender] = Time.unscaledTime;
						Broadcast();
					}
					else if (packet.kind == 1 || packet.kind == 2)
					{
						Handle(sender, packet);
					}
				}
				else
				{
					if (sender != 0)
					{
						return;
					}
					if (packet.kind == 4)
					{
						ApplyDamage(packet);
					}
					else
					{
						if (packet.kind != 3 || packet.phase < 0 || packet.phase > 4 || !float.IsFinite(packet.position.x) || !float.IsFinite(packet.position.y) || !float.IsFinite(packet.position.z) || !float.IsFinite(packet.travel) || packet.travel < 0f || !float.IsFinite(packet.speed) || !float.IsFinite(packet.rotation.x) || !float.IsFinite(packet.rotation.y) || !float.IsFinite(packet.rotation.z) || !float.IsFinite(packet.rotation.w) || !double.IsFinite(packet.attackAt) || !double.IsFinite(packet.revealed) || !float.IsFinite(packet.duration) || !float.IsFinite(packet.growth) || (latest.TryGetValue(packet.id, out var value2) && packet.sequence <= value2))
						{
							return;
						}
						MimicGift mimicGift = Find(packet.id);
						if (!((Object)(object)mimicGift == (Object)null))
						{
							latest[packet.id] = packet.sequence;
							if (mimicGift.Phase == 0 && packet.phase > 0)
							{
								mimicGift.BeginReveal(packet.position, packet.revealed, packet.growth, Mathf.Clamp(packet.duration, 0.5f, 5f));
							}
							mimicGift.Phase = packet.phase;
							mimicGift.PhaseAt = packet.phaseAt;
							mimicGift.Health = packet.health;
							mimicGift.Target = packet.target;
							mimicGift.AttackAt = packet.attackAt;
							mimicGift.ServerPosition = packet.position;
							mimicGift.ServerRotation = packet.rotation;
							mimicGift.TravelDistance = packet.travel;
							mimicGift.MoveSpeed = Mathf.Clamp(packet.speed, 0f, 15f);
							mimicGift.SnapshotAt = Time.unscaledTime;
							if (mimicGift.Phase == 0 && !((GrabbableObject)mimicGift).isHeld)
							{
								((Component)mimicGift).transform.position = packet.position;
								((GrabbableObject)mimicGift).targetFloorPosition = ((Component)mimicGift).transform.localPosition;
								((GrabbableObject)mimicGift).fallTime = 1f;
							}
							if (mimicGift.Phase == 4)
							{
								((Collider)((Component)mimicGift).GetComponent<BoxCollider>()).enabled = false;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Ignored invalid mimic message: " + ex.GetType().Name));
			}
		}

		private unsafe void Send(ulong client, Packet packet)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)manager == (Object)null || !manager.IsListening || manager.ShutdownInProgress)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(6000, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe(JsonUtility.ToJson((object)packet), false);
				manager.CustomMessagingManager.SendNamedMessage("WyattMorse.PresentMimic.v2", client, val, (NetworkDelivery)4);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private void Disconnect()
		{
			if ((Object)(object)manager != (Object)null)
			{
				PresentCommand.ResetAmbushes();
			}
			if ((Object)(object)manager != (Object)null && manager.CustomMessagingManager != null)
			{
				manager.CustomMessagingManager.UnregisterNamedMessageHandler("WyattMorse.PresentMimic.v2");
			}
			manager = null;
			round = null;
			rolled = false;
			latest.Clear();
			strikes.Clear();
			helloTimes.Clear();
			gifts.Clear();
			sequence = (attackSequence = (lastAttack = 0u));
		}

		private void OnDestroy()
		{
			Disconnect();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	internal sealed class MimicVoice : MonoBehaviour
	{
		private AudioSource voice;

		private AudioSource growl;

		private AudioClip roar;

		private AudioClip bite;

		private double soundedBite;

		private int previousStep;

		internal void Initialize(AudioSource source)
		{
			voice = source;
			growl = ((Component)this).gameObject.AddComponent<AudioSource>();
			growl.spatialBlend = 1f;
			growl.minDistance = 2f;
			growl.maxDistance = 24f;
			growl.rolloffMode = (AudioRolloffMode)1;
			growl.loop = true;
			growl.volume = 0f;
			voice.minDistance = 2f;
			voice.maxDistance = 27f;
			AudioSource obj = voice;
			float dopplerLevel = (growl.dopplerLevel = 0.15f);
			obj.dopplerLevel = dopplerLevel;
			roar = MimicAssets.Reveal;
			bite = MimicAssets.Bite;
			growl.clip = MimicAssets.Growl;
			EnemyType[] array = Resources.FindObjectsOfTypeAll<EnemyType>();
			foreach (EnemyType val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.enemyPrefab == (Object)null)
				{
					continue;
				}
				CrawlerAI component = val.enemyPrefab.GetComponent<CrawlerAI>();
				if ((Object)(object)component != (Object)null)
				{
					if (component.longRoarSFX != null && component.longRoarSFX.Length != 0 && (Object)(object)component.longRoarSFX[0] != (Object)null)
					{
						roar = component.longRoarSFX[0];
					}
					else if ((Object)(object)component.shortRoar != (Object)null)
					{
						roar = component.shortRoar;
					}
					if ((Object)(object)component.bitePlayerSFX != (Object)null)
					{
						bite = component.bitePlayerSFX;
					}
					if ((Object)(object)((EnemyAI)component).creatureVoice != (Object)null)
					{
						voice.outputAudioMixerGroup = ((EnemyAI)component).creatureVoice.outputAudioMixerGroup;
					}
				}
				FlowermanAI component2 = val.enemyPrefab.GetComponent<FlowermanAI>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)component2.creatureAngerVoice != (Object)null && (Object)(object)component2.creatureAngerVoice.clip != (Object)null)
				{
					growl.clip = component2.creatureAngerVoice.clip;
					growl.outputAudioMixerGroup = component2.creatureAngerVoice.outputAudioMixerGroup;
				}
			}
			growl.pitch = 0.78f;
			voice.pitch = 0.9f;
		}

		internal void Roar(double started)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			double num;
			if (!((Object)(object)NetworkManager.Singleton != (Object)null))
			{
				num = started;
			}
			else
			{
				NetworkTime serverTime = NetworkManager.Singleton.ServerTime;
				num = ((NetworkTime)(ref serverTime)).Time;
			}
			double num2 = num;
			if (num2 - started < 2.5)
			{
				voice.PlayOneShot(roar, 0.85f);
			}
		}

		internal void Animate(int phase, double attackAt, double now, float distance, float speed)
		{
			float num = ((phase != 2) ? 0f : ((attackAt > 0.0) ? 0.18f : 0.46f));
			growl.volume = Mathf.MoveTowards(growl.volume, num, Time.deltaTime * 0.85f);
			if (growl.volume > 0.005f && !growl.isPlaying)
			{
				growl.Play();
			}
			if (growl.volume <= 0.005f && growl.isPlaying)
			{
				growl.Stop();
			}
			if (phase != 4 && attackAt > soundedBite && now - attackAt >= 0.3799999952316284)
			{
				soundedBite = attackAt;
				voice.PlayOneShot(bite, 0.9f);
			}
			int num2 = Mathf.FloorToInt(distance / 0.95f);
			if (num2 != previousStep && speed > 0.3f && phase == 2 && attackAt <= 0.0)
			{
				voice.PlayOneShot(MimicAssets.Footstep, Mathf.Lerp(0.16f, 0.36f, Mathf.Clamp01(speed / 8f)));
			}
			previousStep = num2;
		}
	}
	[BepInPlugin("WyattMorse.PresentMimic", "PresentMimic", "0.4.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> EnableVisualPreview;

		internal static ConfigEntry<float> RevealedBoxScale;

		internal static ConfigEntry<float> RevealSeconds;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> SpawnChance;

		internal static ConfigEntry<float> ChaseSpeed;

		internal static ConfigEntry<int> Damage;

		internal static ConfigEntry<int> Health;

		private static Harmony? patches;

		private static GameObject? runtime;

		private void Awake()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			if (patches != null)
			{
				return;
			}
			Log = ((BaseUnityPlugin)this).Logger;
			EnableVisualPreview = ((BaseUnityPlugin)this).Config.Bind<bool>("Development", "EnableVisualPreview", false, "Local visual preview only: F8 place a dormant mimic, F9 reveal/reset, F10 remove. Does not spawn a network enemy or change real gifts.");
			RevealedBoxScale = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "RevealedBoxScale", 2.4f, new ConfigDescription("Uniform box growth after revealing; original wrapping, ribbon and mesh proportions are retained.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.1f, 4f), Array.Empty<object>()));
			RevealSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "RevealSeconds", 1.8f, new ConfigDescription("Transformation duration; the host supplies this value for network mimics.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), Array.Empty<object>()));
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "Enabled", true, "Enable rare indoor mimic spawns; host controls gameplay.");
			SpawnChance = ((BaseUnityPlugin)this).Config.Bind<float>("Host", "SpawnChance", 0.1f, new ConfigDescription("Chance of one mimic per indoor round. Set to 1 for the final playtest.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ChaseSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Host", "ChaseSpeed", 12f, new ConfigDescription("Maximum pursuit speed. Accelerates from 3 m/s at the native Bracken's 1.2 m/s per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 12f), Array.Empty<object>()));
			Damage = ((BaseUnityPlugin)this).Config.Bind<int>("Host", "AttackDamage", 40, new ConfigDescription("Damage on jaw contact. Default 40 matches the installed Thumper; bites repeat while the victim remains reachable.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 40), Array.Empty<object>()));
			Health = ((BaseUnityPlugin)this).Config.Bind<int>("Host", "Health", 3, new ConfigDescription("Number of validated melee hits to defeat the mimic.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>()));
			ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>("Host", "SettingsRevision", 0, "Internal migration version for requested mimic behavior.");
			if (val.Value < 4)
			{
				Damage.Value = 40;
				if (Mathf.Approximately(ChaseSpeed.Value, 3.2f))
				{
					ChaseSpeed.Value = 12f;
				}
				val.Value = 4;
			}
			MimicAssets.Build();
			patches = new Harmony("WyattMorse.PresentMimic");
			patches.PatchAll();
			EnsureRuntime();
			Application.quitting += Shutdown;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Present Mimic 0.4.0 loaded: /present retains its 50% roll; cursed gifts ambush on pickup. Bracken-style acceleration, grounded gait, repeated 40-damage bites and creature vocals enabled.");
		}

		internal static void EnsureRuntime()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (!((Object)(object)runtime != (Object)null))
			{
				runtime = new GameObject("PresentMimic.Runtime");
				Object.DontDestroyOnLoad((Object)(object)runtime);
				runtime.AddComponent<MimicService>();
				runtime.AddComponent<PresentMimicPreview>();
			}
		}

		private static void Shutdown()
		{
			if ((Object)(object)runtime != (Object)null)
			{
				Object.Destroy((Object)(object)runtime);
			}
			runtime = null;
			Harmony? obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			patches = null;
			Application.quitting -= Shutdown;
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "Awake")]
	internal static class RestoreMimicRuntime
	{
		private static void Postfix()
		{
			Plugin.EnsureRuntime();
		}
	}
	internal static class PresentCommand
	{
		private static readonly FieldRef<GiftBoxItem, GameObject> Contents = AccessTools.FieldRefAccess<GiftBoxItem, GameObject>("objectInPresent");

		private static readonly FieldRef<GiftBoxItem, Item> ContentsItem = AccessTools.FieldRefAccess<GiftBoxItem, Item>("objectInPresentItem");

		private static readonly FieldRef<GiftBoxItem, int> ContentsValue = AccessTools.FieldRefAccess<GiftBoxItem, int>("objectInPresentValue");

		private static readonly FieldRef<GiftBoxItem, bool> Prepared = AccessTools.FieldRefAccess<GiftBoxItem, bool>("loadedItemFromSave");

		private static readonly Random Random = new Random();

		private static float nextSpawn;

		private static readonly HashSet<GiftBoxItem> Ambushes = new HashSet<GiftBoxItem>();

		private static readonly HashSet<GiftBoxItem> Opened = new HashSet<GiftBoxItem>();

		private static readonly FieldInfo RpcStage = AccessTools.Field(typeof(NetworkBehaviour), "__rpc_exec_stage");

		private static float nextDiscovery;

		internal static void Watch(GiftBoxItem gift)
		{
			if ((Object)(object)gift != (Object)null && (Object)(object)ContentsItem.Invoke(gift) == (Object)(object)MimicAssets.Definition)
			{
				Ambushes.Add(gift);
			}
		}

		internal static void TickPickupAmbushes()
		{
			if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer)
			{
				return;
			}
			if (Time.unscaledTime >= nextDiscovery)
			{
				nextDiscovery = Time.unscaledTime + 1f;
				GiftBoxItem[] array = Object.FindObjectsOfType<GiftBoxItem>();
				foreach (GiftBoxItem val in array)
				{
					if (((NetworkBehaviour)val).IsSpawned)
					{
						Watch(val);
					}
				}
				Opened.RemoveWhere((GiftBoxItem g) => (Object)(object)g == (Object)null || !((NetworkBehaviour)g).IsSpawned);
			}
			GiftBoxItem[] array2 = Ambushes.ToArray();
			foreach (GiftBoxItem val2 in array2)
			{
				if ((Object)(object)val2 == (Object)null || ((GrabbableObject)val2).deactivated || Opened.Contains(val2))
				{
					Ambushes.Remove(val2);
				}
				else if (CanAmbush(val2))
				{
					val2.OpenGiftBoxServerRpc();
				}
			}
		}

		private static bool CanAmbush(GiftBoxItem gift)
		{
			return Plugin.Enabled.Value && ((NetworkBehaviour)gift).IsSpawned && ((GrabbableObject)gift).isHeld && (Object)(object)((GrabbableObject)gift).playerHeldBy != (Object)null && ((GrabbableObject)gift).playerHeldBy.isPlayerControlled && !((GrabbableObject)gift).playerHeldBy.isPlayerDead && ((GrabbableObject)gift).playerHeldBy.ItemSlots != null && (((GrabbableObject)gift).playerHeldBy.ItemSlots.Contains((GrabbableObject)(object)gift) || (Object)(object)((GrabbableObject)gift).playerHeldBy.ItemOnlySlot == (Object)(object)gift);
		}

		internal static bool GuardOpen(GiftBoxItem gift)
		{
			if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || (Object)(object)ContentsItem.Invoke(gift) != (Object)(object)MimicAssets.Definition)
			{
				return true;
			}
			if (RpcStage.GetValue(gift).ToString() != "Execute")
			{
				return true;
			}
			if (Opened.Contains(gift) || ((GrabbableObject)gift).deactivated || !CanAmbush(gift))
			{
				return false;
			}
			Opened.Add(gift);
			return true;
		}

		internal static void ResetAmbushes()
		{
			Ambushes.Clear();
			Opened.Clear();
			nextDiscovery = 0f;
		}

		internal static bool Matches(string text)
		{
			return string.Equals(text?.Trim(), "/present", StringComparison.OrdinalIgnoreCase);
		}

		internal static bool IsMimicRoll(double roll)
		{
			return roll >= 0.0 && roll < 0.5;
		}

		internal static void Spawn()
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: 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_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			StartOfRound instance = StartOfRound.Instance;
			PlayerControllerB val = (((Object)(object)instance != (Object)null) ? instance.localPlayerController : null);
			if ((Object)(object)singleton == (Object)null || !singleton.IsListening || !singleton.IsServer)
			{
				Tip("Only the host can spawn a present.");
				return;
			}
			if ((Object)(object)val == (Object)null || val.isPlayerDead || !val.isPlayerControlled || instance.shipIsLeaving || (Object)(object)RoundManager.Instance == (Object)null)
			{
				Tip("Join a round as a living player before spawning a present.");
				return;
			}
			if (!Plugin.Enabled.Value)
			{
				Tip("Present Mimic is disabled in the host configuration.");
				return;
			}
			if (Time.unscaledTime < nextSpawn)
			{
				Tip("Wait two seconds between presents.");
				return;
			}
			Item val2 = MimicAssets.VanillaGift();
			Item[] array = instance.allItemsList.itemsList.Where((Item i) => (Object)(object)i != (Object)null && i.isScrap && (Object)(object)i.spawnPrefab != (Object)null && (Object)(object)i.spawnPrefab.GetComponent<GrabbableObject>() != (Object)null && (Object)(object)i.spawnPrefab.GetComponent<GiftBoxItem>() == (Object)null && i.maxValue > 0).ToArray();
			if ((Object)(object)val2 == (Object)null || array.Length == 0)
			{
				Tip("The game's gift and loot prefabs are not ready yet.");
				return;
			}
			Vector3 val3 = Vector3.ProjectOnPlane(((Component)val.gameplayCamera).transform.forward, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			Vector3 val4 = ((Component)val).transform.position + Vector3.up * 0.8f;
			Vector3 val5 = val4 + normalized * 1.1f;
			RaycastHit val6 = default(RaycastHit);
			if (Physics.Linecast(val4, val5, ref val6, instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
			{
				val5 = ((RaycastHit)(ref val6)).point - normalized * 0.3f;
			}
			RaycastHit val7 = default(RaycastHit);
			if (Physics.Raycast(val5, Vector3.down, ref val7, 4f, instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1))
			{
				val5 = ((RaycastHit)(ref val7)).point + Vector3.up * 0.25f;
				bool flag = IsMimicRoll(Random.NextDouble());
				Item val8 = (flag ? MimicAssets.Definition : array[Random.Next(array.Length)]);
				GameObject val9 = Object.Instantiate<GameObject>(val2.spawnPrefab, val5, Quaternion.identity);
				try
				{
					GiftBoxItem component = val9.GetComponent<GiftBoxItem>();
					ContentsItem.Invoke(component) = val8;
					Contents.Invoke(component) = (flag ? MimicAssets.OpenedPrefab : val8.spawnPrefab);
					ContentsValue.Invoke(component) = ((!flag) ? Mathf.Max(1, (int)((float)Random.Next(val8.minValue + 25, Math.Max(val8.minValue + 26, val8.maxValue + 35)) * RoundManager.Instance.scrapValueMultiplier)) : 0);
					Prepared.Invoke(component) = true;
					((GrabbableObject)component).SetScrapValue(0);
					((NetworkBehaviour)component).NetworkObject.Spawn(false);
					if (flag)
					{
						Watch(component);
					}
					((GrabbableObject)component).isInElevator = (((GrabbableObject)component).isInShipRoom = val.isInHangarShipRoom);
					nextSpawn = Time.unscaledTime + 2f;
					Tip("Present spawned. 50% ambush on pickup [E]. Safe gifts open normally [LMB].");
					Plugin.Log.LogInfo((object)"Spawned a vanilla command gift with a single host-authoritative 50% roll.");
					return;
				}
				catch (Exception ex)
				{
					NetworkObject component2 = val9.GetComponent<NetworkObject>();
					if ((Object)(object)component2 != (Object)null && component2.IsSpawned)
					{
						component2.Despawn(true);
					}
					else
					{
						Object.Destroy((Object)(object)val9);
					}
					Plugin.Log.LogError((object)("Could not spawn the command present: " + ex));
					Tip("Could not spawn the present. See Present Mimic's log.");
					return;
				}
			}
			Tip("Stand near a clear floor before spawning a present.");
		}

		private static void Tip(string message)
		{
			HUDManager instance = HUDManager.Instance;
			if (instance != null)
			{
				instance.DisplayTip("Present", message, false, false, "PresentMimicCommand");
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
	internal static class PresentChatCommand
	{
		[HarmonyPriority(800)]
		private static void Prefix(HUDManager __instance, CallbackContext context)
		{
			PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
			if (((CallbackContext)(ref context)).performed && !((Object)(object)val == (Object)null) && val.isTypingChat && !val.isPlayerDead && PresentCommand.Matches(__instance.chatTextField.text))
			{
				__instance.chatTextField.text = "";
				PresentCommand.Spawn();
			}
		}
	}
	[HarmonyPatch(typeof(GiftBoxItem), "LoadItemSaveData")]
	internal static class RestoreSavedMimicGift
	{
		private static void Postfix(GiftBoxItem __instance, Item ___objectInPresentItem, ref GameObject ___objectInPresent)
		{
			if ((Object)(object)___objectInPresentItem == (Object)(object)MimicAssets.Definition)
			{
				___objectInPresent = MimicAssets.OpenedPrefab;
				PresentCommand.Watch(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(GiftBoxItem), "OpenGiftBoxServerRpc")]
	internal static class OnePickupAmbush
	{
		private static bool Prefix(GiftBoxItem __instance)
		{
			return PresentCommand.GuardOpen(__instance);
		}
	}
	internal sealed class PresentMimicPreview : MonoBehaviour
	{
		private PresentMimicVisual? preview;

		private StartOfRound? ownerRound;

		private bool revealing;

		private float revealStart;

		private void Update()
		{
			StartOfRound instance = StartOfRound.Instance;
			if (!Plugin.EnableVisualPreview.Value || (Object)(object)instance == (Object)null || ((Object)(object)ownerRound != (Object)null && (Object)(object)ownerRound != (Object)(object)instance))
			{
				Clear();
				return;
			}
			PlayerControllerB localPlayerController = instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				if (((ButtonControl)current.f10Key).wasPressedThisFrame)
				{
					Clear();
				}
				if (!localPlayerController.isPlayerDead && localPlayerController.isPlayerControlled && (Object)(object)localPlayerController.gameplayCamera != (Object)null)
				{
					if (((ButtonControl)current.f8Key).wasPressedThisFrame)
					{
						Place(instance);
					}
					if (((ButtonControl)current.f9Key).wasPressedThisFrame && (Object)(object)preview != (Object)null)
					{
						revealing = !revealing;
						revealStart = Time.time;
						Tip(revealing ? "Revealing the mimic." : "Reset to the original present size.");
					}
				}
			}
			if ((Object)(object)preview != (Object)null)
			{
				float num = Mathf.Max(0f, Time.time - revealStart);
				preview.SetPose(revealing ? Mathf.Clamp01(num / Mathf.Clamp(Plugin.RevealSeconds.Value, 0.5f, 5f)) : 0f, revealing ? num : 0f);
			}
		}

		private void Place(StartOfRound round)
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00e2: 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_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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_012d: 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_0137: 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_0139: 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_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)round.allItemsList == (Object)null || round.allItemsList.itemsList == null)
			{
				return;
			}
			Item val = null;
			foreach (Item items in round.allItemsList.itemsList)
			{
				if ((Object)(object)items != (Object)null && (Object)(object)items.spawnPrefab != (Object)null && (Object)(object)items.spawnPrefab.GetComponent<GiftBoxItem>() != (Object)null)
				{
					val = items;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Tip("Vanilla present prefab is not available in this session.");
				return;
			}
			PlayerControllerB localPlayerController = round.localPlayerController;
			Vector3 val2 = Vector3.ProjectOnPlane(((Component)localPlayerController.gameplayCamera).transform.forward, Vector3.up);
			Vector3 val3 = ((Vector3)(ref val2)).normalized;
			if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
			{
				val3 = ((Component)localPlayerController).transform.forward;
			}
			Vector3 val4 = ((Component)localPlayerController).transform.position + val3 * 4f + Vector3.up * 2f;
			RaycastHit val5 = default(RaycastHit);
			if (!Physics.Raycast(val4, Vector3.down, ref val5, 8f, -5, (QueryTriggerInteraction)1))
			{
				Tip("No floor ahead for a visual preview.");
				return;
			}
			Clear();
			GameObject val6 = new GameObject("PresentMimic local visual preview (no gameplay)");
			try
			{
				val6.transform.position = ((RaycastHit)(ref val5)).point + Vector3.up * 0.015f;
				val6.transform.rotation = Quaternion.LookRotation(-val3, Vector3.up);
				preview = val6.AddComponent<PresentMimicVisual>();
				preview.Initialize(val.spawnPrefab, Quaternion.Euler(val.restingRotation), Plugin.RevealedBoxScale.Value);
				ownerRound = round;
				revealing = false;
				revealStart = Time.time;
				Tip("F9: grow/reveal or reset. F10: remove. This preview is visible only to you.");
				Plugin.Log.LogInfo((object)$"Visual preview uses vanilla '{val.itemName}' meshes/materials; dormant width {preview.DormantWidth:F3} m, growth {Plugin.RevealedBoxScale.Value:F2}x. No real gift was spawned or modified.");
			}
			catch (Exception ex)
			{
				Object.Destroy((Object)(object)val6);
				preview = null;
				Plugin.Log.LogError((object)("Could not create the present visual; no gameplay objects were changed. " + ex));
				Tip("Preview could not be built. See the PresentMimic log entry.");
			}
		}

		private static void Tip(string text)
		{
			if ((Object)(object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.DisplayTip("Present Mimic visual preview", text, false, false, "PMVisualPreview");
			}
		}

		private void Clear()
		{
			if ((Object)(object)preview != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)preview).gameObject);
			}
			preview = null;
			ownerRound = null;
			revealing = false;
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "WyattMorse.PresentMimic";

		public const string PLUGIN_NAME = "PresentMimic";

		public const string PLUGIN_VERSION = "0.4.0";
	}
}
namespace PresentMimic.Visuals
{
	public sealed class GiftShell
	{
		public sealed class Part
		{
			public Mesh Mesh;

			public Material[] Materials;

			public Part(Mesh mesh, Material[] materials)
			{
				Mesh = mesh;
				Materials = materials;
			}
		}

		private struct Vertex
		{
			public Vector3 Position;

			public Vector3 Normal;

			public Vector4 Tangent;

			public Color Color;

			public Vector4[] UV;

			public static Vertex Lerp(Vertex a, Vertex b, float t)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: 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_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: 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_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: 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_009c: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				Vector4[] array = (Vector4[])(object)new Vector4[8];
				for (int i = 0; i < 8; i++)
				{
					array[i] = Vector4.LerpUnclamped(a.UV[i], b.UV[i], t);
				}
				Vertex result = new Vertex
				{
					Position = Vector3.LerpUnclamped(a.Position, b.Position, t)
				};
				Vector3 val = Vector3.LerpUnclamped(a.Normal, b.Normal, t);
				result.Normal = ((Vector3)(ref val)).normalized;
				result.Tangent = Vector4.LerpUnclamped(a.Tangent, b.Tangent, t);
				result.Color = Color.LerpUnclamped(a.Color, b.Color, t);
				result.UV = array;
				return result;
			}
		}

		public readonly List<Part> Parts = new List<Part>();

		public Bounds Bounds { get; private set; }

		public float Width { get; private set; }

		public static GiftShell Capture(GameObject source, Quaternion restingRotation)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00c6: 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)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: 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_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: 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_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
			GiftShell giftShell = new GiftShell();
			try
			{
				bool flag = true;
				Matrix4x4 val = Matrix4x4.TRS(Vector3.zero, restingRotation, source.transform.localScale) * source.transform.worldToLocalMatrix;
				MeshFilter[] componentsInChildren = source.GetComponentsInChildren<MeshFilter>(true);
				foreach (MeshFilter val2 in componentsInChildren)
				{
					MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
					if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || (Object)(object)val2.sharedMesh == (Object)null)
					{
						continue;
					}
					Mesh val3 = ReadMesh(val2.sharedMesh);
					Matrix4x4 val4 = val * ((Component)val2).transform.localToWorldMatrix;
					Vector3[] vertices = val3.vertices;
					Vector3[] normals = val3.normals;
					Vector4[] tangents = val3.tangents;
					Matrix4x4 inverse = ((Matrix4x4)(ref val4)).inverse;
					Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
					for (int j = 0; j < vertices.Length; j++)
					{
						vertices[j] = ((Matrix4x4)(ref val4)).MultiplyPoint3x4(vertices[j]);
						if (flag)
						{
							giftShell.Bounds = new Bounds(vertices[j], Vector3.zero);
							flag = false;
						}
						else
						{
							Bounds bounds = giftShell.Bounds;
							((Bounds)(ref bounds)).Encapsulate(vertices[j]);
							giftShell.Bounds = bounds;
						}
						Vector3 val5;
						if (j < normals.Length)
						{
							int num = j;
							val5 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[j]);
							normals[num] = ((Vector3)(ref val5)).normalized;
						}
						if (j < tangents.Length)
						{
							val5 = ((Matrix4x4)(ref val4)).MultiplyVector(Vector4.op_Implicit(tangents[j]));
							Vector3 normalized = ((Vector3)(ref val5)).normalized;
							tangents[j] = new Vector4(normalized.x, normalized.y, normalized.z, tangents[j].w * Mathf.Sign(((Matrix4x4)(ref val4)).determinant));
						}
					}
					val3.vertices = vertices;
					val3.normals = normals;
					val3.tangents = tangents;
					if (((Matrix4x4)(ref val4)).determinant < 0f)
					{
						for (int k = 0; k < val3.subMeshCount; k++)
						{
							int[] triangles = val3.GetTriangles(k);
							for (int l = 0; l < triangles.Length; l += 3)
							{
								int num2 = triangles[l];
								triangles[l] = triangles[l + 1];
								triangles[l + 1] = num2;
							}
							val3.SetTriangles(triangles, k);
						}
					}
					giftShell.Parts.Add(new Part(val3, ((Renderer)component).sharedMaterials));
				}
				if (!flag)
				{
					Bounds bounds2 = giftShell.Bounds;
					if (!(((Bounds)(ref bounds2)).size.x < 0.001f))
					{
						bounds2 = giftShell.Bounds;
						giftShell.Width = ((Bounds)(ref bounds2)).size.x;
						bounds2 = giftShell.Bounds;
						float x = ((Bounds)(ref bounds2)).center.x;
						bounds2 = giftShell.Bounds;
						float y = ((Bounds)(ref bounds2)).min.y;
						bounds2 = giftShell.Bounds;
						Vector3 val6 = default(Vector3);
						((Vector3)(ref val6))..ctor(x, y, ((Bounds)(ref bounds2)).center.z);
						foreach (Part part in giftShell.Parts)
						{
							Vector3[] vertices2 = part.Mesh.vertices;
							for (int m = 0; m < vertices2.Length; m++)
							{
								vertices2[m] = (vertices2[m] - val6) / giftShell.Width;
							}
							part.Mesh.vertices = vertices2;
							part.Mesh.RecalculateBounds();
						}
						bounds2 = giftShell.Bounds;
						Vector3 val7 = (((Bounds)(ref bounds2)).center - val6) / giftShell.Width;
						bounds2 = giftShell.Bounds;
						giftShell.Bounds = new Bounds(val7, ((Bounds)(ref bounds2)).size / giftShell.Width);
						return giftShell;
					}
				}
				throw new InvalidOperationException("Gift has no usable mesh renderers.");
			}
			catch
			{
				giftShell.Dispose();
				throw;
			}
		}

		private static Mesh ReadMesh(Mesh source)
		{
			//IL_0017: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: 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)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Invalid comparison between Unknown and I4
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			if (source.isReadable)
			{
				return Object.Instantiate<Mesh>(source);
			}
			Mesh val = new Mesh
			{
				name = ((Object)source).name + " (mimic copy)",
				indexFormat = source.indexFormat
			};
			try
			{
				Dictionary<int, byte[]> dictionary = new Dictionary<int, byte[]>();
				for (int i = 0; i < source.vertexBufferCount; i++)
				{
					GraphicsBuffer vertexBuffer = source.GetVertexBuffer(i);
					try
					{
						byte[] array = new byte[vertexBuffer.count * vertexBuffer.stride];
						vertexBuffer.GetData((Array)array);
						dictionary.Add(i, array);
					}
					finally
					{
						((IDisposable)vertexBuffer)?.Dispose();
					}
				}
				Vector3[] array2 = (Vector3[])(object)new Vector3[source.vertexCount];
				Vector3[] array3 = (Vector3[])(object)new Vector3[source.vertexCount];
				Vector4[] array4 = (Vector4[])(object)new Vector4[source.vertexCount];
				Color[] array5 = (Color[])(object)new Color[source.vertexCount];
				List<Vector4>[] array6 = new List<Vector4>[8];
				for (int j = 0; j < 8; j++)
				{
					array6[j] = new List<Vector4>(source.vertexCount);
				}
				for (int k = 0; k < source.vertexCount; k++)
				{
					array2[k] = Vector4.op_Implicit(ReadAttribute(source, dictionary, (VertexAttribute)0, k));
					array3[k] = Vector4.op_Implicit(ReadAttribute(source, dictionary, (VertexAttribute)1, k));
					array4[k] = ReadAttribute(source, dictionary, (VertexAttribute)2, k);
					array5[k] = Color.op_Implicit(ReadAttribute(source, dictionary, (VertexAttribute)3, k));
					for (int l = 0; l < 8; l++)
					{
						if (source.HasVertexAttribute((VertexAttribute)(4 + l)))
						{
							array6[l].Add(ReadAttribute(source, dictionary, (VertexAttribute)(4 + l), k));
						}
					}
				}
				val.vertices = array2;
				if (source.HasVertexAttribute((VertexAttribute)1))
				{
					val.normals = array3;
				}
				if (source.HasVertexAttribute((VertexAttribute)2))
				{
					val.tangents = array4;
				}
				if (source.HasVertexAttribute((VertexAttribute)3))
				{
					val.colors = array5;
				}
				for (int m = 0; m < 8; m++)
				{
					if (array6[m].Count > 0)
					{
						val.SetUVs(m, array6[m]);
					}
				}
				GraphicsBuffer indexBuffer = source.GetIndexBuffer();
				try
				{
					byte[] array7 = new byte[indexBuffer.count * indexBuffer.stride];
					indexBuffer.GetData((Array)array7);
					val.subMeshCount = source.subMeshCount;
					for (int n = 0; n < source.subMeshCount; n++)
					{
						SubMeshDescriptor subMesh = source.GetSubMesh(n);
						if ((int)((SubMeshDescriptor)(ref subMesh)).topology > 0)
						{
							throw new InvalidOperationException("Gift mesh must use triangles.");
						}
						int[] array8 = new int[((SubMeshDescriptor)(ref subMesh)).indexCount];
						for (int num = 0; num < array8.Length; num++)
						{
							int num2 = ((SubMeshDescriptor)(ref subMesh)).indexStart + num;
							array8[num] = (int)(((int)source.indexFormat == 0) ? BitConverter.ToUInt16(array7, num2 * 2) : BitConverter.ToUInt32(array7, num2 * 4)) + ((SubMeshDescriptor)(ref subMesh)).baseVertex;
						}
						val.SetTriangles(array8, n);
					}
				}
				finally
				{
					((IDisposable)indexBuffer)?.Dispose();
				}
				if (!source.HasVertexAttribute((VertexAttribute)1))
				{
					val.RecalculateNormals();
				}
				val.RecalculateBounds();
				return val;
			}
			catch
			{
				DestroyOwned((Object)(object)val);
				throw;
			}
		}

		private unsafe static Vector4 ReadAttribute(Mesh mesh, Dictionary<int, byte[]> streams, VertexAttribute attribute, int vertex)
		{
			//IL_0002: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003f: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0195: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			//IL_017e: 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