Decompiled source of EchoMannequin v1.2.12

BepInEx/plugins/EchoMannequin/EchoMannequin.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EchoMannequinMod
{
	internal static class DynamicIconCapture
	{
		private const int CaptureLayer = 31;

		internal static Sprite Capture(Transform model)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: 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_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Expected O, but got Unknown
			//IL_02f0: 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_0345: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)model == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = ((Component)model).GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren.Length == 0)
			{
				return null;
			}
			bool flag = false;
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(model.position, Vector3.one);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null) && val.enabled)
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			if (!flag)
			{
				return null;
			}
			Dictionary<GameObject, int> dictionary = new Dictionary<GameObject, int>();
			Transform[] componentsInChildren2 = ((Component)model).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				dictionary[((Component)val2).gameObject] = ((Component)val2).gameObject.layer;
				((Component)val2).gameObject.layer = 31;
			}
			RenderTexture val3 = null;
			Texture2D val4 = null;
			GameObject val5 = null;
			Camera val6 = null;
			RenderTexture active = RenderTexture.active;
			GameObject val7 = null;
			GameObject val8 = null;
			try
			{
				val3 = new RenderTexture(256, 256, 24, (RenderTextureFormat)0);
				val3.antiAliasing = 2;
				val3.Create();
				val5 = new GameObject("Echo Icon Camera");
				val6 = val5.AddComponent<Camera>();
				((Behaviour)val6).enabled = false;
				val6.clearFlags = (CameraClearFlags)2;
				val6.backgroundColor = new Color(0f, 0f, 0f, 0f);
				val6.cullingMask = int.MinValue;
				val6.orthographic = true;
				val6.nearClipPlane = 0.01f;
				val6.farClipPlane = 20f;
				float num = Mathf.Max(((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.y) * 1.2f;
				val6.orthographicSize = Mathf.Max(0.25f, num);
				Vector3 val9 = new Vector3(0.65f, 0.18f, -1f);
				Vector3 normalized = ((Vector3)(ref val9)).normalized;
				Transform transform = ((Component)val6).transform;
				Vector3 center = ((Bounds)(ref bounds)).center;
				val9 = ((Bounds)(ref bounds)).extents;
				transform.position = center + normalized * Mathf.Max(2f, ((Vector3)(ref val9)).magnitude * 3f);
				((Component)val6).transform.LookAt(((Bounds)(ref bounds)).center);
				val6.targetTexture = val3;
				val7 = CreateLight("Echo Icon Key", ((Bounds)(ref bounds)).center + new Vector3(-1f, 2f, -2f), new Color(0.78f, 0.9f, 1f), 1.4f);
				val8 = CreateLight("Echo Icon Fill", ((Bounds)(ref bounds)).center + new Vector3(1.5f, 0.4f, 1f), new Color(0.35f, 0.85f, 0.9f), 0.7f);
				val6.Render();
				RenderTexture.active = val3;
				val4 = new Texture2D(256, 256, (TextureFormat)4, false);
				val4.ReadPixels(new Rect(0f, 0f, 256f, 256f), 0, 0);
				val4.Apply(false, false);
				RenderTexture.active = active;
				((Object)val4).name = "Echo Mannequin Live Icon";
				((Texture)val4).wrapMode = (TextureWrapMode)1;
				Sprite obj = Sprite.Create(val4, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f), 100f);
				((Object)obj).name = "Echo Mannequin Live Icon";
				return obj;
			}
			catch
			{
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
				return null;
			}
			finally
			{
				foreach (KeyValuePair<GameObject, int> item in dictionary)
				{
					if ((Object)(object)item.Key != (Object)null)
					{
						item.Key.layer = item.Value;
					}
				}
				if ((Object)(object)val6 != (Object)null)
				{
					val6.targetTexture = null;
				}
				if ((Object)(object)RenderTexture.active == (Object)(object)val3)
				{
					RenderTexture.active = active;
				}
				if ((Object)(object)val5 != (Object)null)
				{
					Object.Destroy((Object)(object)val5);
				}
				if ((Object)(object)val7 != (Object)null)
				{
					Object.Destroy((Object)(object)val7);
				}
				if ((Object)(object)val8 != (Object)null)
				{
					Object.Destroy((Object)(object)val8);
				}
				if ((Object)(object)val3 != (Object)null)
				{
					val3.Release();
					Object.Destroy((Object)(object)val3);
				}
			}
		}

		private static GameObject CreateLight(string name, Vector3 position, Color color, float intensity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0043: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.position = position;
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.range = 6f;
			obj.intensity = intensity;
			obj.color = color;
			obj.cullingMask = int.MinValue;
			return val;
		}
	}
	internal sealed class GroundedMotion
	{
		private bool sampled;

		private bool wasGrounded;

		internal bool Active { get; private set; }

		internal void Reset()
		{
			Active = false;
			sampled = false;
		}

		internal void ForceActive(bool ownerGrounded)
		{
			Active = true;
			sampled = true;
			wasGrounded = ownerGrounded;
		}

		internal bool Step(bool held, bool floorContact, bool ownerGrounded, float upwardSpeed, int mode)
		{
			bool active = Active;
			if (held)
			{
				Active = false;
			}
			else if (floorContact)
			{
				Active = true;
			}
			bool result = sampled && active && Active && !held && mode != 2 && wasGrounded && !ownerGrounded && upwardSpeed > 0.5f;
			sampled = true;
			wasGrounded = ownerGrounded;
			return result;
		}
	}
	internal sealed class LiveReplica
	{
		private readonly Transform root;

		private readonly PlayerAvatar owner;

		private readonly bool neutralPreview;

		private readonly Dictionary<Transform, Transform> transforms = new Dictionary<Transform, Transform>();

		private readonly Dictionary<Renderer, Renderer> renderers = new Dictionary<Renderer, Renderer>();

		private readonly Dictionary<Renderer, Material[]> neutralMaterials = new Dictionary<Renderer, Material[]>();

		private float nextScan;

		private float floorOffset;

		private bool hasPose;

		private static readonly FieldInfo TumbleOwner = AccessTools.Field(typeof(PlayerTumble), "playerAvatar");

		private static readonly FieldInfo CosmeticOwner = AccessTools.Field(typeof(PlayerMaterial), "cosmetic");

		private bool hasTumblePreview;

		internal float Height { get; private set; }

		internal bool NeutralPreview => neutralPreview;

		internal LiveReplica(Transform root, PlayerAvatar owner, bool neutralPreview = false)
		{
			this.root = root;
			this.owner = owner;
			this.neutralPreview = neutralPreview;
			Height = 1.25f;
		}

		private bool IsOwnerTumble(Renderer renderer)
		{
			PlayerTumble val = (((Object)(object)renderer != (Object)null) ? ((Component)renderer).GetComponentInParent<PlayerTumble>() : null);
			if ((Object)(object)val != (Object)null && TumbleOwner != null)
			{
				object? value = TumbleOwner.GetValue(val);
				return (Object)((value is PlayerAvatar) ? value : null) == (Object)(object)owner;
			}
			return false;
		}

		private bool IsBaseAvatarRenderer(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null || (Object)(object)owner.playerAvatarVisuals == (Object)null || !((Component)renderer).transform.IsChildOf(((Component)owner.playerAvatarVisuals).transform))
			{
				return false;
			}
			PlayerMaterial component = ((Component)renderer).GetComponent<PlayerMaterial>();
			if (!((Object)(object)component == (Object)null) && !(CosmeticOwner == null))
			{
				return CosmeticOwner.GetValue(component) == null;
			}
			return true;
		}

		private bool IsNeutralRenderer(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<ItemAttributes>() != (Object)null)
			{
				return false;
			}
			PlayerMaterial component = ((Component)renderer).GetComponent<PlayerMaterial>();
			if (!((Object)(object)component == (Object)null) && !(CosmeticOwner == null))
			{
				return CosmeticOwner.GetValue(component) == null;
			}
			return true;
		}

		private Material[] NeutralMaterials(Renderer source)
		{
			if (neutralMaterials.TryGetValue(source, out var value))
			{
				return value;
			}
			value = ((IEnumerable<Material>)source.sharedMaterials).Select((Func<Material, Material>)delegate(Material material)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected O, but got Unknown
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)material == (Object)null)
				{
					return (Material)null;
				}
				Material val = new Material(material);
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(0.48f, 0.5f, 0.52f, 1f);
				string[] array = new string[5] { "_Color", "_BaseColor", "_ColorPrimary", "_ColorSecondary", "_FresnelColor" };
				foreach (string text in array)
				{
					if (val.HasProperty(text))
					{
						val.SetColor(text, val2);
					}
				}
				return val;
			}).ToArray();
			neutralMaterials[source] = value;
			return value;
		}

		private Transform Map(Transform source)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: 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_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//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_0162: 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_00cd: 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)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (transforms.TryGetValue(source, out var value))
			{
				return value;
			}
			Transform obj = (((Object)(object)source != (Object)(object)((Component)owner).transform && (Object)(object)source != (Object)(object)owner.playerTransform && (Object)(object)source.parent != (Object)null && (source.IsChildOf(((Component)owner).transform) || ((Object)(object)owner.playerTransform != (Object)null && source.IsChildOf(owner.playerTransform)))) ? Map(source.parent) : null);
			value = new GameObject(((Object)source).name).transform;
			value.SetParent(root, false);
			if ((Object)(object)obj != (Object)null)
			{
				value.localPosition = source.localPosition;
				value.localRotation = source.localRotation;
				value.localScale = source.localScale;
			}
			else
			{
				Quaternion val = Quaternion.Inverse(Quaternion.Euler(0f, ((Component)owner).transform.eulerAngles.y, 0f));
				value.localPosition = val * (source.position - ((Component)owner).transform.position) + Vector3.up * floorOffset;
				value.localRotation = val * source.rotation;
				value.localScale = source.lossyScale;
			}
			transforms.Add(source, value);
			return value;
		}

		private void Scan()
		{
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner.playerAvatarVisuals == (Object)null)
			{
				return;
			}
			HashSet<Renderer> hashSet = new HashSet<Renderer>(((Component)owner.playerAvatarVisuals).GetComponentsInChildren<Renderer>(true));
			if ((Object)(object)owner.playerCosmetics != (Object)null && AccessTools.Field(typeof(PlayerCosmetics), "cosmeticParents").GetValue(owner.playerCosmetics) is IEnumerable enumerable)
			{
				foreach (object item2 in enumerable)
				{
					if (item2 == null)
					{
						continue;
					}
					FieldInfo fieldInfo = AccessTools.Field(item2.GetType(), "parent");
					Transform val = (Transform)((fieldInfo != null) ? /*isinst with value type is only supported in some contexts*/: null);
					if ((Object)(object)val != (Object)null)
					{
						Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
						foreach (Renderer item in componentsInChildren)
						{
							hashSet.Add(item);
						}
					}
				}
			}
			Transform[] array = (Transform[])(object)new Transform[2]
			{
				((Component)owner).transform,
				owner.playerTransform
			};
			foreach (Transform val2 in array)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val3 in componentsInChildren)
				{
					PhysGrabObject componentInParent = ((Component)val3).GetComponentInParent<PhysGrabObject>();
					PlayerTumble componentInParent2 = ((Component)val3).GetComponentInParent<PlayerTumble>();
					bool flag = (Object)(object)componentInParent2 != (Object)null && TumbleOwner != null && (Object)/*isinst with value type is only supported in some contexts*/ == (Object)(object)owner;
					if (!((Object)(object)((Component)val3).GetComponentInParent<MannequinController>() != (Object)null) && !((Object)(object)((Component)val3).GetComponentInParent<Camera>() != (Object)null) && !((Object)(object)((Component)val3).GetComponentInParent<Canvas>() != (Object)null) && (!((Object)(object)componentInParent != (Object)null) || flag) && (!((Object)(object)((Component)val3).GetComponentInParent<ItemAttributes>() != (Object)null) || flag))
					{
						PlayerAvatar componentInParent3 = ((Component)val3).GetComponentInParent<PlayerAvatar>();
						if (!((Object)(object)componentInParent3 != (Object)null) || !((Object)(object)componentInParent3 != (Object)(object)owner))
						{
							hashSet.Add(val3);
						}
					}
				}
			}
			hashSet.RemoveWhere(delegate(Renderer renderer)
			{
				if ((Object)(object)renderer == (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<MannequinController>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<Camera>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<Canvas>() != (Object)null)
				{
					return true;
				}
				PlayerTumble componentInParent4 = ((Component)renderer).GetComponentInParent<PlayerTumble>();
				if ((!((Object)(object)componentInParent4 != (Object)null) || !(TumbleOwner != null) || !((Object)/*isinst with value type is only supported in some contexts*/ == (Object)(object)owner)) && ((Object)(object)((Component)renderer).GetComponentInParent<PhysGrabObject>() != (Object)null || (Object)(object)((Component)renderer).GetComponentInParent<ItemAttributes>() != (Object)null))
				{
					return true;
				}
				PlayerAvatar componentInParent5 = ((Component)renderer).GetComponentInParent<PlayerAvatar>();
				return (Object)(object)componentInParent5 != (Object)null && (Object)(object)componentInParent5 != (Object)(object)owner;
			});
			if (neutralPreview)
			{
				Renderer[] tumbleRenderers = hashSet.Where((Renderer renderer) => IsOwnerTumble(renderer) && IsNeutralRenderer(renderer)).ToArray();
				hasTumblePreview = tumbleRenderers.Length != 0;
				hashSet.RemoveWhere((Renderer renderer) => (!hasTumblePreview) ? (!IsBaseAvatarRenderer(renderer)) : (!tumbleRenderers.Contains(renderer)));
			}
			foreach (Renderer item3 in hashSet)
			{
				if (!renderers.ContainsKey(item3))
				{
					SkinnedMeshRenderer val4 = (SkinnedMeshRenderer)(object)((item3 is SkinnedMeshRenderer) ? item3 : null);
					MeshRenderer val5 = (MeshRenderer)(object)((item3 is MeshRenderer) ? item3 : null);
					if ((Object)(object)val4 != (Object)null && (Object)(object)val4.sharedMesh != (Object)null)
					{
						SkinnedMeshRenderer val6 = ((Component)Map(((Component)item3).transform)).gameObject.AddComponent<SkinnedMeshRenderer>();
						val6.sharedMesh = val4.sharedMesh;
						val6.bones = val4.bones.Select(Map).ToArray();
						val6.rootBone = Map(val4.rootBone);
						((Renderer)val6).localBounds = ((Renderer)val4).localBounds;
						val6.updateWhenOffscreen = true;
						renderers.Add(item3, (Renderer)(object)val6);
					}
					else if ((Object)(object)val5 != (Object)null && (Object)(object)((Component)val5).GetComponent<MeshFilter>() != (Object)null)
					{
						GameObject gameObject = ((Component)Map(((Component)item3).transform)).gameObject;
						(gameObject.GetComponent<MeshFilter>() ?? gameObject.AddComponent<MeshFilter>()).sharedMesh = ((Component)val5).GetComponent<MeshFilter>().sharedMesh;
						renderers.Add(item3, (Renderer)(object)gameObject.AddComponent<MeshRenderer>());
					}
				}
			}
			KeyValuePair<Renderer, Renderer>[] array2 = renderers.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<Renderer, Renderer> keyValuePair = array2[i];
				if ((Object)(object)keyValuePair.Key == (Object)null || !hashSet.Contains(keyValuePair.Key))
				{
					if ((Object)(object)keyValuePair.Value != (Object)null)
					{
						Object.Destroy((Object)(object)keyValuePair.Value);
					}
					renderers.Remove(keyValuePair.Key);
				}
			}
			KeyValuePair<Transform, Transform>[] array3 = transforms.ToArray();
			for (int i = 0; i < array3.Length; i++)
			{
				KeyValuePair<Transform, Transform> keyValuePair2 = array3[i];
				if ((Object)(object)keyValuePair2.Key == (Object)null)
				{
					if ((Object)(object)keyValuePair2.Value != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)keyValuePair2.Value).gameObject);
					}
					transforms.Remove(keyValuePair2.Key);
				}
			}
		}

		private bool Visible(Renderer renderer)
		{
			PlayerAvatarVisuals playerAvatarVisuals = owner.playerAvatarVisuals;
			if (neutralPreview && IsOwnerTumble(renderer))
			{
				return true;
			}
			bool flag = ((Component)renderer).transform.IsChildOf(((Component)playerAvatarVisuals).transform);
			if (!renderer.enabled && !flag)
			{
				return false;
			}
			Transform val = ((Component)renderer).transform;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)((Component)playerAvatarVisuals).transform && (Object)(object)val != (Object)(object)((Component)owner).transform && (Object)(object)val != (Object)(object)owner.playerTransform)
			{
				if (!((Component)val).gameObject.activeSelf && (Object)(object)((Component)val).gameObject != (Object)(object)playerAvatarVisuals.meshParent)
				{
					return false;
				}
				val = val.parent;
			}
			return true;
		}

		internal void Tick(bool portable, bool freeze)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//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_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_04fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_052d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			if (Time.unscaledTime >= nextScan)
			{
				nextScan = Time.unscaledTime + 0.2f;
				Scan();
			}
			bool flag = !freeze || !hasPose;
			Vector3 position = ((Component)owner).transform.position;
			Quaternion val = Quaternion.Inverse(Quaternion.Euler(0f, ((Component)owner).transform.eulerAngles.y, 0f));
			foreach (KeyValuePair<Transform, Transform> transform in transforms)
			{
				if (flag && !((Object)(object)transform.Key == (Object)null) && !((Object)(object)transform.Value == (Object)null))
				{
					if ((Object)(object)transform.Key.parent != (Object)null && transforms.TryGetValue(transform.Key.parent, out var value) && (Object)(object)transform.Value.parent == (Object)(object)value)
					{
						transform.Value.localPosition = transform.Key.localPosition;
						transform.Value.localRotation = transform.Key.localRotation;
						transform.Value.localScale = transform.Key.localScale;
					}
					else
					{
						transform.Value.localPosition = val * (transform.Key.position - position) + Vector3.up * floorOffset;
						transform.Value.localRotation = val * transform.Key.rotation;
						transform.Value.localScale = transform.Key.lossyScale;
					}
				}
			}
			float num = float.PositiveInfinity;
			float num2 = float.NegativeInfinity;
			foreach (KeyValuePair<Renderer, Renderer> renderer in renderers)
			{
				if ((Object)(object)renderer.Key == (Object)null || (Object)(object)renderer.Value == (Object)null)
				{
					continue;
				}
				Renderer key = renderer.Key;
				Renderer value2 = renderer.Value;
				value2.enabled = Visible(key);
				value2.sharedMaterials = (neutralPreview ? NeutralMaterials(key) : key.sharedMaterials);
				value2.shadowCastingMode = (ShadowCastingMode)1;
				value2.receiveShadows = key.receiveShadows;
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((key is SkinnedMeshRenderer) ? key : null);
				SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((value2 is SkinnedMeshRenderer) ? value2 : null);
				if (key is MeshRenderer)
				{
					((Component)value2).GetComponent<MeshFilter>().sharedMesh = ((Component)key).GetComponent<MeshFilter>().sharedMesh;
				}
				if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null && (Object)(object)val2.sharedMesh != (Object)null)
				{
					if ((Object)(object)val3.sharedMesh != (Object)(object)val2.sharedMesh)
					{
						val3.sharedMesh = val2.sharedMesh;
						val3.bones = val2.bones.Select(Map).ToArray();
						val3.rootBone = Map(val2.rootBone);
					}
					if (flag)
					{
						for (int i = 0; i < val2.sharedMesh.blendShapeCount; i++)
						{
							val3.SetBlendShapeWeight(i, val2.GetBlendShapeWeight(i));
						}
					}
				}
				if (value2.enabled)
				{
					float num3 = num;
					Bounds bounds = key.bounds;
					num = Mathf.Min(num3, ((Bounds)(ref bounds)).min.y - position.y);
					float num4 = num2;
					bounds = key.bounds;
					num2 = Mathf.Max(num4, ((Bounds)(ref bounds)).max.y - position.y);
				}
			}
			if (flag && !float.IsInfinity(num) && !float.IsInfinity(num2))
			{
				float num5 = 0f - num - floorOffset;
				floorOffset = 0f - num;
				foreach (KeyValuePair<Transform, Transform> transform2 in transforms)
				{
					if ((Object)(object)transform2.Value != (Object)null && (Object)(object)transform2.Value.parent == (Object)(object)root)
					{
						Transform value3 = transform2.Value;
						value3.localPosition += Vector3.up * num5;
					}
				}
				Height = Mathf.Clamp(num2 + floorOffset, 0.5f, 2.5f);
			}
			hasPose = transforms.Count > 0;
			if (neutralPreview && !hasTumblePreview)
			{
				root.localRotation = Quaternion.Euler(90f, 0f, 0f);
				root.localScale = new Vector3(-0.3f, 0.12f, 0.3f);
			}
			else
			{
				root.localRotation = Quaternion.identity;
				root.localScale = new Vector3(-1f, 1f, 1f) * (portable ? 0.3f : 1f);
			}
		}

		internal void Dispose()
		{
			foreach (Material[] value in neutralMaterials.Values)
			{
				foreach (Material val in value)
				{
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
			neutralMaterials.Clear();
		}
	}
	[DefaultExecutionOrder(10000)]
	public sealed class MannequinController : MonoBehaviour, IPunObservable
	{
		private static readonly FieldInfo OwnerId = AccessTools.Field(typeof(ItemEquippable), "ownerPlayerId");

		private static readonly FieldInfo IsGrabbed = AccessTools.Field(typeof(PhysGrabObject), "grabbed");

		private ItemEquippable item;

		private PhysGrabObject physics;

		private Rigidbody body;

		private CapsuleCollider shape;

		private Transform model;

		private Transform neutralPreviewRoot;

		private Material neutralPreviewMaterial;

		private LiveReplica replica;

		private PlayerAvatar owner;

		private int ownerViewId;

		private Vector3 previousOwnerPosition;

		private RigidbodyConstraints originalConstraints;

		private bool moving;

		private readonly GroundedMotion motion = new GroundedMotion();

		private bool active;

		private float lastFloorContact = float.NegativeInfinity;

		private Vector3 floorPoint;

		private static readonly FieldInfo Grounded = AccessTools.Field(typeof(PlayerAvatar), "isGrounded");

		private static readonly FieldInfo OwnerVelocity = AccessTools.Field(typeof(PlayerAvatar), "rbVelocityRaw");

		private static readonly FieldInfo PlayerCurrentHealth = AccessTools.Field(typeof(PlayerHealth), "health");

		private static readonly FieldInfo PlayerMaximumHealth = AccessTools.Field(typeof(PlayerHealth), "maxHealth");

		private static readonly FieldInfo OwnerDead = AccessTools.Field(typeof(PlayerAvatar), "deadSet");

		private static readonly FieldInfo OwnerLocal = AccessTools.Field(typeof(PlayerAvatar), "isLocal");

		private static readonly FieldInfo ImpactDetector = AccessTools.Field(typeof(PhysGrabObject), "impactDetector");

		private static readonly MethodInfo NativeDestroyObject = AccessTools.Method(typeof(PhysGrabObjectImpactDetector), "DestroyObject", (Type[])null, (Type[])null);

		private static readonly FieldInfo PhysDead = AccessTools.Field(typeof(PhysGrabObject), "dead");

		private static readonly FieldInfo ForceGrabPoint = AccessTools.Field(typeof(PhysGrabObject), "forceGrabPoint");

		private static readonly FieldInfo MidPointOffset = AccessTools.Field(typeof(PhysGrabObject), "midPointOffset");

		private static readonly FieldInfo BoundingBox = AccessTools.Field(typeof(PhysGrabObject), "boundingBox");

		private static readonly FieldInfo ItemHeight = AccessTools.Field(typeof(PhysGrabObject), "itemHeightY");

		private static readonly FieldInfo ItemWidth = AccessTools.Field(typeof(PhysGrabObject), "itemWidthX");

		private static readonly FieldInfo ItemLength = AccessTools.Field(typeof(PhysGrabObject), "itemLengthZ");

		private float nextOwnerSearch;

		private int mode;

		private float mirrorYaw;

		private bool wasDeployed;

		private float nextModeChange;

		private ItemAttributes attributes;

		private int health;

		private int maxHealth;

		private int ownerMaxHealth;

		private bool shopPreview;

		private bool? portablePhysics;

		private bool destroyed;

		private bool wasStored;

		private bool iconCapturePending;

		private float iconCaptureAt;

		private Sprite liveIcon;

		private readonly List<Sprite> iconHistory = new List<Sprite>();

		private bool pendingDestroy;

		private bool nativeDestroyRequested;

		private bool forceUnequipRequested;

		private float externalPullUntil;

		private Vector3 externalPullTarget;

		private static readonly FieldInfo Grabbers = AccessTools.Field(typeof(PhysGrabObject), "playerGrabbing");

		private static readonly FieldInfo HeldObject = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject");

		private static readonly FieldInfo InputDisabled = AccessTools.Field(typeof(PlayerController), "InputDisableTimer");

		private static readonly string[] ModeNames = new string[3] { "1 — Обычный", "2 — Ходить на месте", "3 — Замереть" };

		private bool HeldLocally
		{
			get
			{
				if (!item.IsEquipped() && (Object)(object)PhysGrabber.instance != (Object)null && PhysGrabber.instance.grabbed)
				{
					object? value = HeldObject.GetValue(PhysGrabber.instance);
					return (Object)((value is PhysGrabObject) ? value : null) == (Object)(object)physics;
				}
				return false;
			}
		}

		private bool Authority
		{
			get
			{
				if (SemiFunc.IsMultiplayer())
				{
					return PhotonNetwork.IsMasterClient;
				}
				return true;
			}
		}

		private bool Grabbed
		{
			get
			{
				if ((Object)(object)physics != (Object)null)
				{
					return (bool)IsGrabbed.GetValue(physics);
				}
				return false;
			}
		}

		private bool Stored
		{
			get
			{
				if ((Object)(object)item != (Object)null)
				{
					return item.IsEquipped();
				}
				return false;
			}
		}

		internal bool IsLiveDecoy
		{
			get
			{
				if (active && !destroyed && health > 0 && !Grabbed)
				{
					return !Stored;
				}
				return false;
			}
		}

		internal PlayerAvatar Owner => owner;

		internal int Health => health;

		internal Vector3 DecoyPosition
		{
			get
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)shape != (Object)null))
				{
					return ((Component)this).transform.position;
				}
				Bounds bounds = ((Collider)shape).bounds;
				return ((Bounds)(ref bounds)).center;
			}
		}

		internal Transform DecoyAnchor
		{
			get
			{
				if (!((Object)(object)model != (Object)null))
				{
					return ((Component)this).transform;
				}
				return model;
			}
		}

		private void Awake()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			item = ((Component)this).GetComponent<ItemEquippable>();
			attributes = ((Component)this).GetComponent<ItemAttributes>();
			physics = ((Component)this).GetComponent<PhysGrabObject>();
			body = ((Component)this).GetComponent<Rigidbody>();
			shape = ((Component)((Component)this).transform.Find("Echo Body Collider")).GetComponent<CapsuleCollider>();
			if (ForceGrabPoint != null)
			{
				ForceGrabPoint.SetValue(physics, null);
			}
			body.centerOfMass = shape.center;
			originalConstraints = body.constraints;
			ApplyPhysicalProfile(portable: true);
		}

		private void Start()
		{
			portablePhysics = null;
			ApplyPhysicalProfile(portable: true);
			shopPreview = SemiFunc.RunIsShop();
			if (shopPreview)
			{
				CreateNeutralShopPreview();
			}
			MannequinFactory.ApplyRuntimeIcon(((Component)this).GetComponent<ItemAttributes>());
			MannequinDistraction.Register(this);
			wasStored = Stored;
		}

		private PlayerAvatar EquippedOwner()
		{
			if (!SemiFunc.IsMultiplayer())
			{
				return PlayerAvatar.instance;
			}
			PhotonView val = PhotonView.Find((int)OwnerId.GetValue(item));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			PlayerAvatar component = ((Component)val).GetComponent<PlayerAvatar>();
			PhysGrabber component2 = ((Component)val).GetComponent<PhysGrabber>();
			if (!((Object)(object)component != (Object)null))
			{
				if (!((Object)(object)component2 != (Object)null))
				{
					return null;
				}
				return component2.playerAvatar;
			}
			return component;
		}

		private void Bind(PlayerAvatar avatar, bool neutralPreview = false)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)avatar == (Object)null) && (!((Object)(object)owner == (Object)(object)avatar) || replica == null || replica.NeutralPreview != neutralPreview))
			{
				owner = avatar;
				ownerViewId = (((Object)(object)avatar.photonView != (Object)null) ? avatar.photonView.ViewID : 0);
				previousOwnerPosition = ((Component)owner).transform.position;
				if (replica != null)
				{
					replica.Dispose();
				}
				if ((Object)(object)model != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)model).gameObject);
				}
				if ((Object)(object)neutralPreviewRoot != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)neutralPreviewRoot).gameObject);
				}
				if ((Object)(object)neutralPreviewMaterial != (Object)null)
				{
					Object.Destroy((Object)(object)neutralPreviewMaterial);
				}
				neutralPreviewRoot = null;
				neutralPreviewMaterial = null;
				model = new GameObject("Echo Live Replica").transform;
				model.SetParent(((Component)this).transform, false);
				replica = new LiveReplica(model, owner, neutralPreview);
				iconCapturePending = !neutralPreview;
				iconCaptureAt = Time.unscaledTime + 0.2f;
				SyncOwnerHealth(reset: true);
				ApplyHealth(health, maxHealth);
				if (Authority)
				{
					motion.Reset();
					active = false;
					wasDeployed = false;
				}
			}
		}

		private void Update()
		{
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Invalid comparison between Unknown and I4
			PlayerAvatar val = null;
			if (Grabbed)
			{
				val = ((Grabbers.GetValue(physics) is List<PhysGrabber> source) ? (from grabber in source
					where (Object)(object)grabber != (Object)null && (Object)(object)grabber.playerAvatar != (Object)null
					select grabber.playerAvatar).FirstOrDefault() : null);
			}
			if (Authority && shopPreview && (Object)(object)val != (Object)null)
			{
				shopPreview = false;
				Bind(val);
				SetModeForEveryone(1);
			}
			bool stored = Stored;
			if (Authority && wasStored && !stored)
			{
				SetModeForEveryone(1);
			}
			if (!wasStored && stored && (Object)(object)model != (Object)null && replica != null && !destroyed)
			{
				replica.Tick(portable: true, mode == 2);
				CaptureLiveIcon();
			}
			wasStored = stored;
			if (HeldLocally && Keyboard.current != null && ((ButtonControl)Keyboard.current.eKey).wasPressedThisFrame && (int)Cursor.lockState == 1 && Time.timeScale > 0f && (Object)(object)PlayerController.instance != (Object)null && (float)InputDisabled.GetValue(PlayerController.instance) <= 0f && Time.unscaledTime >= nextModeChange)
			{
				nextModeChange = Time.unscaledTime + 0.25f;
				if (SemiFunc.IsMultiplayer())
				{
					((Component)this).GetComponent<PhotonView>().RPC("EchoModeRequest", (RpcTarget)2, new object[1] { mode });
				}
				else
				{
					SetMode(MirrorRules.NextMode(mode));
				}
			}
			if (Authority)
			{
				if (Stored)
				{
					shopPreview = false;
					Bind(EquippedOwner());
				}
				else if ((Object)(object)val != (Object)null)
				{
					Bind(val);
				}
				if (!shopPreview && (Object)(object)owner == (Object)null && Time.time >= nextOwnerSearch)
				{
					nextOwnerSearch = Time.time + 1f;
					Bind((from p in Object.FindObjectsOfType<PlayerAvatar>()
						where (Object)(object)p.playerAvatarVisuals != (Object)null && (Object)(object)((Component)p).GetComponent<MannequinController>() == (Object)null
						select p).OrderBy(delegate(PlayerAvatar p)
					{
						//IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references)
						Vector3 val3 = ((Component)p).transform.position - ((Component)this).transform.position;
						return ((Vector3)(ref val3)).sqrMagnitude;
					}).FirstOrDefault());
				}
			}
			else if (((Object)(object)owner == (Object)null || owner.photonView.ViewID != ownerViewId) && ownerViewId != 0)
			{
				PhotonView val2 = PhotonView.Find(ownerViewId);
				if ((Object)(object)val2 != (Object)null)
				{
					Bind(((Component)val2).GetComponent<PlayerAvatar>(), shopPreview);
				}
			}
			if ((Object)(object)owner == (Object)null)
			{
				if ((Object)(object)model != (Object)null)
				{
					((Component)model).gameObject.SetActive(false);
				}
				return;
			}
			SyncOwnerHealth(reset: false);
			if (Authority && !shopPreview && !destroyed && OwnerIsDead())
			{
				Hurt(Mathf.Max(1, health));
			}
			if (Stored || Grabbed)
			{
				lastFloorContact = float.NegativeInfinity;
				if (Authority)
				{
					motion.Reset();
					active = false;
				}
			}
		}

		private void CreateNeutralShopPreview()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: 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_017d: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)neutralPreviewRoot != (Object)null)
			{
				return;
			}
			neutralPreviewRoot = new GameObject("Echo Neutral Curled Mannequin").transform;
			neutralPreviewRoot.SetParent(((Component)this).transform, false);
			Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard");
			if ((Object)(object)val != (Object)null)
			{
				neutralPreviewMaterial = new Material(val);
			}
			if ((Object)(object)neutralPreviewMaterial != (Object)null)
			{
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(0.22f, 0.26f, 0.3f, 1f);
				string[] array = new string[5] { "_Color", "_BaseColor", "_ColorPrimary", "_ColorSecondary", "_FresnelColor" };
				foreach (string text in array)
				{
					if (neutralPreviewMaterial.HasProperty(text))
					{
						neutralPreviewMaterial.SetColor(text, val2);
					}
				}
			}
			AddPreviewPart("Body", (PrimitiveType)0, new Vector3(0f, 0.22f, 0f), Vector3.zero, new Vector3(0.34f, 0.29f, 0.3f));
			AddPreviewPart("Head", (PrimitiveType)0, new Vector3(0.14f, 0.28f, 0.08f), Vector3.zero, Vector3.one * 0.22f);
			AddPreviewPart("Arm L", (PrimitiveType)1, new Vector3(-0.13f, 0.21f, 0.11f), new Vector3(0f, 0f, 70f), new Vector3(0.095f, 0.18f, 0.095f));
			AddPreviewPart("Arm R", (PrimitiveType)1, new Vector3(0.02f, 0.15f, 0.14f), new Vector3(0f, 0f, 110f), new Vector3(0.095f, 0.18f, 0.095f));
			AddPreviewPart("Leg L", (PrimitiveType)1, new Vector3(-0.11f, 0.09f, 0f), new Vector3(0f, 0f, 82f), new Vector3(0.11f, 0.2f, 0.11f));
			AddPreviewPart("Leg R", (PrimitiveType)1, new Vector3(0.1f, 0.08f, -0.02f), new Vector3(0f, 0f, 98f), new Vector3(0.11f, 0.2f, 0.11f));
			AlignVisualToCollider(neutralPreviewRoot);
		}

		private void AddPreviewPart(string partName, PrimitiveType primitive, Vector3 position, Vector3 rotation, Vector3 scale)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			GameObject obj = GameObject.CreatePrimitive(primitive);
			((Object)obj).name = partName;
			obj.transform.SetParent(neutralPreviewRoot, false);
			obj.transform.localPosition = position;
			obj.transform.localEulerAngles = rotation;
			obj.transform.localScale = scale;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			Renderer component2 = obj.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)neutralPreviewMaterial != (Object)null)
			{
				component2.sharedMaterial = neutralPreviewMaterial;
			}
		}

		private void SyncOwnerHealth(bool reset)
		{
			if (Authority && !((Object)(object)owner == (Object)null) && !((Object)(object)owner.playerHealth == (Object)null))
			{
				int num = Mathf.Max(1, (int)PlayerMaximumHealth.GetValue(owner.playerHealth));
				if (reset || maxHealth <= 0)
				{
					health = Mathf.Clamp((int)PlayerCurrentHealth.GetValue(owner.playerHealth), 1, num);
				}
				else if (num != ownerMaxHealth)
				{
					health = Mathf.Clamp(health + num - ownerMaxHealth, 1, num);
				}
				ownerMaxHealth = num;
				maxHealth = num;
			}
		}

		private bool OwnerIsDead()
		{
			if ((Object)(object)owner == (Object)null || (Object)(object)owner.playerHealth == (Object)null)
			{
				return false;
			}
			if (!(OwnerDead != null) || !(bool)OwnerDead.GetValue(owner))
			{
				return (int)PlayerCurrentHealth.GetValue(owner.playerHealth) <= 0;
			}
			return true;
		}

		internal void Hurt(int damage)
		{
			if (Authority && !destroyed && damage > 0)
			{
				PlayHitFeedback();
				int num = Mathf.Max(0, health - damage);
				if (SemiFunc.IsMultiplayer())
				{
					((Component)this).GetComponent<PhotonView>().RPC("EchoHealthCommit", (RpcTarget)0, new object[2] { num, maxHealth });
				}
				else
				{
					ApplyHealth(num, maxHealth);
				}
			}
		}

		private void PlayHitFeedback()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			object? value = ImpactDetector.GetValue(physics);
			PhysGrabObjectImpactDetector val = (PhysGrabObjectImpactDetector)((value is PhysGrabObjectImpactDetector) ? value : null);
			MethodInfo methodInfo = AccessTools.Method(typeof(PhysGrabObjectImpactDetector), "ImpactLight", new Type[2]
			{
				typeof(float),
				typeof(Vector3)
			}, (Type[])null);
			if ((Object)(object)val != (Object)null && methodInfo != null)
			{
				methodInfo.Invoke(val, new object[2] { 24f, DecoyPosition });
			}
		}

		internal void PullToward(Vector3 target)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (Authority && !destroyed && !Grabbed && !Stored)
			{
				externalPullTarget = target;
				externalPullUntil = Time.time + 0.25f;
			}
		}

		[PunRPC]
		private void EchoHealthCommit(int nextHealth, int nextMax, PhotonMessageInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (info.Sender == PhotonNetwork.MasterClient)
			{
				ApplyHealth(nextHealth, nextMax);
			}
		}

		private void ApplyHealth(int nextHealth, int nextMax)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			bool num = health > 0 && nextHealth <= 0;
			maxHealth = Mathf.Max(1, nextMax);
			health = Mathf.Clamp(nextHealth, 0, maxHealth);
			destroyed = health <= 0;
			if ((Object)(object)shape != (Object)null)
			{
				((Collider)shape).enabled = true;
			}
			if (num && Authority)
			{
				pendingDestroy = true;
			}
			if (destroyed && Stored && !forceUnequipRequested && (Object)(object)owner != (Object)null && OwnerLocal != null && (bool)OwnerLocal.GetValue(owner) && (Object)(object)owner.photonView != (Object)null)
			{
				forceUnequipRequested = true;
				item.ForceUnequip(((Component)owner).transform.position + Vector3.up * 0.5f, owner.photonView.ViewID);
			}
		}

		private void FinishNativeDestruction()
		{
			if (Authority && pendingDestroy && !nativeDestroyRequested && !Grabbed && !Stored)
			{
				nativeDestroyRequested = true;
				pendingDestroy = false;
				object? value = ImpactDetector.GetValue(physics);
				PhysGrabObjectImpactDetector val = (PhysGrabObjectImpactDetector)((value is PhysGrabObjectImpactDetector) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					NativeDestroyObject.Invoke(val, new object[1] { true });
				}
				else
				{
					PhysDead.SetValue(physics, true);
				}
			}
		}

		private void OnCollisionEnter(Collision collision)
		{
			RecordFloor(collision);
		}

		private void OnCollisionStay(Collision collision)
		{
			RecordFloor(collision);
		}

		private bool FloorBelow()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = ((Collider)shape).bounds;
			RaycastHit[] array = Physics.RaycastAll(((Bounds)(ref bounds)).center, Vector3.down, ((Bounds)(ref bounds)).extents.y + 0.08f, -1, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if (((RaycastHit)(ref val)).normal.y >= 0.55f && (Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody != (Object)(object)body && (Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<PlayerAvatar>() == (Object)null && (Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<PlayerController>() == (Object)null && (Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<PhysGrabObject>() == (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private void RecordFloor(Collision collision)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!Authority || (Object)(object)item == (Object)null || Stored || Grabbed)
			{
				return;
			}
			Collider collider = collision.collider;
			if ((Object)(object)((Component)collider).GetComponentInParent<PlayerAvatar>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<PlayerController>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<PhysGrabObject>() != (Object)null)
			{
				return;
			}
			for (int i = 0; i < collision.contactCount; i++)
			{
				ContactPoint contact = collision.GetContact(i);
				if (!(((ContactPoint)(ref contact)).normal.y < 0.55f))
				{
					lastFloorContact = Time.fixedTime;
					floorPoint = ((ContactPoint)(ref contact)).point;
					break;
				}
			}
		}

		private void FixedUpdate()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: 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_02cf: 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_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			if (!Authority || (Object)(object)body == (Object)null)
			{
				return;
			}
			FinishNativeDestruction();
			if (shopPreview)
			{
				motion.Reset();
				active = false;
			}
			else
			{
				if ((Object)(object)owner == (Object)null)
				{
					return;
				}
				Vector3 position = ((Component)owner).transform.position;
				Vector3 val = position - previousOwnerPosition;
				previousOwnerPosition = position;
				bool flag = Stored || Grabbed;
				bool flag2 = Time.fixedTime - lastFloorContact <= Time.fixedDeltaTime * 2.1f;
				Vector3 val2 = (Vector3)OwnerVelocity.GetValue(owner);
				bool flag3 = motion.Step(flag, flag2, (bool)Grounded.GetValue(owner), val2.y, mode);
				active = motion.Active;
				if (flag || !active)
				{
					wasDeployed = false;
					if (moving)
					{
						body.constraints = originalConstraints;
						moving = false;
					}
				}
				else if (!body.isKinematic)
				{
					if (!wasDeployed)
					{
						mirrorYaw = ((Component)owner).transform.eulerAngles.y;
						body.position = new Vector3(body.position.x, floorPoint.y + 0.03f, body.position.z);
						body.velocity = Vector3.zero;
						body.MoveRotation(Quaternion.Euler(0f, mirrorYaw + 180f, 0f));
						wasDeployed = true;
					}
					moving = true;
					body.constraints = (RigidbodyConstraints)(originalConstraints | 0x70);
					bool flag4 = Time.time < externalPullUntil;
					if (mode != 0 && !flag4)
					{
						Rigidbody obj = body;
						obj.constraints = (RigidbodyConstraints)(obj.constraints | 0xA);
					}
					Vector3 val3 = val / Time.fixedDeltaTime;
					MirrorRules.Movement(val3.x, val3.z, mirrorYaw, mode, out var resultX, out var resultZ);
					val3.x = resultX;
					val3.z = resultZ;
					val3.y = 0f;
					if (((Vector3)(ref val)).sqrMagnitude > 4f)
					{
						val3 = Vector3.zero;
					}
					val3 = Vector3.ClampMagnitude(val3, 12f);
					val3.y = body.velocity.y;
					if (flag4)
					{
						Vector3 val4 = externalPullTarget - body.worldCenterOfMass;
						val3.x = Mathf.Clamp(val4.x * 4f, -9f, 9f);
						val3.z = Mathf.Clamp(val4.z * 4f, -9f, 9f);
						val3.y = Mathf.Max(val3.y, Mathf.Clamp(val4.y * 2f, -2f, 5f));
					}
					if (flag3 && (flag2 || FloorBelow()) && ((Vector3)(ref val)).sqrMagnitude <= 4f)
					{
						val3.y = val2.y;
					}
					body.velocity = val3;
					if (mode != 2)
					{
						body.MoveRotation(Quaternion.Euler(0f, MirrorRules.Facing(mirrorYaw, ((Component)owner).transform.eulerAngles.y), 0f));
					}
				}
			}
		}

		private void LateUpdate()
		{
			if ((Object)(object)owner == (Object)null || replica == null || (Object)(object)model == (Object)null)
			{
				return;
			}
			bool stored = Stored;
			((Component)model).gameObject.SetActive(!stored && !nativeDestroyRequested);
			if (!stored)
			{
				bool portable = shopPreview || Grabbed || !active;
				replica.Tick(portable, shopPreview || mode == 2);
				ApplyPhysicalProfile(portable);
				AlignVisualToCollider(model);
				if (!destroyed && iconCapturePending && Time.unscaledTime >= iconCaptureAt)
				{
					CaptureLiveIcon();
					iconCapturePending = false;
				}
			}
		}

		private void AlignVisualToCollider(Transform visualRoot)
		{
			//IL_0051: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)visualRoot == (Object)null || (Object)(object)shape == (Object)null)
			{
				return;
			}
			Renderer[] array = (from renderer in ((Component)visualRoot).GetComponentsInChildren<Renderer>(true)
				where (Object)(object)renderer != (Object)null && renderer.enabled
				select renderer).ToArray();
			if (array.Length != 0)
			{
				Bounds bounds = array[0].bounds;
				for (int num = 1; num < array.Length; num++)
				{
					((Bounds)(ref bounds)).Encapsulate(array[num].bounds);
				}
				Vector3 val = ((Component)this).transform.InverseTransformPoint(((Bounds)(ref bounds)).center);
				Vector3 val2 = shape.center - val;
				visualRoot.localPosition += val2;
			}
		}

		private void ApplyPhysicalProfile(bool portable)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)shape == (Object)null) && !((Object)(object)physics == (Object)null) && portablePhysics != portable)
			{
				portablePhysics = portable;
				float num = (portable ? 0.55f : 1.65f);
				float num2 = (portable ? 0.2f : 0.36f);
				shape.height = num;
				shape.radius = num2;
				shape.center = Vector3.up * num * 0.5f;
				if ((Object)(object)body != (Object)null)
				{
					body.centerOfMass = shape.center;
				}
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(num2 * 2f, num, num2 * 2f);
				if (MidPointOffset != null)
				{
					MidPointOffset.SetValue(physics, shape.center);
				}
				if (BoundingBox != null)
				{
					BoundingBox.SetValue(physics, val);
				}
				if (ItemHeight != null)
				{
					ItemHeight.SetValue(physics, num);
				}
				if (ItemWidth != null)
				{
					ItemWidth.SetValue(physics, num2 * 2f);
				}
				if (ItemLength != null)
				{
					ItemLength.SetValue(physics, num2 * 2f);
				}
			}
		}

		private void CaptureLiveIcon()
		{
			Sprite val = DynamicIconCapture.Capture(model);
			if (!((Object)(object)val == (Object)null))
			{
				liveIcon = val;
				iconHistory.Add(val);
				attributes.icon = val;
				item.ItemIcon = val;
			}
		}

		public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (stream.IsWriting)
			{
				stream.SendNext((object)ownerViewId);
				stream.SendNext((object)mode);
				stream.SendNext((object)mirrorYaw);
				stream.SendNext((object)active);
				stream.SendNext((object)health);
				stream.SendNext((object)maxHealth);
				stream.SendNext((object)shopPreview);
				return;
			}
			int num = (int)stream.ReceiveNext();
			int num2 = (int)stream.ReceiveNext();
			float num3 = (float)stream.ReceiveNext();
			bool flag = (bool)stream.ReceiveNext();
			int nextHealth = (int)stream.ReceiveNext();
			int nextMax = (int)stream.ReceiveNext();
			bool flag2 = (bool)stream.ReceiveNext();
			if (info.Sender == PhotonNetwork.MasterClient)
			{
				bool num4 = shopPreview != flag2;
				shopPreview = flag2;
				ownerViewId = num;
				SetMode(num2);
				mirrorYaw = num3;
				active = flag;
				ApplyHealth(nextHealth, nextMax);
				if (num4 && (Object)(object)owner != (Object)null)
				{
					Bind(owner, shopPreview);
				}
			}
		}

		private void SetMode(int value)
		{
			if (value >= 0 && value <= 2)
			{
				mode = value;
			}
		}

		private void SetModeForEveryone(int value)
		{
			if (SemiFunc.IsMultiplayer())
			{
				((Component)this).GetComponent<PhotonView>().RPC("EchoModeCommit", (RpcTarget)0, new object[1] { value });
			}
			else
			{
				SetMode(value);
			}
		}

		[PunRPC]
		private void EchoModeRequest(int expected, PhotonMessageInfo info)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.IsMasterClient && Grabbed && !item.IsEquipped() && expected == mode && Grabbers.GetValue(physics) is List<PhysGrabber> source && source.Any((PhysGrabber g) => (Object)(object)g != (Object)null && (Object)(object)g.playerAvatar != (Object)null && g.playerAvatar.photonView.Owner == info.Sender))
			{
				((Component)this).GetComponent<PhotonView>().RPC("EchoModeCommit", (RpcTarget)0, new object[1] { MirrorRules.NextMode(mode) });
			}
		}

		[PunRPC]
		private void EchoModeCommit(int value, PhotonMessageInfo info)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (info.Sender == PhotonNetwork.MasterClient)
			{
				SetMode(value);
			}
		}

		private void OnGUI()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (HeldLocally)
			{
				GUI.Box(new Rect((float)((Screen.width - 360) / 2), (float)(Screen.height - 135), 360f, 62f), "Echo Mannequin • HP " + health + "/" + maxHealth + "\nE — сменить режим: " + ModeNames[mode]);
			}
		}

		private void OnDisable()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)body != (Object)null && moving)
			{
				body.constraints = originalConstraints;
			}
			moving = false;
			wasDeployed = false;
			motion.Reset();
			active = false;
			lastFloorContact = float.NegativeInfinity;
		}

		private void OnDestroy()
		{
			MannequinDistraction.Unregister(this);
			if (replica != null)
			{
				replica.Dispose();
			}
			if ((Object)(object)neutralPreviewMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)neutralPreviewMaterial);
			}
			foreach (Sprite item in iconHistory)
			{
				if ((Object)(object)item != (Object)null)
				{
					if ((Object)(object)item.texture != (Object)null)
					{
						Object.Destroy((Object)(object)item.texture);
					}
					Object.Destroy((Object)(object)item);
				}
			}
			iconHistory.Clear();
		}
	}
	internal static class MannequinDistraction
	{
		private static readonly List<MannequinController> All = new List<MannequinController>();

		private static readonly FieldInfo Position = AccessTools.Field(typeof(Enemy), "PositionTarget");

		private static readonly FieldInfo HasAgent = AccessTools.Field(typeof(Enemy), "HasNavMeshAgent");

		private static readonly FieldInfo Agent = AccessTools.Field(typeof(Enemy), "NavMeshAgent");

		private static readonly FieldInfo Investigate = AccessTools.Field(typeof(Enemy), "StateInvestigate");

		private static readonly MethodInfo InvestigateSet = AccessTools.Method(typeof(EnemyStateInvestigate), "Set", new Type[2]
		{
			typeof(Vector3),
			typeof(bool)
		}, (Type[])null);

		private static readonly FieldInfo SlowState = AccessTools.Field(typeof(EnemySlowMouth), "currentState");

		private static readonly MethodInfo SlowUpdateState = AccessTools.Method(typeof(EnemySlowMouth), "UpdateState", (Type[])null, (Type[])null);

		private static readonly HashSet<string> LoggedTypes = new HashSet<string>();

		private static float nextTick;

		internal static void Register(MannequinController value)
		{
			if ((Object)(object)value != (Object)null && !All.Contains(value))
			{
				All.Add(value);
			}
		}

		internal static void Unregister(MannequinController value)
		{
			All.Remove(value);
		}

		internal static MannequinController Closest(Enemy enemy, float range)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemy == (Object)null)
			{
				return null;
			}
			MannequinController result = null;
			float num = range * range;
			for (int num2 = All.Count - 1; num2 >= 0; num2--)
			{
				MannequinController mannequinController = All[num2];
				if ((Object)(object)mannequinController == (Object)null)
				{
					All.RemoveAt(num2);
				}
				else if (mannequinController.IsLiveDecoy)
				{
					Vector3 val = mannequinController.DecoyPosition - ((Component)enemy).transform.position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = mannequinController;
					}
				}
			}
			return result;
		}

		internal static void Tick()
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || Time.time < nextTick)
			{
				return;
			}
			nextTick = Time.time + 0.65f;
			Enemy[] array = Object.FindObjectsOfType<Enemy>();
			foreach (Enemy val in array)
			{
				MannequinController mannequinController = Closest(val, 35f);
				if ((Object)(object)mannequinController == (Object)null)
				{
					continue;
				}
				InvestigateNaturally(val, mannequinController);
				MonoBehaviour val2 = ((IEnumerable<MonoBehaviour>)((Component)val).GetComponentsInChildren<MonoBehaviour>(true)).FirstOrDefault((Func<MonoBehaviour, bool>)((MonoBehaviour component) => (Object)(object)component != (Object)null && ((object)component).GetType() != typeof(Enemy) && ((object)component).GetType().Name.StartsWith("Enemy", StringComparison.Ordinal)));
				string text = (((Object)(object)val2 != (Object)null) ? ((object)val2).GetType().Name : ((Object)((Component)val).gameObject).name);
				if (LoggedTypes.Add(text))
				{
					MannequinPlugin.Log.LogInfo((object)("Monster distraction active for " + text + "."));
				}
				EnemySlowMouth componentInChildren = ((Component)val).GetComponentInChildren<EnemySlowMouth>();
				if ((Object)(object)componentInChildren != (Object)null && SlowState != null && SlowUpdateState != null)
				{
					int num = Convert.ToInt32(SlowState.GetValue(componentInChildren));
					if (num == 1 || num == 3 || num == 4 || num == 7 || num == 8 || num >= 12)
					{
						SlowUpdateState.Invoke(componentInChildren, new object[1] { Enum.ToObject(SlowState.FieldType, 16) });
					}
				}
			}
		}

		internal static void InvestigateNaturally(Enemy enemy, MannequinController decoy)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)enemy == (Object)null) && !((Object)(object)decoy == (Object)null))
			{
				EnemyStateInvestigate val = (EnemyStateInvestigate)((Investigate != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val != (Object)null && InvestigateSet != null)
				{
					InvestigateSet.Invoke(val, new object[2] { decoy.DecoyPosition, false });
				}
				else
				{
					Redirect(enemy, decoy);
				}
			}
		}

		internal static void Redirect(Enemy enemy, MannequinController decoy)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)enemy == (Object)null) && !((Object)(object)decoy == (Object)null))
			{
				if (Position != null)
				{
					Position.SetValue(enemy, decoy.DecoyPosition);
				}
				EnemyNavMeshAgent val = (EnemyNavMeshAgent)((Agent != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if (HasAgent != null && (bool)HasAgent.GetValue(enemy) && (Object)(object)val != (Object)null)
				{
					val.SetDestination(decoy.DecoyPosition);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyBombThrower), "Update")]
	internal static class BombThrowerMannequinPatch
	{
		private static readonly FieldInfo EnemyField = AccessTools.Field(typeof(EnemyBombThrower), "enemy");

		private static readonly FieldInfo CurrentState = AccessTools.Field(typeof(EnemyBombThrower), "currentState");

		private static readonly FieldInfo Destination = AccessTools.Field(typeof(EnemyBombThrower), "agentDestination");

		private static readonly FieldInfo HeadGrown = AccessTools.Field(typeof(EnemyBombThrower), "headGrown");

		private static readonly FieldInfo HeadCooldown = AccessTools.Field(typeof(EnemyBombThrower), "headAttackCooldown");

		private static readonly MethodInfo UpdateState = AccessTools.Method(typeof(EnemyBombThrower), "UpdateState", (Type[])null, (Type[])null);

		[HarmonyPostfix]
		private static void Postfix(EnemyBombThrower __instance)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			object? value = EnemyField.GetValue(__instance);
			MannequinController mannequinController = MannequinDistraction.Closest((Enemy)((value is Enemy) ? value : null), 35f);
			if (!((Object)(object)mannequinController == (Object)null))
			{
				int num = Convert.ToInt32(CurrentState.GetValue(__instance));
				if (num != 0 && num < 8)
				{
					Destination.SetValue(__instance, mannequinController.DecoyPosition);
					float num2 = Vector3.Distance(((Component)__instance).transform.position, mannequinController.DecoyPosition);
					int value2 = (((bool)HeadGrown.GetValue(__instance) && (float)HeadCooldown.GetValue(__instance) <= 0f && num2 <= 14f) ? 8 : 3);
					UpdateState.Invoke(__instance, new object[1] { Enum.ToObject(CurrentState.FieldType, value2) });
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyBombThrowerHead), "FixedUpdate")]
	internal static class BombThrowerHeadMannequinPatch
	{
		private static readonly FieldInfo Controller = AccessTools.Field(typeof(EnemyBombThrowerHead), "controller");

		private static readonly FieldInfo PhysicsObject = AccessTools.Field(typeof(EnemyBombThrowerHead), "physGrabObject");

		private static readonly FieldInfo CurrentState = AccessTools.Field(typeof(EnemyBombThrowerHead), "currentState");

		private static readonly FieldInfo EnemyField = AccessTools.Field(typeof(EnemyBombThrower), "enemy");

		private static readonly MethodInfo UpdateState = AccessTools.Method(typeof(EnemyBombThrowerHead), "UpdateState", (Type[])null, (Type[])null);

		[HarmonyPostfix]
		private static void Postfix(EnemyBombThrowerHead __instance)
		{
			//IL_009d: 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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_012e: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)__instance == (Object)null || Convert.ToInt32(CurrentState.GetValue(__instance)) != 2)
			{
				return;
			}
			object? value = Controller.GetValue(__instance);
			EnemyBombThrower val = (EnemyBombThrower)((value is EnemyBombThrower) ? value : null);
			MannequinController mannequinController = MannequinDistraction.Closest((Enemy)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null), 35f);
			object? value2 = PhysicsObject.GetValue(__instance);
			PhysGrabObject val2 = (PhysGrabObject)((value2 is PhysGrabObject) ? value2 : null);
			if (!((Object)(object)mannequinController == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val2.rb == (Object)null) && val2.playerGrabbing.Count <= 0)
			{
				Vector3 val3 = mannequinController.DecoyPosition - val2.rb.worldCenterOfMass;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				if (magnitude <= 1.35f)
				{
					UpdateState.Invoke(__instance, new object[1] { Enum.ToObject(CurrentState.FieldType, 3) });
				}
				else
				{
					Vector3 val4 = ((Vector3)(ref val3)).normalized * Mathf.Clamp(magnitude * 1.5f, 5f, 11f);
					val2.rb.velocity = Vector3.Lerp(val2.rb.velocity, val4, Time.fixedDeltaTime * 7f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHeadGrabber), "Update")]
	internal static class HeadGrabberMannequinPatch
	{
		private static readonly FieldInfo EnemyField = AccessTools.Field(typeof(EnemyHeadGrabber), "enemy");

		private static readonly FieldInfo PlayerTarget = AccessTools.Field(typeof(EnemyHeadGrabber), "playerTarget");

		private static readonly FieldInfo HeadTarget = AccessTools.Field(typeof(EnemyHeadGrabber), "headTarget");

		private static readonly FieldInfo PullAnchor = AccessTools.Field(typeof(EnemyHeadGrabber), "headTargetPositionTransform");

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

		[HarmonyPostfix]
		private static void Postfix(EnemyHeadGrabber __instance)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)__instance == (Object)null || (PlayerTarget != null && PlayerTarget.GetValue(__instance) != null) || (HeadTarget != null && HeadTarget.GetValue(__instance) != null))
			{
				return;
			}
			Enemy enemy = (Enemy)((EnemyField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			MannequinController mannequinController = MannequinDistraction.Closest(enemy, 35f);
			if (!((Object)(object)mannequinController == (Object)null))
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!NextPath.TryGetValue(instanceID, out var value) || Time.time >= value)
				{
					NextPath[instanceID] = Time.time + 0.5f;
					MannequinDistraction.Redirect(enemy, mannequinController);
				}
				if (Vector3.Distance(((Component)__instance).transform.position, mannequinController.DecoyPosition) <= 5f)
				{
					Transform val = (Transform)((PullAnchor != null) ? /*isinst with value type is only supported in some contexts*/: null);
					mannequinController.PullToward(((Object)(object)val != (Object)null) ? val.position : (((Component)__instance).transform.position + Vector3.up));
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHunter), "ShootRPC")]
	internal static class HunterMannequinShotPatch
	{
		private static readonly FieldInfo EnemyField = AccessTools.Field(typeof(EnemyHunter), "enemy");

		[HarmonyPrefix]
		private static void Prefix(EnemyHunter __instance, ref Vector3 __0)
		{
			//IL_0040: 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)
			if (!((Object)(object)__instance == (Object)null))
			{
				MannequinController mannequinController = MannequinDistraction.Closest((Enemy)((EnemyField != null) ? /*isinst with value type is only supported in some contexts*/: null), 35f);
				if ((Object)(object)mannequinController != (Object)null)
				{
					__0 = mannequinController.DecoyPosition;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemySlowMouth), "StateGoToPlayer")]
	internal static class SlowMouthMannequinPatch
	{
		private static readonly FieldInfo EnemyField = AccessTools.Field(typeof(EnemySlowMouth), "enemy");

		private static readonly MethodInfo AnimTarget = AccessTools.Method(typeof(EnemySlowMouth), "AnimStateTargetting", (Type[])null, (Type[])null);

		private static readonly MethodInfo AnimPuke = AccessTools.Method(typeof(EnemySlowMouth), "AnimStatePuke", (Type[])null, (Type[])null);

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

		[HarmonyPrefix]
		private static bool Prefix(EnemySlowMouth __instance, bool __0)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer() || __0)
			{
				return true;
			}
			object? value = EnemyField.GetValue(__instance);
			Enemy enemy = (Enemy)((value is Enemy) ? value : null);
			MannequinController mannequinController = MannequinDistraction.Closest(enemy, 35f);
			if ((Object)(object)mannequinController == (Object)null)
			{
				return true;
			}
			MannequinDistraction.Redirect(enemy, mannequinController);
			if (Vector3.Distance(((Component)__instance).transform.position, mannequinController.DecoyPosition) > 1.15f)
			{
				AnimTarget.Invoke(__instance, null);
				return false;
			}
			AnimPuke.Invoke(__instance, null);
			((Component)__instance).transform.position = Vector3.Lerp(((Component)__instance).transform.position, mannequinController.DecoyPosition, Time.deltaTime * 10f);
			int instanceID = ((Object)__instance).GetInstanceID();
			if (!NextDamage.TryGetValue(instanceID, out var value2) || Time.time >= value2)
			{
				NextDamage[instanceID] = Time.time + 1f;
				mannequinController.Hurt(5);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(HurtCollider), "PhysObjectHurt")]
	internal static class MannequinHurtPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(HurtCollider __instance, PhysGrabObject __0, BreakImpact __1)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			MannequinController mannequinController = (((Object)(object)__0 != (Object)null) ? ((Component)__0).GetComponent<MannequinController>() : null);
			if ((Object)(object)mannequinController == (Object)null)
			{
				return true;
			}
			int num = (__instance.playerKill ? mannequinController.Health : __instance.playerDamage);
			if (num <= 0)
			{
				num = (((int)__1 == 3) ? 50 : (((int)__1 == 2) ? 25 : 10));
			}
			mannequinController.Hurt(num);
			return false;
		}
	}
	internal static class MannequinFactory
	{
		internal const string ItemName = "Item Echo Mannequin";

		private const string PrefabName = "Item Echo Mannequin";

		private static bool _loggedMissingSource;

		private static bool _registrationComplete;

		private static Sprite _inventoryIcon;

		private static Item _registeredItem;

		internal static Item RegisteredItem => _registeredItem;

		private static Sprite CreateIcon()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("EchoMannequin.Icon.png"))
			{
				if (stream == null)
				{
					throw new InvalidOperationException("Embedded mannequin icon is missing.");
				}
				byte[] array = new byte[stream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				if (!ImageConversion.LoadImage(val, array, false))
				{
					throw new InvalidOperationException("Embedded mannequin icon could not be decoded.");
				}
			}
			((Object)val).name = "Echo Mannequin Icon";
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
		}

		private static void ConfigurePhysics(GameObject prefab)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = prefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!val.isTrigger)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
			PhysGrabObjectCollider[] componentsInChildren2 = prefab.GetComponentsInChildren<PhysGrabObjectCollider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Renderer[] componentsInChildren3 = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren3)
			{
				if (!(val2 is ParticleSystemRenderer))
				{
					Object.DestroyImmediate((Object)(object)val2);
				}
			}
			MeshFilter[] componentsInChildren4 = prefab.GetComponentsInChildren<MeshFilter>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			Light[] componentsInChildren5 = prefab.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren5[i]);
			}
			GameObject val3 = new GameObject("Echo Body Collider");
			val3.transform.SetParent(prefab.transform, false);
			val3.layer = LayerMask.NameToLayer("PhysGrabObject");
			val3.tag = "Phys Grab Object";
			CapsuleCollider obj = val3.AddComponent<CapsuleCollider>();
			obj.radius = 0.36f;
			obj.height = 1.65f;
			obj.center = new Vector3(0f, 0.825f, 0f);
			val3.AddComponent<PhysGrabObjectCollider>();
			PhysGrabObject component = prefab.GetComponent<PhysGrabObject>();
			if ((Object)(object)component != (Object)null)
			{
				if (AccessTools.Field(typeof(PhysGrabObject), "colliders").GetValue(component) is List<Transform> list)
				{
					list.Clear();
				}
				AccessTools.Field(typeof(PhysGrabObject), "forceGrabPoint").SetValue(component, null);
			}
			Rigidbody component2 = prefab.GetComponent<Rigidbody>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.mass = 5f;
			}
			PhysGrabObjectImpactDetector component3 = prefab.GetComponent<PhysGrabObjectImpactDetector>();
			if ((Object)(object)component3 != (Object)null)
			{
				AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "destroyDisable").SetValue(component3, false);
				AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "particleDisable").SetValue(component3, false);
				AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "particleBreakSmokeDisable").SetValue(component3, false);
				AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "particleMultiplier").SetValue(component3, 1.35f);
				object value = AccessTools.Field(typeof(PhysGrabObjectImpactDetector), "particles").GetValue(component3);
				if (value != null && AccessTools.Field(value.GetType(), "colliderTransforms").GetValue(value) is List<Transform> list2)
				{
					list2.Clear();
					list2.Add(val3.transform);
				}
			}
		}

		internal static void ApplyRuntimeIcon(ItemAttributes attributes)
		{
			if (!((Object)(object)attributes == (Object)null))
			{
				if ((Object)(object)_inventoryIcon == (Object)null)
				{
					_inventoryIcon = CreateIcon();
				}
				Sprite itemIcon = (attributes.icon = Object.Instantiate<Sprite>(_inventoryIcon));
				AccessTools.Field(typeof(ItemAttributes), "hasIcon").SetValue(attributes, true);
				ItemEquippable component = ((Component)attributes).GetComponent<ItemEquippable>();
				if ((Object)(object)component != (Object)null)
				{
					component.ItemIcon = itemIcon;
				}
			}
		}

		internal static bool TryRegister()
		{
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			if (_registrationComplete)
			{
				return true;
			}
			List<Item> list = new List<Item>();
			list.AddRange(Items.AllItems.Where((Item val5) => (Object)(object)val5 != (Object)null));
			list.AddRange(from val5 in Resources.LoadAll<Item>("ScriptableObjects")
				where (Object)(object)val5 != (Object)null
				select val5);
			list.AddRange(from val5 in Resources.FindObjectsOfTypeAll<Item>()
				where (Object)(object)val5 != (Object)null
				select val5);
			if ((Object)(object)StatsManager.instance != (Object)null && StatsManager.instance.itemDictionary != null)
			{
				list.AddRange(StatsManager.instance.itemDictionary.Values.Where((Item val5) => (Object)(object)val5 != (Object)null));
			}
			if ((Object)(object)ShopManager.instance != (Object)null)
			{
				list.AddRange(ShopManager.instance.potentialItems.Where((Item val5) => (Object)(object)val5 != (Object)null));
				list.AddRange(ShopManager.instance.potentialItemConsumables.Where((Item val5) => (Object)(object)val5 != (Object)null));
				list.AddRange(ShopManager.instance.potentialItemUpgrades.Where((Item val5) => (Object)(object)val5 != (Object)null));
				list.AddRange(ShopManager.instance.potentialItemHealthPacks.Where((Item val5) => (Object)(object)val5 != (Object)null));
			}
			list = list.Distinct().ToList();
			Item val = ((IEnumerable<Item>)Items.AllItems).FirstOrDefault((Func<Item, bool>)((Item item2) => IsNamed(item2, "Item Echo Mannequin")));
			if ((Object)(object)val != (Object)null)
			{
				_registeredItem = val;
				return true;
			}
			Item val2 = Resources.Load<Item>("Items/Item Drone Indestructible") ?? ((IEnumerable<Item>)list).FirstOrDefault((Func<Item, bool>)((Item item2) => IsNamed(item2, "Item Drone Indestructible")));
			if ((Object)(object)val2 == (Object)null || val2.prefab == null || (Object)(object)((PrefabRef<GameObject>)(object)val2.prefab).Prefab == (Object)null)
			{
				if (!_loggedMissingSource)
				{
					_loggedMissingSource = true;
					string text = string.Join(", ", (from val5 in list
						where ContainsDrone(((Object)val5).name) || ContainsDrone(val5.itemName)
						select "[" + ((Object)val5).name + " | " + val5.itemName + "]").Distinct().Take(20).ToArray());
					MannequinPlugin.Log.LogWarning((object)("Waiting for the built-in Item Drone Indestructible prefab. Loaded item candidates: " + list.Count + ". Drone candidates: " + text));
				}
				return false;
			}
			GameObject obj = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)val2.prefab).Prefab);
			((Object)obj).name = "Item Echo Mannequin";
			obj.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)obj);
			RemoveDroneBehaviour(obj);
			ConfigurePhysics(obj);
			Item val3 = ScriptableObject.CreateInstance<Item>();
			CopyItem(val2, val3);
			val3.itemVolume = (itemVolume)0;
			val3.spawnRotationOffset = Quaternion.identity;
			((Object)val3).name = "Item Echo Mannequin";
			val3.itemName = "Item Echo Mannequin";
			val3.description = "A live replica of its owner. Grab, store and drop; it mirrors walking, crouching and tumbling.";
			val3.maxAmountInShop = 1;
			val3.maxPurchase = false;
			val3.maxPurchaseAmount = 1;
			Value val4 = ScriptableObject.CreateInstance<Value>();
			((Object)val4).name = "Value - Echo Mannequin";
			val4.valueMin = 30000f;
			val4.valueMax = 40000f;
			val3.value = val4;
			ItemAttributes component = obj.GetComponent<ItemAttributes>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("The source item has no ItemAttributes component.");
			}
			component.item = val3;
			Sprite itemIcon = (component.icon = CreateIcon());
			ItemEquippable component2 = obj.GetComponent<ItemEquippable>();
			if ((Object)(object)component2 == (Object)null)
			{
				throw new InvalidOperationException("The source item has no ItemEquippable component.");
			}
			component2.ItemIcon = itemIcon;
			MannequinController item = obj.AddComponent<MannequinController>();
			obj.GetComponent<PhotonView>().ObservedComponents.Add((Component)(object)item);
			if (Items.RegisterItem(component) == null)
			{
				throw new InvalidOperationException("REPOLib rejected the mannequin prefab.");
			}
			_registrationComplete = true;
			_registeredItem = val3;
			MannequinPlugin.Log.LogInfo((object)"Registered Item Echo Mannequin with shop price 30000-40000 and maximum one per visit.");
			return true;
		}

		private static bool IsNamed(Item item, string expected)
		{
			if ((Object)(object)item != (Object)null)
			{
				if (!string.Equals(((Object)item).name, expected, StringComparison.Ordinal))
				{
					return string.Equals(item.itemName, expected, StringComparison.Ordinal);
				}
				return true;
			}
			return false;
		}

		private static bool ContainsDrone(string value)
		{
			if (!string.IsNullOrEmpty(value))
			{
				return value.IndexOf("Drone", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static void RemoveDroneBehaviour(GameObject prefab)
		{
			List<Component> removed = new List<Component>();
			MonoBehaviour[] componentsInChildren = prefab.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Type type = ((object)val).GetType();
					if (val is ItemBattery || val is ItemToggle || type.Name.StartsWith("ItemDrone", StringComparison.Ordinal))
					{
						removed.Add((Component)(object)val);
						Object.DestroyImmediate((Object)(object)val);
					}
				}
			}
			PhotonView[] componentsInChildren2 = prefab.GetComponentsInChildren<PhotonView>(true);
			foreach (PhotonView val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && val2.ObservedComponents != null)
				{
					val2.ObservedComponents.RemoveAll((Component component) => (Object)(object)component == (Object)null || removed.Contains(component));
				}
			}
		}

		private static void CopyItem(Item source, Item destination)
		{
			//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_001c: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			destination.disabled = false;
			destination.itemNameLocalized = null;
			destination.itemType = source.itemType;
			destination.emojiIcon = source.emojiIcon;
			destination.itemVolume = source.itemVolume;
			destination.itemSecretShopType = source.itemSecretShopType;
			destination.colorPreset = source.colorPreset;
			destination.maxAmount = Math.Max(1, source.maxAmount);
			destination.maxAmountInShop = 1;
			destination.minPlayerCount = source.minPlayerCount;
			destination.maxPurchase = false;
			destination.maxPurchaseAmount = 1;
			destination.spawnRotationOffset = source.spawnRotationOffset;
			destination.physicalItem = true;
		}
	}
	[BepInPlugin("uz.cherdak.repo.echomannequin", "Echo Mannequin", "1.2.12")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class MannequinPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private float nextAttempt;

		private bool ready;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("uz.cherdak.repo.echomannequin").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Echo Mannequin 1.2.12 loaded");
		}

		private void Update()
		{
			MannequinDistraction.Tick();
			if (ready || Time.unscaledTime < nextAttempt)
			{
				return;
			}
			nextAttempt = Time.unscaledTime + 3f;
			try
			{
				ready = MannequinFactory.TryRegister();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "LoadItemsFromFolder")]
	internal static class RegisterPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			try
			{
				MannequinFactory.TryRegister();
			}
			catch (Exception ex)
			{
				MannequinPlugin.Log.LogError((object)ex);
			}
		}
	}
	internal static class MirrorRules
	{
		internal static int NextMode(int mode)
		{
			return (mode + 1) % 3;
		}

		internal static float Facing(float planeYaw, float ownerYaw)
		{
			return 2f * planeYaw + 180f - ownerYaw;
		}

		internal static void Movement(float x, float z, float planeYaw, int mode, out float resultX, out float resultZ)
		{
			if (mode != 0)
			{
				resultX = (resultZ = 0f);
				return;
			}
			double num = (double)planeYaw * Math.PI / 180.0;
			float num2 = (float)Math.Sin(num);
			float num3 = (float)Math.Cos(num);
			float num4 = x *