Decompiled source of ShopItemClone v1.0.0

ShopItemClone.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 REPOJP.ShopItemClone
{
	[BepInPlugin("REPOJP.ShopItemClone", "Shop Item Clone", "1.0.0")]
	public sealed class ShopItemClonePlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "REPOJP.ShopItemClone";

		public const string PluginName = "Shop Item Clone";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource LogSource;

		internal static ShopItemClonePlugin Instance;

		internal static ConfigEntry<bool> CloneUpgrades;

		internal static ConfigEntry<bool> CloneMeleeWeapons;

		internal static ConfigEntry<bool> CloneGuns;

		internal static ConfigEntry<bool> CloneCarts;

		internal static ConfigEntry<bool> CloneDrones;

		internal static ConfigEntry<bool> CloneOrbs;

		internal static ConfigEntry<bool> CloneHealthPacks;

		internal static ConfigEntry<bool> CloneExplosives;

		internal static ConfigEntry<bool> CloneEnergyCrystals;

		internal static ConfigEntry<bool> PreventCloneInExtractionPoint;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			try
			{
				Instance = this;
				LogSource = ((BaseUnityPlugin)this).Logger;
				BindConfig();
				ShopItemCloneRuntime.EnsureCreated();
				harmony = new Harmony("REPOJP.ShopItemClone");
				harmony.PatchAll(typeof(ShopItemClonePlugin).Assembly);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Shop Item Clone 1.0.0 loaded");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("Failed to initialize {0}\n{1}", "Shop Item Clone", arg));
			}
		}

		private void BindConfig()
		{
			CloneUpgrades = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Upgrades", true, "Clone item upgrades and player upgrades when the held item touches the ground in the shop. ショップ中に手持ち状態のアップグレード系アイテムが地面接触したとき複製");
			CloneMeleeWeapons = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Melee Weapons", true, "Clone melee weapons when the held item touches the ground in the shop. ショップ中に手持ち状態の近接武器が地面接触したとき複製");
			CloneGuns = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Guns", true, "Clone guns when the held item touches the ground in the shop. ショップ中に手持ち状態の銃が地面接触したとき複製");
			CloneCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Carts", true, "Clone carts and pocket carts when the held item touches the ground in the shop. cart と pocket_cart はそれぞれ1ショップ中5回まで複製。ショップ中に手持ち状態のカート系が地面接触したとき複製");
			CloneDrones = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Drones", true, "Clone drones when the held item touches the ground in the shop. ショップ中に手持ち状態のドローンが地面接触したとき複製");
			CloneOrbs = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Orbs", true, "Clone orbs when the held item touches the ground in the shop. ショップ中に手持ち状態のオーブが地面接触したとき複製");
			CloneHealthPacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Health Packs", true, "Clone health packs when the held item touches the ground in the shop. ショップ中に手持ち状態のヘルスパックが地面接触したとき複製");
			CloneExplosives = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Explosives", true, "Clone grenades and mines when the held item touches the ground in the shop. ショップ中に手持ち状態の爆破物系が地面接触したとき複製");
			CloneEnergyCrystals = ((BaseUnityPlugin)this).Config.Bind<bool>("Category Toggle", "Clone Energy Crystals", true, "Clone energy crystals when the held item touches the ground in the shop. ショップ中に手持ち状態のエナジークリスタルが地面接触したとき複製");
			PreventCloneInExtractionPoint = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Prevent Clone In Extraction Point", true, "Prevent cloning while the held item is inside the extraction point. 納品所内にある手持ちアイテムの複製を禁止");
		}
	}
	internal sealed class ShopItemCloneRuntime : MonoBehaviour
	{
		private sealed class ContactState
		{
			internal PhysGrabObject Source;

			internal bool Latched;

			internal float LastValidGroundContactTime;

			internal float LastCloneTime;
		}

		[CompilerGenerated]
		private sealed class <FinalizeCloneAfterStart>d__37 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PhysGrabObject source;

			public ItemAttributes sourceItem;

			public GameObject cloneObject;

			public ShopItemCloneRuntime <>4__this;

			private ItemAttributes <cloneItem>5__1;

			private PhotonView <clonePhotonView>5__2;

			private Rigidbody <sourceRb>5__3;

			private Rigidbody <cloneRb>5__4;

			private ItemToggle <sourceToggle>5__5;

			private ItemToggle <cloneToggle>5__6;

			private ItemBattery <sourceBattery>5__7;

			private ItemBattery <cloneBattery>5__8;

			private int <sourceValue>5__9;

			private int <targetBars>5__10;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <FinalizeCloneAfterStart>d__37(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<cloneItem>5__1 = null;
				<clonePhotonView>5__2 = null;
				<sourceRb>5__3 = null;
				<cloneRb>5__4 = null;
				<sourceToggle>5__5 = null;
				<cloneToggle>5__6 = null;
				<sourceBattery>5__7 = null;
				<cloneBattery>5__8 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					if ((Object)(object)source == (Object)null || (Object)(object)sourceItem == (Object)null || (Object)(object)cloneObject == (Object)null)
					{
						return false;
					}
					<cloneItem>5__1 = cloneObject.GetComponent<ItemAttributes>();
					<clonePhotonView>5__2 = cloneObject.GetComponent<PhotonView>();
					<sourceRb>5__3 = source.rb;
					<cloneRb>5__4 = cloneObject.GetComponent<Rigidbody>();
					if ((Object)(object)<cloneItem>5__1 == (Object)null)
					{
						return false;
					}
					TryApplyInitialMotion(<sourceRb>5__3, <cloneRb>5__4);
					if (ItemValueField != null)
					{
						<sourceValue>5__9 = (int)ItemValueField.GetValue(sourceItem);
						if (GameManager.Multiplayer() && (Object)(object)<clonePhotonView>5__2 != (Object)null)
						{
							<clonePhotonView>5__2.RPC("GetValueRPC", (RpcTarget)0, new object[1] { <sourceValue>5__9 });
						}
						else
						{
							<cloneItem>5__1.GetValueRPC(<sourceValue>5__9);
						}
					}
					<sourceToggle>5__5 = ((Component)source).GetComponent<ItemToggle>();
					<cloneToggle>5__6 = cloneObject.GetComponent<ItemToggle>();
					if ((Object)(object)<sourceToggle>5__5 != (Object)null && (Object)(object)<cloneToggle>5__6 != (Object)null && <cloneToggle>5__6.toggleState != <sourceToggle>5__5.toggleState)
					{
						<cloneToggle>5__6.ToggleItem(<sourceToggle>5__5.toggleState, -1);
					}
					<sourceBattery>5__7 = ((Component)source).GetComponent<ItemBattery>();
					<cloneBattery>5__8 = cloneObject.GetComponent<ItemBattery>();
					if ((Object)(object)<sourceBattery>5__7 != (Object)null && (Object)(object)<cloneBattery>5__8 != (Object)null)
					{
						<targetBars>5__10 = Mathf.Clamp(Mathf.RoundToInt(<sourceBattery>5__7.batteryLife / (100f / (float)<cloneBattery>5__8.batteryBars)), 0, <cloneBattery>5__8.batteryBars);
						if (GameManager.Multiplayer() && (Object)(object)<clonePhotonView>5__2 != (Object)null)
						{
							<clonePhotonView>5__2.RPC("BatteryFullPercentChangeRPC", (RpcTarget)0, new object[2] { <targetBars>5__10, false });
						}
						else if (BatteryFullPercentChangeRpcMethod != null)
						{
							BatteryFullPercentChangeRpcMethod.Invoke(<cloneBattery>5__8, new object[2] { <targetBars>5__10, false });
						}
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <IgnoreCloneCollisionTemporary>d__38 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public GameObject sourceObject;

			public GameObject cloneObject;

			public float duration;

			public ShopItemCloneRuntime <>4__this;

			private Collider[] <sourceColliders>5__1;

			private Collider[] <cloneColliders>5__2;

			private int <i>5__3;

			private Collider <sourceCollider>5__4;

			private int <j>5__5;

			private Collider <cloneCollider>5__6;

			private int <i>5__7;

			private Collider <sourceCollider>5__8;

			private int <j>5__9;

			private Collider <cloneCollider>5__10;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <IgnoreCloneCollisionTemporary>d__38(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<sourceColliders>5__1 = null;
				<cloneColliders>5__2 = null;
				<sourceCollider>5__4 = null;
				<cloneCollider>5__6 = null;
				<sourceCollider>5__8 = null;
				<cloneCollider>5__10 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_014b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0155: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if ((Object)(object)sourceObject == (Object)null || (Object)(object)cloneObject == (Object)null)
					{
						return false;
					}
					<sourceColliders>5__1 = sourceObject.GetComponentsInChildren<Collider>(true);
					<cloneColliders>5__2 = cloneObject.GetComponentsInChildren<Collider>(true);
					<i>5__3 = 0;
					while (<i>5__3 < <sourceColliders>5__1.Length)
					{
						<sourceCollider>5__4 = <sourceColliders>5__1[<i>5__3];
						if (!((Object)(object)<sourceCollider>5__4 == (Object)null))
						{
							<j>5__5 = 0;
							while (<j>5__5 < <cloneColliders>5__2.Length)
							{
								<cloneCollider>5__6 = <cloneColliders>5__2[<j>5__5];
								if (!((Object)(object)<cloneCollider>5__6 == (Object)null))
								{
									Physics.IgnoreCollision(<sourceCollider>5__4, <cloneCollider>5__6, true);
									<cloneCollider>5__6 = null;
								}
								<j>5__5++;
							}
							<sourceCollider>5__4 = null;
						}
						<i>5__3++;
					}
					<>2__current = (object)new WaitForSeconds(duration);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)sourceObject == (Object)null || (Object)(object)cloneObject == (Object)null)
					{
						return false;
					}
					<i>5__7 = 0;
					while (<i>5__7 < <sourceColliders>5__1.Length)
					{
						<sourceCollider>5__8 = <sourceColliders>5__1[<i>5__7];
						if (!((Object)(object)<sourceCollider>5__8 == (Object)null))
						{
							<j>5__9 = 0;
							while (<j>5__9 < <cloneColliders>5__2.Length)
							{
								<cloneCollider>5__10 = <cloneColliders>5__2[<j>5__9];
								if (!((Object)(object)<cloneCollider>5__10 == (Object)null))
								{
									Physics.IgnoreCollision(<sourceCollider>5__8, <cloneCollider>5__10, false);
									<cloneCollider>5__10 = null;
								}
								<j>5__9++;
							}
							<sourceCollider>5__8 = null;
						}
						<i>5__7++;
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private const float DefaultCloneHeightOffset = 0.01f;

		private const float CartCloneHeightOffset = 1f;

		private const float CloneCollisionIgnoreSeconds = 0.2f;

		private const float CloneImpactDisableSeconds = 0.2f;

		private const float RearmNoContactSeconds = 0.08f;

		private const float RearmAfterSpawnSeconds = 0.15f;

		private const float GroundNormalMinY = 0.35f;

		private const int CartCloneMaxPerShop = 5;

		private const int PocketCartCloneMaxPerShop = 5;

		private static ShopItemCloneRuntime instance;

		private static readonly FieldInfo ItemValueField = AccessTools.Field(typeof(ItemAttributes), "value");

		private static readonly FieldInfo InExtractionPointField = AccessTools.Field(typeof(RoomVolumeCheck), "inExtractionPoint");

		private static readonly MethodInfo BatteryFullPercentChangeRpcMethod = AccessTools.Method(typeof(ItemBattery), "BatteryFullPercentChangeRPC", (Type[])null, (Type[])null);

		private readonly Dictionary<int, ContactState> contactStates = new Dictionary<int, ContactState>();

		private int currentShopCartCloneCount;

		private int currentShopPocketCartCloneCount;

		private bool wasShopMainPhase;

		internal static ShopItemCloneRuntime Instance => instance;

		internal static void EnsureCreated()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)instance != (Object)null))
			{
				GameObject val = new GameObject("ShopItemCloneRuntime");
				val.transform.parent = null;
				((Object)val).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)val);
				instance = val.AddComponent<ShopItemCloneRuntime>();
			}
		}

		private void Update()
		{
			try
			{
				bool flag = IsShopMainPhase();
				if (flag && !wasShopMainPhase)
				{
					ResetShopCounters();
				}
				else if (!flag && wasShopMainPhase)
				{
					ResetShopCounters();
					contactStates.Clear();
				}
				wasShopMainPhase = flag;
				if (contactStates.Count == 0)
				{
					return;
				}
				float unscaledTime = Time.unscaledTime;
				List<int> list = null;
				foreach (KeyValuePair<int, ContactState> contactState in contactStates)
				{
					ContactState value = contactState.Value;
					PhysGrabObject source = value.Source;
					if ((Object)(object)source == (Object)null)
					{
						if (list == null)
						{
							list = new List<int>();
						}
						list.Add(contactState.Key);
						continue;
					}
					bool flag2 = IsActuallyHeld(source);
					bool flag3 = IsShopMainPhase();
					if (!flag2 || !flag3)
					{
						if (list == null)
						{
							list = new List<int>();
						}
						list.Add(contactState.Key);
					}
					else if (!(unscaledTime - value.LastCloneTime < 0.15f) && unscaledTime - value.LastValidGroundContactTime > 0.08f)
					{
						value.Latched = false;
					}
				}
				if (list == null)
				{
					return;
				}
				foreach (int item in list)
				{
					contactStates.Remove(item);
				}
			}
			catch (Exception arg)
			{
				ShopItemClonePlugin.LogSource.LogError((object)$"Runtime update failed\n{arg}");
			}
		}

		internal void OnImpactStay(PhysGrabObjectImpactDetector detector, Collision collision)
		{
			try
			{
				if ((Object)(object)detector == (Object)null || collision == null || !IsHostAuthority() || !IsShopMainPhase())
				{
					return;
				}
				PhysGrabObject component = ((Component)detector).GetComponent<PhysGrabObject>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				ItemAttributes component2 = ((Component)component).GetComponent<ItemAttributes>();
				if (!((Object)(object)component2 == (Object)null) && !((Object)(object)((Component)component).GetComponent<ValuableObject>() != (Object)null) && IsCategoryEnabled(component2) && IsActuallyHeld(component) && (ShopItemClonePlugin.PreventCloneInExtractionPoint == null || !ShopItemClonePlugin.PreventCloneInExtractionPoint.Value || !IsInsideExtractionPoint(component)) && IsGroundLikeEnvironmentCollision(collision))
				{
					int instanceID = ((Object)component).GetInstanceID();
					if (!contactStates.TryGetValue(instanceID, out ContactState value))
					{
						value = new ContactState();
						value.Source = component;
						contactStates[instanceID] = value;
					}
					value.LastValidGroundContactTime = Time.unscaledTime;
					if (!value.Latched)
					{
						value.Latched = true;
						value.LastCloneTime = Time.unscaledTime;
						CloneHeldShopItem(component, component2);
					}
				}
			}
			catch (Exception arg)
			{
				ShopItemClonePlugin.LogSource.LogError((object)$"Impact handling failed\n{arg}");
			}
		}

		private static bool IsHostAuthority()
		{
			if (!GameManager.Multiplayer())
			{
				return true;
			}
			return PhotonNetwork.IsMasterClient;
		}

		private static bool IsShopMainPhase()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if (!SemiFunc.RunIsShop())
			{
				return false;
			}
			if ((Object)(object)GameDirector.instance == (Object)null)
			{
				return false;
			}
			return (int)GameDirector.instance.currentState == 2;
		}

		private static bool IsCategoryEnabled(ItemAttributes itemAttributes)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected I4, but got Unknown
			if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null)
			{
				return false;
			}
			itemType itemType = itemAttributes.item.itemType;
			itemType val = itemType;
			switch ((int)val)
			{
			case 3:
			case 4:
				return ShopItemClonePlugin.CloneUpgrades != null && ShopItemClonePlugin.CloneUpgrades.Value;
			case 7:
				return ShopItemClonePlugin.CloneMeleeWeapons != null && ShopItemClonePlugin.CloneMeleeWeapons.Value;
			case 9:
				return ShopItemClonePlugin.CloneGuns != null && ShopItemClonePlugin.CloneGuns.Value;
			case 2:
			case 12:
				return ShopItemClonePlugin.CloneCarts != null && ShopItemClonePlugin.CloneCarts.Value;
			case 0:
				return ShopItemClonePlugin.CloneDrones != null && ShopItemClonePlugin.CloneDrones.Value;
			case 1:
				return ShopItemClonePlugin.CloneOrbs != null && ShopItemClonePlugin.CloneOrbs.Value;
			case 8:
				return ShopItemClonePlugin.CloneHealthPacks != null && ShopItemClonePlugin.CloneHealthPacks.Value;
			case 6:
			case 11:
				return ShopItemClonePlugin.CloneExplosives != null && ShopItemClonePlugin.CloneExplosives.Value;
			case 5:
				return ShopItemClonePlugin.CloneEnergyCrystals != null && ShopItemClonePlugin.CloneEnergyCrystals.Value;
			default:
				return false;
			}
		}

		private static bool IsActuallyHeld(PhysGrabObject source)
		{
			if ((Object)(object)source == (Object)null)
			{
				return false;
			}
			if (!source.grabbed)
			{
				return false;
			}
			List<PhysGrabber> playerGrabbing = source.playerGrabbing;
			if (playerGrabbing == null || playerGrabbing.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < playerGrabbing.Count; i++)
			{
				PhysGrabber val = playerGrabbing[i];
				if (!((Object)(object)val == (Object)null) && val.grabbed && !((Object)(object)val.grabbedPhysGrabObject != (Object)(object)source))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsInsideExtractionPoint(PhysGrabObject source)
		{
			if ((Object)(object)source == (Object)null)
			{
				return false;
			}
			RoomVolumeCheck val = ((Component)source).GetComponent<RoomVolumeCheck>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)source).GetComponentInChildren<RoomVolumeCheck>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)source).GetComponentInParent<RoomVolumeCheck>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			val.CheckSet();
			object value = InExtractionPointField.GetValue(val);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static void TryApplyInitialMotion(Rigidbody sourceRb, Rigidbody cloneRb)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)sourceRb == (Object)null) && !((Object)(object)cloneRb == (Object)null) && !cloneRb.isKinematic)
			{
				cloneRb.velocity = sourceRb.velocity;
				cloneRb.angularVelocity = sourceRb.angularVelocity;
			}
		}

		private static bool IsGroundLikeEnvironmentCollision(Collision collision)
		{
			//IL_00f5: 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)
			if (collision == null)
			{
				return false;
			}
			Transform transform = collision.transform;
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			MaterialSurface val = ((Component)transform).GetComponent<MaterialSurface>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)transform).GetComponentInParent<MaterialSurface>();
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)transform).GetComponentInParent<PhysGrabObject>() != (Object)null)
			{
				return false;
			}
			if (((Component)transform).CompareTag("Player") || (Object)(object)((Component)transform).GetComponentInParent<PlayerAvatar>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)transform).GetComponentInParent<EnemyRigidbody>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)transform).GetComponentInParent<PhysGrabCart>() != (Object)null)
			{
				return false;
			}
			float num = -1f;
			ContactPoint[] contacts = collision.contacts;
			for (int i = 0; i < contacts.Length; i++)
			{
				if (((ContactPoint)(ref contacts[i])).normal.y > num)
				{
					num = ((ContactPoint)(ref contacts[i])).normal.y;
				}
			}
			return num >= 0.35f;
		}

		private static bool IsCartItem(ItemAttributes itemAttributes)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null)
			{
				return false;
			}
			return (int)itemAttributes.item.itemType == 2 || (int)itemAttributes.item.itemType == 12;
		}

		private static bool IsStandardCartItem(ItemAttributes itemAttributes)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null)
			{
				return false;
			}
			return (int)itemAttributes.item.itemType == 2;
		}

		private static bool IsPocketCartItem(ItemAttributes itemAttributes)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			if ((Object)(object)itemAttributes == (Object)null || (Object)(object)itemAttributes.item == (Object)null)
			{
				return false;
			}
			return (int)itemAttributes.item.itemType == 12;
		}

		private Vector3 GetCloneSpawnPosition(PhysGrabObject source, ItemAttributes sourceItem)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.01f;
			if (IsCartItem(sourceItem))
			{
				num = 1f;
			}
			return ((Component)source).transform.position + Vector3.up * num;
		}

		private bool CanCloneCartThisShop(ItemAttributes sourceItem)
		{
			if (IsStandardCartItem(sourceItem))
			{
				return currentShopCartCloneCount < 5;
			}
			if (IsPocketCartItem(sourceItem))
			{
				return currentShopPocketCartCloneCount < 5;
			}
			return true;
		}

		private void RegisterCartClone(ItemAttributes sourceItem)
		{
			if (IsStandardCartItem(sourceItem))
			{
				currentShopCartCloneCount++;
			}
			else if (IsPocketCartItem(sourceItem))
			{
				currentShopPocketCartCloneCount++;
			}
		}

		private void ResetShopCounters()
		{
			currentShopCartCloneCount = 0;
			currentShopPocketCartCloneCount = 0;
		}

		private void CloneHeldShopItem(PhysGrabObject source, ItemAttributes sourceItem)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)sourceItem == (Object)null || (Object)(object)sourceItem.item == (Object)null || !CanCloneCartThisShop(sourceItem))
			{
				return;
			}
			string text = null;
			if (sourceItem.item.prefab != null)
			{
				text = sourceItem.item.prefab.ResourcePath;
			}
			if (string.IsNullOrEmpty(text))
			{
				ShopItemClonePlugin.LogSource.LogWarning((object)("Skipped clone because resource path was missing: " + ((Object)source).name));
				return;
			}
			Vector3 cloneSpawnPosition = GetCloneSpawnPosition(source, sourceItem);
			Quaternion rotation = ((Component)source).transform.rotation;
			GameObject val = ((!GameManager.Multiplayer()) ? Object.Instantiate<GameObject>(sourceItem.item.prefab.Prefab, cloneSpawnPosition, rotation) : PhotonNetwork.InstantiateRoomObject(text, cloneSpawnPosition, rotation, (byte)0, (object[])null));
			if (!((Object)(object)val == (Object)null))
			{
				RegisterCartClone(sourceItem);
				Rigidbody rb = source.rb;
				Rigidbody component = val.GetComponent<Rigidbody>();
				TryApplyInitialMotion(rb, component);
				PhysGrabObjectImpactDetector component2 = val.GetComponent<PhysGrabObjectImpactDetector>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.ImpactDisable(0.2f);
				}
				((MonoBehaviour)this).StartCoroutine(FinalizeCloneAfterStart(source, sourceItem, val));
				((MonoBehaviour)this).StartCoroutine(IgnoreCloneCollisionTemporary(((Component)source).gameObject, val, 0.2f));
			}
		}

		[IteratorStateMachine(typeof(<FinalizeCloneAfterStart>d__37))]
		private IEnumerator FinalizeCloneAfterStart(PhysGrabObject source, ItemAttributes sourceItem, GameObject cloneObject)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FinalizeCloneAfterStart>d__37(0)
			{
				<>4__this = this,
				source = source,
				sourceItem = sourceItem,
				cloneObject = cloneObject
			};
		}

		[IteratorStateMachine(typeof(<IgnoreCloneCollisionTemporary>d__38))]
		private IEnumerator IgnoreCloneCollisionTemporary(GameObject sourceObject, GameObject cloneObject, float duration)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <IgnoreCloneCollisionTemporary>d__38(0)
			{
				<>4__this = this,
				sourceObject = sourceObject,
				cloneObject = cloneObject,
				duration = duration
			};
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "OnCollisionStay")]
	internal static class PhysGrabObjectImpactDetectorPatch
	{
		private static void Postfix(PhysGrabObjectImpactDetector __instance, Collision collision)
		{
			ShopItemCloneRuntime instance = ShopItemCloneRuntime.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				instance.OnImpactStay(__instance, collision);
			}
		}
	}
}