Decompiled source of EchoMannequin v1.1.1

BepInEx/plugins/EchoMannequin/EchoMannequin.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 sealed class GroundedMotion
	{
		private bool sampled;

		private bool wasGrounded;

		internal bool Active { get; private set; }

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

		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 Dictionary<Transform, Transform> transforms = new Dictionary<Transform, Transform>();

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

		private readonly MaterialPropertyBlock properties = new MaterialPropertyBlock();

		private float nextScan;

		private float floorOffset;

		private bool hasPose;

		internal float Height { get; private set; }

		internal LiveReplica(Transform root, PlayerAvatar owner)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			this.root = root;
			this.owner = owner;
			Height = 1.25f;
		}

		private Transform Map(Transform source)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_0188: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_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 ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (transforms.TryGetValue(source, out var value))
			{
				return value;
			}
			Transform val = (((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)val != (Object)null)
			{
				value.localPosition = val.localPosition + val.localRotation * Vector3.Scale(val.localScale, source.localPosition);
				value.localRotation = val.localRotation * source.localRotation;
				value.localScale = Vector3.Scale(val.localScale, source.localScale);
			}
			else
			{
				Quaternion val2 = Quaternion.Inverse(Quaternion.Euler(0f, ((Component)owner).transform.eulerAngles.y, 0f));
				value.localPosition = val2 * (source.position - ((Component)owner).transform.position) + Vector3.up * floorOffset;
				value.localRotation = val2 * source.rotation;
				value.localScale = source.lossyScale;
			}
			transforms.Add(source, value);
			return value;
		}

		private void Scan()
		{
			//IL_02b4: 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)
				{
					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)((Component)val3).GetComponentInParent<PhysGrabObject>() != (Object)null) && !((Object)(object)((Component)val3).GetComponentInParent<ItemAttributes>() != (Object)null))
					{
						PlayerAvatar componentInParent = ((Component)val3).GetComponentInParent<PlayerAvatar>();
						if (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)componentInParent != (Object)(object)owner))
						{
							hashSet.Add(val3);
						}
					}
				}
			}
			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)
		{
			if (!renderer.enabled)
			{
				return false;
			}
			PlayerAvatarVisuals playerAvatarVisuals = owner.playerAvatarVisuals;
			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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: 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_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: 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))
				{
					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 value = renderer.Value;
				value.enabled = Visible(key);
				value.sharedMaterials = key.sharedMaterials;
				value.shadowCastingMode = (ShadowCastingMode)1;
				value.receiveShadows = key.receiveShadows;
				key.GetPropertyBlock(properties);
				value.SetPropertyBlock(properties);
				for (int i = 0; i < key.sharedMaterials.Length; i++)
				{
					key.GetPropertyBlock(properties, i);
					value.SetPropertyBlock(properties, i);
				}
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((key is SkinnedMeshRenderer) ? key : null);
				SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((value is SkinnedMeshRenderer) ? value : null);
				if (key is MeshRenderer)
				{
					((Component)value).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 j = 0; j < val2.sharedMesh.blendShapeCount; j++)
						{
							val3.SetBlendShapeWeight(j, val2.GetBlendShapeWeight(j));
						}
					}
				}
				if (value.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)
					{
						Transform value2 = transform2.Value;
						value2.localPosition += Vector3.up * num5;
					}
				}
				Height = Mathf.Clamp(num2 + floorOffset, 0.5f, 2.5f);
			}
			hasPose = transforms.Count > 0;
			root.localScale = new Vector3(-1f, 1f, 1f) * (portable ? 0.3f : 1f);
		}
	}
	[DefaultExecutionOrder(10000)]
	public sealed class MannequinController : MonoBehaviour, IPunObservable
	{
		private static readonly FieldInfo OwnerId = AccessTools.Field(typeof(ItemEquippable), "ownerPlayerId");

		private static readonly FieldInfo LastGrabber = AccessTools.Field(typeof(PhysGrabObject), "lastPlayerGrabbing");

		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 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 float nextOwnerSearch;

		private int mode;

		private float mirrorYaw;

		private bool wasDeployed;

		private float nextModeChange;

		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 void Awake()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			item = ((Component)this).GetComponent<ItemEquippable>();
			physics = ((Component)this).GetComponent<PhysGrabObject>();
			body = ((Component)this).GetComponent<Rigidbody>();
			shape = ((Component)((Component)this).transform.Find("Echo Body Collider")).GetComponent<CapsuleCollider>();
			originalConstraints = body.constraints;
		}

		private void Start()
		{
			MannequinFactory.ApplyRuntimeIcon(((Component)this).GetComponent<ItemAttributes>());
		}

		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)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)avatar == (Object)null) && !((Object)(object)owner == (Object)(object)avatar))
			{
				owner = avatar;
				ownerViewId = (((Object)(object)avatar.photonView != (Object)null) ? avatar.photonView.ViewID : 0);
				previousOwnerPosition = ((Component)owner).transform.position;
				if ((Object)(object)model != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)model).gameObject);
				}
				model = new GameObject("Echo Live Replica").transform;
				model.SetParent(((Component)this).transform, false);
				replica = new LiveReplica(model, owner);
				if (Authority)
				{
					motion.Reset();
					active = false;
					wasDeployed = false;
				}
			}
		}

		private void Update()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			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 (item.IsEquipped())
				{
					Bind(EquippedOwner());
				}
				else if (Grabbed)
				{
					object? value = LastGrabber.GetValue(physics);
					Bind((PlayerAvatar)((value is PlayerAvatar) ? value : null));
				}
				if ((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
						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 val2 = ((Component)p).transform.position - ((Component)this).transform.position;
						return ((Vector3)(ref val2)).sqrMagnitude;
					}).FirstOrDefault());
				}
			}
			else if (((Object)(object)owner == (Object)null || owner.photonView.ViewID != ownerViewId) && ownerViewId != 0)
			{
				PhotonView val = PhotonView.Find(ownerViewId);
				if ((Object)(object)val != (Object)null)
				{
					Bind(((Component)val).GetComponent<PlayerAvatar>());
				}
			}
			if ((Object)(object)owner == (Object)null)
			{
				if ((Object)(object)model != (Object)null)
				{
					((Component)model).gameObject.SetActive(false);
				}
			}
			else if (item.IsEquipped() || Grabbed)
			{
				lastFloorContact = float.NegativeInfinity;
				if (Authority)
				{
					motion.Reset();
					active = false;
				}
			}
		}

		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_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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!Authority || (Object)(object)item == (Object)null || item.IsEquipped() || 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0042: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00fb: 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_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			if (!Authority || (Object)(object)body == (Object)null || (Object)(object)owner == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)owner).transform.position;
			Vector3 val = position - previousOwnerPosition;
			previousOwnerPosition = position;
			bool flag = item.IsEquipped() || 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);
				if (mode != 0)
				{
					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 (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()
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)owner == (Object)null) && replica != null && !((Object)(object)model == (Object)null))
			{
				bool flag = item.IsEquipped();
				((Component)model).gameObject.SetActive(!flag);
				if (!flag)
				{
					bool flag2 = Grabbed || !active;
					replica.Tick(flag2, mode == 2);
					float num = Mathf.Max(0.5f, replica.Height * (flag2 ? 0.3f : 1f));
					shape.height = num;
					shape.radius = (flag2 ? 0.15f : 0.25f);
					shape.center = Vector3.up * num * 0.5f;
					body.centerOfMass = shape.center;
				}
			}
		}

		public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
		{
			//IL_007d: 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);
				return;
			}
			int num = (int)stream.ReceiveNext();
			int num2 = (int)stream.ReceiveNext();
			float num3 = (float)stream.ReceiveNext();
			bool flag = (bool)stream.ReceiveNext();
			if (info.Sender == PhotonNetwork.MasterClient)
			{
				ownerViewId = num;
				SetMode(num2);
				mirrorYaw = num3;
				active = flag;
			}
		}

		private void SetMode(int value)
		{
			if (value >= 0 && value <= 2)
			{
				mode = 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 • Зеркало\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;
		}
	}
	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 Sprite CreateIcon()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					bool flag = j >= 18 && j < 46 && i >= 34 && i < 56;
					bool flag2 = j >= 22 && j < 42 && i >= 16 && i < 34;
					bool flag3 = i >= 8 && i < 16 && ((j >= 20 && j < 29) || (j >= 35 && j < 44));
					bool flag4 = i >= 42 && i < 49 && ((j >= 23 && j < 28) || (j >= 36 && j < 41));
					array[i * 64 + j] = (Color)(flag4 ? Color.black : ((flag || flag2 || flag3) ? new Color(0.35f, 0.95f, 0.85f) : Color.clear));
				}
			}
			val.SetPixels(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
		}

		private static void ConfigurePhysics(GameObject prefab)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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)
				{
					val.enabled = false;
				}
			}
			Renderer[] componentsInChildren2 = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
			Light[] componentsInChildren3 = prefab.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
			GameObject val2 = new GameObject("Echo Body Collider");
			val2.transform.SetParent(prefab.transform, false);
			val2.layer = LayerMask.NameToLayer("PhysGrabObject");
			val2.tag = "Phys Grab Object";
			CapsuleCollider obj = val2.AddComponent<CapsuleCollider>();
			obj.radius = 0.25f;
			obj.height = 1.25f;
			obj.center = new Vector3(0f, 0.625f, 0f);
			val2.AddComponent<PhysGrabObjectCollider>();
			Rigidbody component = prefab.GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.mass = 5f;
			}
		}

		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()
		{
			if (_registrationComplete)
			{
				return true;
			}
			List<Item> list = new List<Item>();
			list.AddRange(Items.AllItems.Where((Item val4) => (Object)(object)val4 != (Object)null));
			list.AddRange(from val4 in Resources.LoadAll<Item>("ScriptableObjects")
				where (Object)(object)val4 != (Object)null
				select val4);
			list.AddRange(from val4 in Resources.FindObjectsOfTypeAll<Item>()
				where (Object)(object)val4 != (Object)null
				select val4);
			if ((Object)(object)StatsManager.instance != (Object)null && StatsManager.instance.itemDictionary != null)
			{
				list.AddRange(StatsManager.instance.itemDictionary.Values.Where((Item val4) => (Object)(object)val4 != (Object)null));
			}
			if ((Object)(object)ShopManager.instance != (Object)null)
			{
				list.AddRange(ShopManager.instance.potentialItems.Where((Item val4) => (Object)(object)val4 != (Object)null));
				list.AddRange(ShopManager.instance.potentialItemConsumables.Where((Item val4) => (Object)(object)val4 != (Object)null));
				list.AddRange(ShopManager.instance.potentialItemUpgrades.Where((Item val4) => (Object)(object)val4 != (Object)null));
				list.AddRange(ShopManager.instance.potentialItemHealthPacks.Where((Item val4) => (Object)(object)val4 != (Object)null));
			}
			list = list.Distinct().ToList();
			if (Items.AllItems.Any((Item item2) => IsNamed(item2, "Item Echo Mannequin")))
			{
				return true;
			}
			Item val = Resources.Load<Item>("Items/Item Drone Indestructible") ?? ((IEnumerable<Item>)list).FirstOrDefault((Func<Item, bool>)((Item item2) => IsNamed(item2, "Item Drone Indestructible")));
			if ((Object)(object)val == (Object)null || val.prefab == null || (Object)(object)((PrefabRef<GameObject>)(object)val.prefab).Prefab == (Object)null)
			{
				if (!_loggedMissingSource)
				{
					_loggedMissingSource = true;
					string text = string.Join(", ", (from val4 in list
						where ContainsDrone(((Object)val4).name) || ContainsDrone(val4.itemName)
						select "[" + ((Object)val4).name + " | " + val4.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)val.prefab).Prefab);
			((Object)obj).name = "Item Echo Mannequin";
			obj.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)obj);
			RemoveDroneBehaviour(obj);
			ConfigurePhysics(obj);
			Item val2 = ScriptableObject.CreateInstance<Item>();
			CopyItem(val, val2);
			((Object)val2).name = "Item Echo Mannequin";
			val2.itemName = "Item Echo Mannequin";
			val2.description = "A live replica of its owner. Grab, store and drop; it mirrors walking, crouching and tumbling.";
			val2.maxAmountInShop = 1;
			Value val3 = ScriptableObject.CreateInstance<Value>();
			((Object)val3).name = "Value - Echo Mannequin";
			val3.valueMin = 30000f;
			val3.valueMax = 40000f;
			val2.value = val3;
			ItemAttributes component = obj.GetComponent<ItemAttributes>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("The source item has no ItemAttributes component.");
			}
			component.item = val2;
			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;
			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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			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 = source.maxPurchase;
			destination.maxPurchaseAmount = source.maxPurchaseAmount;
			destination.spawnRotationOffset = source.spawnRotationOffset;
			destination.physicalItem = true;
		}
	}
	[BepInPlugin("uz.cherdak.repo.echomannequin", "Echo Mannequin", "1.1.1")]
	[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.1.1 loaded");
		}

		private void Update()
		{
			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 * num2 + z * num3;
			resultX = x - 2f * num4 * num2;
			resultZ = z - 2f * num4 * num3;
		}
	}
}