Decompiled source of ShoppingCart v1.0.4

ShoppingCart.dll

Decompiled 3 weeks 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 System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using ShoppingCart;
using TMPro;
using UnityEngine;

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

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class ShopCartComponent : MonoBehaviour
{
	private List<ItemAttributes> itemsInCart = new List<ItemAttributes>();

	private Transform? inCartTransform;

	private Collider? inCartTrigger;

	private float rescanTimer;

	private const float RESCAN_INTERVAL = 0.2f;

	private float nextValueDebugLogTime;

	private string? lastSetDisplayText;

	private float lastSetDisplayTime;

	private static FieldInfo? ShopItemField;

	private int totalCost;

	public TextMeshPro? costDisplay;

	private PhotonView? photonView;

	private PhysGrabObject? physGrabObject;

	private MeshRenderer? cartMesh;

	private float cleanupTimer;

	private const float CLEANUP_INTERVAL = 0.5f;

	private void Awake()
	{
		photonView = ((Component)this).GetComponent<PhotonView>();
		physGrabObject = ((Component)this).GetComponent<PhysGrabObject>();
		inCartTransform = ((Component)this).transform.Find("In Cart");
		if ((Object)(object)inCartTransform != (Object)null)
		{
			inCartTrigger = ((Component)inCartTransform).GetComponent<Collider>();
			if ((Object)(object)inCartTrigger == (Object)null)
			{
				global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' child has no Collider!");
			}
			else if (!inCartTrigger.isTrigger)
			{
				global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' collider is not marked as Trigger. Value scanning will still work, but trigger events won't.");
			}
			if ((Object)(object)((Component)inCartTransform).GetComponent<ShopCartTrigger>() == (Object)null)
			{
				global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' child needs ShopCartTrigger component!");
			}
		}
		else
		{
			global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: 'In Cart' child GameObject not found!");
		}
		if ((Object)(object)costDisplay == (Object)null)
		{
			Transform val = ((Component)this).transform.Find("Screen/Text");
			if ((Object)(object)val != (Object)null)
			{
				costDisplay = ((Component)val).GetComponent<TextMeshPro>();
			}
			if ((Object)(object)costDisplay == (Object)null)
			{
				TextMeshPro[] componentsInChildren = ((Component)this).GetComponentsInChildren<TextMeshPro>(true);
				costDisplay = ((IEnumerable<TextMeshPro>)componentsInChildren).FirstOrDefault((Func<TextMeshPro, bool>)((TextMeshPro t) => (Object)(object)t.transform.parent != (Object)null && ((Object)t.transform.parent).name == "Screen" && ((Object)t).name == "Text")) ?? ((IEnumerable<TextMeshPro>)componentsInChildren).FirstOrDefault((Func<TextMeshPro, bool>)((TextMeshPro t) => ((Object)t).name.Contains("Screen") || ((Object)(object)t.transform.parent != (Object)null && ((Object)t.transform.parent).name.Contains("Screen")))) ?? componentsInChildren.FirstOrDefault();
			}
		}
		cartMesh = ((IEnumerable<MeshRenderer>)((Component)this).GetComponentsInChildren<MeshRenderer>(true)).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer m) => (Object)(object)((Component)m).transform != (Object)(object)((Component)this).transform));
	}

	private void Start()
	{
		try
		{
			CartMaterialRepair.RepairCartMaterials(((Component)this).gameObject);
		}
		catch
		{
		}
		UpdateCostDisplay();
		if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value)
		{
			global::ShoppingCart.ShoppingCart.LogInfo("ShopCartComponent: Start on '" + ((Object)((Component)this).gameObject).name + "'. costDisplay=" + (((Object)(object)costDisplay != (Object)null) ? ((Object)costDisplay).name : "<null>") + ", inCartTrigger=" + (((Object)(object)inCartTrigger != (Object)null) ? ((object)inCartTrigger).GetType().Name : "<null>"));
		}
	}

	private void Update()
	{
		if (SemiFunc.RunIsShop() && SemiFunc.IsMasterClientOrSingleplayer())
		{
			if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && (Object)(object)costDisplay != (Object)null && lastSetDisplayText != null && Time.unscaledTime - lastSetDisplayTime < 1f && ((TMP_Text)costDisplay).text != lastSetDisplayText)
			{
				global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: Screen text overwritten. Expected '" + lastSetDisplayText + "', actual '" + ((TMP_Text)costDisplay).text + "'. Another script is writing to the same TMP.");
				lastSetDisplayTime = -999f;
			}
			rescanTimer -= Time.deltaTime;
			if (rescanTimer <= 0f)
			{
				RescanAndRecalculate();
				rescanTimer = 0.2f;
			}
			cleanupTimer -= Time.deltaTime;
			if (cleanupTimer <= 0f)
			{
				CleanupDestroyedItems();
				cleanupTimer = 0.5f;
			}
		}
	}

	public void OnItemEnter(ItemAttributes itemAttributes)
	{
		if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop())
		{
			RescanAndRecalculate();
		}
	}

	public void OnItemExit(ItemAttributes itemAttributes)
	{
		if (SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.RunIsShop())
		{
			RescanAndRecalculate();
		}
	}

	private bool IsPurchasableShopItem(ItemAttributes itemAttributes)
	{
		if ((Object)(object)itemAttributes == (Object)null)
		{
			return false;
		}
		if (!SemiFunc.RunIsShop())
		{
			return false;
		}
		if ((object)ShopItemField == null)
		{
			ShopItemField = typeof(ItemAttributes).GetField("shopItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		if (ShopItemField != null && ShopItemField.FieldType == typeof(bool))
		{
			try
			{
				return (bool)ShopItemField.GetValue(itemAttributes);
			}
			catch
			{
			}
		}
		return (Object)(object)itemAttributes.item != (Object)null;
	}

	private void RescanAndRecalculate()
	{
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: 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_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_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: 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_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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			return;
		}
		if ((Object)(object)inCartTransform == (Object)null || (Object)(object)inCartTrigger == (Object)null)
		{
			if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime)
			{
				global::ShoppingCart.ShoppingCart.LogWarning($"ShopCartComponent: Missing inCartTransform/inCartTrigger. inCartTransform={(Object)(object)inCartTransform != (Object)null}, inCartTrigger={(Object)(object)inCartTrigger != (Object)null}");
				nextValueDebugLogTime = Time.unscaledTime + 1f;
			}
			return;
		}
		Collider? obj = inCartTrigger;
		BoxCollider val = (BoxCollider)(object)((obj is BoxCollider) ? obj : null);
		Vector3 val2;
		Vector3 val3;
		Quaternion val4;
		if (val != null)
		{
			val2 = ((Component)val).transform.TransformPoint(val.center);
			Vector3 lossyScale = ((Component)val).transform.lossyScale;
			((Vector3)(ref lossyScale))..ctor(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z));
			val3 = Vector3.Scale(val.size * 0.5f, lossyScale);
			val4 = ((Component)val).transform.rotation;
		}
		else
		{
			Bounds bounds = inCartTrigger.bounds;
			val2 = ((Bounds)(ref bounds)).center;
			val3 = ((Bounds)(ref bounds)).extents;
			val4 = Quaternion.identity;
		}
		Collider[] array = Physics.OverlapBox(val2, val3, val4, -1, (QueryTriggerInteraction)1);
		if (array == null)
		{
			return;
		}
		itemsInCart.Clear();
		int num = 0;
		int num2 = 0;
		Collider[] array2 = array;
		foreach (Collider val5 in array2)
		{
			if ((Object)(object)val5 == (Object)null || ((Component)val5).transform.IsChildOf(((Component)this).transform))
			{
				continue;
			}
			ItemAttributes componentInParent = ((Component)val5).GetComponentInParent<ItemAttributes>();
			if ((Object)(object)componentInParent == (Object)null || !IsPurchasableShopItem(componentInParent) || itemsInCart.Contains(componentInParent))
			{
				continue;
			}
			itemsInCart.Add(componentInParent);
			num += componentInParent.value;
			num2++;
			if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime)
			{
				bool flag = IsPurchasableShopItem(componentInParent);
				int num3 = 0;
				PhotonView component = ((Component)componentInParent).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					num3 = component.ViewID;
				}
				global::ShoppingCart.ShoppingCart.LogInfo($"ShopCartComponent: Found item '{((Object)((Component)componentInParent).gameObject).name}' value={componentInParent.value} shopItem={flag} pv={num3} at {((Component)componentInParent).transform.position}");
			}
		}
		if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime)
		{
			global::ShoppingCart.ShoppingCart.LogInfo($"ShopCartComponent: OverlapBox center={val2} ext={val3} rotY={((Quaternion)(ref val4)).eulerAngles.y:F1} overlaps={array.Length} uniqueItems={num2} newTotal={num}");
			nextValueDebugLogTime = Time.unscaledTime + 1f;
		}
		if (num != totalCost)
		{
			totalCost = num;
			UpdateCostDisplay();
			if (SemiFunc.IsMultiplayer() && (Object)(object)photonView != (Object)null)
			{
				photonView.RPC("UpdateCartDisplayRPC", (RpcTarget)1, new object[1] { totalCost });
			}
		}
	}

	private void CalculateTotalCost()
	{
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			return;
		}
		int num = 0;
		foreach (ItemAttributes item in itemsInCart)
		{
			if ((Object)(object)item != (Object)null)
			{
				num += item.value;
			}
		}
		if (num != totalCost)
		{
			totalCost = num;
			UpdateCostDisplay();
			if (SemiFunc.IsMultiplayer() && (Object)(object)photonView != (Object)null)
			{
				photonView.RPC("UpdateCartDisplayRPC", (RpcTarget)1, new object[1] { totalCost });
			}
		}
	}

	private void UpdateCostDisplay()
	{
		if ((Object)(object)costDisplay == (Object)null)
		{
			if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime)
			{
				global::ShoppingCart.ShoppingCart.LogWarning("ShopCartComponent: costDisplay is null; cannot update screen text.");
				nextValueDebugLogTime = Time.unscaledTime + 1f;
			}
			return;
		}
		string text = SemiFunc.DollarGetString(Mathf.Max(0, totalCost));
		string text2 = "$" + text;
		((TMP_Text)costDisplay).text = text2;
		((Component)costDisplay).gameObject.SetActive(true);
		lastSetDisplayText = text2;
		lastSetDisplayTime = Time.unscaledTime;
		if (global::ShoppingCart.ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= nextValueDebugLogTime)
		{
			global::ShoppingCart.ShoppingCart.LogInfo("ShopCartComponent: Set screen text to '" + text2 + "' on '" + ((Object)costDisplay).name + "'");
			nextValueDebugLogTime = Time.unscaledTime + 1f;
		}
	}

	[PunRPC]
	private void UpdateCartDisplayRPC(int syncedTotalCost, PhotonMessageInfo info = default(PhotonMessageInfo))
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if (SemiFunc.MasterOnlyRPC(info))
		{
			totalCost = syncedTotalCost;
			UpdateCostDisplay();
		}
	}

	private void CleanupDestroyedItems()
	{
		if (!SemiFunc.IsMasterClientOrSingleplayer())
		{
			return;
		}
		bool flag = false;
		for (int num = itemsInCart.Count - 1; num >= 0; num--)
		{
			if ((Object)(object)itemsInCart[num] == (Object)null || (Object)(object)((Component)itemsInCart[num]).gameObject == (Object)null)
			{
				itemsInCart.RemoveAt(num);
				flag = true;
			}
		}
		if (flag)
		{
			CalculateTotalCost();
		}
	}
}
public class ShopCartTrigger : MonoBehaviour
{
	public ShopCartComponent? parentCart;

	private static readonly int[] ALLOWED_ITEM_LAYERS = new int[4] { 9, 16, 20, 23 };

	private void Awake()
	{
		parentCart = ((Component)this).GetComponentInParent<ShopCartComponent>();
		if ((Object)(object)parentCart == (Object)null)
		{
			Debug.LogError((object)"ShopCartTrigger: Parent ShopCartComponent not found!");
		}
		else
		{
			Debug.Log((object)("ShopCartTrigger: Found parent cart at '" + ((Object)((Component)parentCart).gameObject).name + "'"));
		}
	}

	private void OnTriggerEnter(Collider other)
	{
		if ((Object)(object)parentCart == (Object)null || (Object)(object)((Component)other).transform.root == (Object)(object)((Component)this).transform.root)
		{
			return;
		}
		int otherLayer = ((Component)other).gameObject.layer;
		if (Array.Exists(ALLOWED_ITEM_LAYERS, (int layer) => layer == otherLayer))
		{
			ItemAttributes componentInParent = ((Component)other).GetComponentInParent<ItemAttributes>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				parentCart.OnItemEnter(componentInParent);
			}
		}
	}

	private void OnTriggerExit(Collider other)
	{
		if ((Object)(object)parentCart == (Object)null)
		{
			return;
		}
		int otherLayer = ((Component)other).gameObject.layer;
		if (Array.Exists(ALLOWED_ITEM_LAYERS, (int layer) => layer == otherLayer))
		{
			ItemAttributes componentInParent = ((Component)other).GetComponentInParent<ItemAttributes>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				parentCart.OnItemExit(componentInParent);
			}
		}
	}
}
namespace ShoppingCart
{
	internal static class CartMaterialRepair
	{
		internal static void RepairCartMaterials(GameObject cartRoot)
		{
			if ((Object)(object)cartRoot == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren;
			try
			{
				componentsInChildren = cartRoot.GetComponentsInChildren<Renderer>(true);
			}
			catch
			{
				return;
			}
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Material[] materials;
				try
				{
					materials = val.materials;
				}
				catch
				{
					continue;
				}
				bool flag = IsBasketLike(((Object)((Component)val).gameObject).name);
				foreach (Material val2 in materials)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						if (IsBrokenOrErrorShader(val2))
						{
							TryRepairMaterialShader(val2, flag);
						}
						else if (flag)
						{
							TryEnableAlphaClip(val2);
						}
					}
				}
				try
				{
					val.materials = materials;
				}
				catch
				{
				}
			}
		}

		private static bool IsBasketLike(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string text = name.ToLowerInvariant();
			if (!text.Contains("basket") && !text.Contains("wire") && !text.Contains("grid") && !text.Contains("net") && !text.Contains("mesh"))
			{
				return text.Contains("cage");
			}
			return true;
		}

		private static bool IsBrokenOrErrorShader(Material mat)
		{
			Shader shader = mat.shader;
			if ((Object)(object)shader == (Object)null)
			{
				return true;
			}
			string text = ((Object)shader).name ?? string.Empty;
			if (text.Contains("InternalErrorShader", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.Contains("Hidden/InternalErrorShader", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		private static void TryRepairMaterialShader(Material mat, bool basketLike)
		{
			//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_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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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)
			Texture val = null;
			if (mat.HasProperty("_BaseMap"))
			{
				val = mat.GetTexture("_BaseMap");
			}
			if ((Object)(object)val == (Object)null && mat.HasProperty("_MainTex"))
			{
				val = mat.GetTexture("_MainTex");
			}
			Color val2 = Color.white;
			if (mat.HasProperty("_BaseColor"))
			{
				val2 = mat.GetColor("_BaseColor");
			}
			else if (mat.HasProperty("_Color"))
			{
				val2 = mat.GetColor("_Color");
			}
			Shader val3 = Shader.Find("Universal Render Pipeline/Lit");
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = Shader.Find("Standard");
			}
			if ((Object)(object)val3 == (Object)null)
			{
				return;
			}
			mat.shader = val3;
			if (mat.HasProperty("_BaseColor"))
			{
				mat.SetColor("_BaseColor", val2);
			}
			if (mat.HasProperty("_Color"))
			{
				mat.SetColor("_Color", val2);
			}
			if ((Object)(object)val != (Object)null)
			{
				if (mat.HasProperty("_BaseMap"))
				{
					mat.SetTexture("_BaseMap", val);
				}
				if (mat.HasProperty("_MainTex"))
				{
					mat.SetTexture("_MainTex", val);
				}
			}
			if (basketLike)
			{
				TryEnableAlphaClip(mat);
			}
		}

		private static void TryEnableAlphaClip(Material mat)
		{
			if (mat.HasProperty("_AlphaClip"))
			{
				mat.SetFloat("_AlphaClip", 1f);
			}
			if (mat.HasProperty("_Cutoff"))
			{
				float num = mat.GetFloat("_Cutoff");
				if (num <= 0f)
				{
					num = 0.5f;
				}
				mat.SetFloat("_Cutoff", num);
			}
			try
			{
				mat.EnableKeyword("_ALPHATEST_ON");
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class ExamplePlayerControllerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void Start_Prefix(PlayerController __instance)
		{
			ShoppingCart.Logger.LogDebug((object)$"{__instance} Start Prefix");
		}

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Start_Postfix(PlayerController __instance)
		{
			ShoppingCart.Logger.LogDebug((object)$"{__instance} Start Postfix");
		}
	}
	[HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "DestroyObject")]
	internal static class ImpactDestroyPatch
	{
		private const float FALL_OUT_Y = -50f;

		private static float _nextBlockedLogTime;

		private static bool _missingSpawnPointLogged;

		[HarmonyPrefix]
		private static bool Prefix(PhysGrabObjectImpactDetector __instance)
		{
			//IL_001e: 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_00b6: 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_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)
			if (!ShopCartSpawner.IsModCart(((Component)__instance).gameObject))
			{
				return true;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			if (((Component)__instance).transform.position.y < -50f)
			{
				if ((Object)(object)TruckSafetySpawnPoint.instance == (Object)null)
				{
					if (!_missingSpawnPointLogged)
					{
						_missingSpawnPointLogged = true;
						ShoppingCart.LogWarning("Mod cart fell out of the map and this level has no TruckSafetySpawnPoint; cannot recover it.");
					}
					return false;
				}
				PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>();
				if ((Object)(object)component != (Object)null)
				{
					if ((Object)(object)component.rb != (Object)null && !component.rb.isKinematic)
					{
						component.rb.velocity = Vector3.zero;
						component.rb.angularVelocity = Vector3.zero;
					}
					Transform transform = ((Component)TruckSafetySpawnPoint.instance).transform;
					component.Teleport(transform.position, transform.rotation);
					ShoppingCart.LogWarning($"Mod cart fell out of the map; teleported to truck safety spawn {transform.position}");
				}
				return false;
			}
			if (Time.unscaledTime >= _nextBlockedLogTime)
			{
				_nextBlockedLogTime = Time.unscaledTime + 1f;
				ShoppingCart.LogInfo("Blocked DestroyObject on the mod cart");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemAttributes), "ShowInfo")]
	internal static class ItemAttributesShowInfoPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemAttributes __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return false;
			}
			return !ShopCartSpawner.IsModCart(((Component)__instance).gameObject);
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "CartSteer")]
	internal static class PhysGrabCartDistancePatch
	{
		private static float _nextCartSteerLogTime;

		private static float _lastA;

		private static float _lastB;

		private static float _lastD;

		private static float _lastTurnMultiplier;

		private static float _lastTurnMinFactor;

		private static float _lastTurnMaxClamp;

		[HarmonyPrefix]
		private static bool Prefix(PhysGrabCart __instance)
		{
			int spawnedCartInstanceID = ShopCartSpawner.SpawnedCartInstanceID;
			if (spawnedCartInstanceID == 0 || ((Object)((Component)__instance).gameObject).GetInstanceID() != spawnedCartInstanceID)
			{
				return true;
			}
			CustomCartSteer(__instance);
			return false;
		}

		private static void CustomCartSteer(PhysGrabCart cart)
		{
			//IL_0169: 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_017d: 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_01ac: 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_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: 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_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: 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_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_045b: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			float num = ShoppingCart.CartWalkDistance.Value;
			float num2 = ShoppingCart.CartSprintDistance.Value;
			float num3 = ShoppingCart.CartTurnMultiplier.Value;
			float num4 = ShoppingCart.CartTurnMinFactor.Value;
			float num5 = ShoppingCart.CartTurnMaxClamp.Value;
			if (float.IsNaN(num) || num < 0f)
			{
				num = 0f;
			}
			if (float.IsNaN(num2) || num2 < 0f)
			{
				num2 = 0f;
			}
			num = Mathf.Clamp(num, 0.7f, 4f);
			num2 = Mathf.Clamp(num2, 0.7f, 4f);
			if (num3 < 0f)
			{
				num3 = 0f;
			}
			if (num4 < 0f)
			{
				num4 = 0f;
			}
			if (num5 < 0f)
			{
				num5 = 0f;
			}
			PhysGrabObjectGrabArea component = ((Component)cart).GetComponent<PhysGrabObjectGrabArea>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			List<PhysGrabber> listOfAllGrabbers = component.listOfAllGrabbers;
			foreach (PhysGrabber item in listOfAllGrabbers)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					if (item.isLocal)
					{
						TutorialDirector.instance.playerUsedCart = true;
					}
					item.OverrideGrabPoint(cart.cartGrabPoint);
				}
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			BoxCollider component2 = ((Component)cart.inCart).GetComponent<BoxCollider>();
			float num10 = default(float);
			Vector3 val10 = default(Vector3);
			foreach (PhysGrabber item2 in listOfAllGrabbers)
			{
				if (!Object.op_Implicit((Object)(object)item2))
				{
					continue;
				}
				Vector3 val = ((Component)item2.playerAvatar).transform.position + Vector3.up * 0.25f;
				if (item2.playerAvatar.isTumbling)
				{
					val = item2.playerAvatar.tumble.physGrabObject.centerPoint;
				}
				if (!(Vector3.Distance(((Collider)component2).ClosestPoint(val), val) >= 0.01f))
				{
					continue;
				}
				Rigidbody component3 = ((Component)cart).GetComponent<Rigidbody>();
				((object)cart).GetType().GetMethod("CartMassOverride", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(cart, new object[1] { 4f });
				if ((Object)(object)item2 == (Object)(object)PhysGrabber.instance)
				{
					SemiFunc.PhysGrabberLocalChangeAlpha(0.1f);
				}
				if (!cart.cartActive && item2.initialPressTimer > 0f)
				{
					cart.cartActive = true;
				}
				if (!cart.cartActive || (Object)(object)item2 != (Object)(object)listOfAllGrabbers[0])
				{
					break;
				}
				cart.cartBeingPulled = true;
				item2.OverridePhysGrabForcesDisable(0.1f);
				float num6 = num;
				float num7 = num2;
				if (cart.isSmallCart)
				{
					num6 = 1.75f;
					num7 = 2f;
				}
				Vector3 val2 = PlayerController.instance.rb.velocity;
				if (!item2.isLocal)
				{
					val2 = item2.playerAvatar.rbVelocityRaw;
				}
				bool flag = Vector3.Dot(val2, ((Component)cart).transform.forward) > 0f;
				float num8 = ((item2.playerAvatar.isSprinting && flag) ? num7 : num6);
				Vector3 val3 = ((Component)item2).transform.rotation * Vector3.back;
				Vector3 val4 = ((Component)item2.playerAvatar).transform.position - val3 * num8;
				float num9 = Mathf.Clamp(Vector3.Distance(((Component)cart).transform.position, val4 / 1f), 0f, 1f);
				Vector3 val5 = val4 - ((Component)cart).transform.position;
				Vector3 val6 = ((Vector3)(ref val5)).normalized * 5f * num9;
				val6 = Vector3.ClampMagnitude(val6, 5f);
				float y = component3.velocity.y;
				component3.velocity = Vector3.MoveTowards(component3.velocity, val6, num9 * 2f);
				component3.velocity = new Vector3(component3.velocity.x, y, component3.velocity.z);
				component3.velocity = Vector3.ClampMagnitude(component3.velocity, 5f);
				Quaternion val7 = Quaternion.LookRotation(((Component)item2).transform.position - ((Component)cart).transform.position, Vector3.up);
				Quaternion val8 = Quaternion.Euler(0f, ((Quaternion)(ref val7)).eulerAngles.y + 180f, 0f);
				val7 = component3.rotation;
				Quaternion val9 = Quaternion.Euler(0f, ((Quaternion)(ref val7)).eulerAngles.y, 0f);
				val7 = val8 * Quaternion.Inverse(val9);
				((Quaternion)(ref val7)).ToAngleAxis(ref num10, ref val10);
				if (num10 > 180f)
				{
					num10 -= 360f;
				}
				float num11 = Mathf.Clamp(Mathf.Abs(num10) / 180f, num4, 1f) * num3;
				num11 = Mathf.Clamp(num11, 0f, num5);
				Vector3 val11 = MathF.PI / 180f * num10 * ((Vector3)(ref val10)).normalized * num11;
				val11 = Vector3.ClampMagnitude(val11, num5);
				component3.angularVelocity = Vector3.MoveTowards(component3.angularVelocity, val11, num11);
				component3.angularVelocity = Vector3.ClampMagnitude(component3.angularVelocity, num5);
				if (ShoppingCart.CartSteerDebugLogging.Value && Time.unscaledTime >= _nextCartSteerLogTime)
				{
					if (Mathf.Abs(_lastA - num6) > 0.001f || Mathf.Abs(_lastB - num7) > 0.001f || Mathf.Abs(_lastD - num8) > 0.001f || Mathf.Abs(_lastTurnMultiplier - num3) > 0.001f || Mathf.Abs(_lastTurnMinFactor - num4) > 0.001f || Mathf.Abs(_lastTurnMaxClamp - num5) > 0.001f)
					{
						ShoppingCart.LogInfo($"[CartSteer] dist walk={num6:F2} sprint={num7:F2} active={num8:F2} | turn mult={num3:F1} min={num4:F2} clamp={num5:F1}");
						_lastA = num6;
						_lastB = num7;
						_lastD = num8;
						_lastTurnMultiplier = num3;
						_lastTurnMinFactor = num4;
						_lastTurnMaxClamp = num5;
					}
					_nextCartSteerLogTime = Time.unscaledTime + 1f;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabCart), "ObjectsInCart")]
	internal static class PhysGrabCartShopTotalPatch
	{
		private sealed class CartScanState
		{
			public readonly Dictionary<int, float> LastSeenTime = new Dictionary<int, float>();

			public readonly Dictionary<int, int> LastValueDollars = new Dictionary<int, int>();
		}

		private static readonly FieldRef<PhysGrabCart, Transform>? InCartRef;

		private static readonly FieldRef<PhysGrabCart, int>? HaulCurrentRef;

		private static readonly FieldRef<PhysGrabCart, float>? ObjectInCartCheckTimerRef;

		private static readonly FieldRef<PhysGrabCart, List<PhysGrabObject>>? ItemsInCartRef;

		private static readonly FieldRef<PhysGrabCart, int>? ItemsInCartCountRef;

		private static readonly bool Disabled;

		private static float _nextDebugTime;

		private const float SCAN_CULL_DISTANCE = 12f;

		private const float SCAN_INTERVAL_SECONDS = 0.5f;

		private const int SHOP_ITEM_K_TO_DOLLARS = 1000;

		private const float MISSING_GRACE_SECONDS = 1f;

		private static readonly Dictionary<int, CartScanState> StateByCart;

		private static readonly HashSet<int> AdoptedCarts;

		private static readonly HashSet<int> AttachFailed;

		private static readonly HashSet<int> ScreenFailed;

		static PhysGrabCartShopTotalPatch()
		{
			StateByCart = new Dictionary<int, CartScanState>();
			AdoptedCarts = new HashSet<int>();
			AttachFailed = new HashSet<int>();
			ScreenFailed = new HashSet<int>();
			try
			{
				InCartRef = AccessTools.FieldRefAccess<PhysGrabCart, Transform>("inCart");
				HaulCurrentRef = AccessTools.FieldRefAccess<PhysGrabCart, int>("haulCurrent");
				ObjectInCartCheckTimerRef = AccessTools.FieldRefAccess<PhysGrabCart, float>("objectInCartCheckTimer");
				ItemsInCartRef = AccessTools.FieldRefAccess<PhysGrabCart, List<PhysGrabObject>>("itemsInCart");
				ItemsInCartCountRef = AccessTools.FieldRefAccess<PhysGrabCart, int>("itemsInCartCount");
			}
			catch (Exception ex)
			{
				Disabled = true;
				ShoppingCart.LogError("PhysGrabCartShopTotalPatch disabled, PhysGrabCart layout changed: " + ex.GetType().Name + ": " + ex.Message);
			}
		}

		internal static void ResetState()
		{
			StateByCart.Clear();
			AdoptedCarts.Clear();
			AttachFailed.Clear();
			ScreenFailed.Clear();
		}

		[HarmonyPrefix]
		private static bool Prefix(PhysGrabCart __instance)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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_0160: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: 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_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: 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_01ec: 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_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			if (Disabled)
			{
				return true;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if ((Object)(object)__instance.valueScreen == (Object)null)
			{
				if (!ShopCartSpawner.IsModCart(((Component)__instance).gameObject))
				{
					return true;
				}
				if (AttachFailed.Contains(instanceID))
				{
					return false;
				}
				if (!TryAttachValueScreen(__instance))
				{
					AttachFailed.Add(instanceID);
					return false;
				}
				AdoptedCarts.Add(instanceID);
				ShopCartSpawner.ApplyModCartProtection(((Component)__instance).gameObject);
			}
			if (!AdoptedCarts.Contains(instanceID))
			{
				return true;
			}
			if (!SemiFunc.RunIsShop())
			{
				return true;
			}
			if (!StateByCart.TryGetValue(instanceID, out CartScanState value))
			{
				value = new CartScanState();
				StateByCart[instanceID] = value;
			}
			if (SemiFunc.PlayerNearestDistance(((Component)__instance).transform.position) > 12f)
			{
				return false;
			}
			Transform val = InCartRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null)
			{
				if (!ScreenFailed.Contains(instanceID))
				{
					ScreenFailed.Add(instanceID);
					ShoppingCart.LogError("PhysGrabCartShopTotalPatch: '" + ((Object)((Component)__instance).gameObject).name + "' has no 'In Cart' transform; scan disabled for this cart.");
				}
				return false;
			}
			int num = HaulCurrentRef.Invoke(__instance);
			float num2 = ObjectInCartCheckTimerRef.Invoke(__instance);
			if (num2 > 0f)
			{
				ObjectInCartCheckTimerRef.Invoke(__instance) = Mathf.Max(0f, num2 - Time.deltaTime);
				return false;
			}
			PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>();
			Vector3 val2 = val.position;
			Vector3 val3 = val.localScale / 2f;
			Quaternion rotation = val.rotation;
			BoxCollider component2 = ((Component)val).GetComponent<BoxCollider>();
			if ((Object)(object)component2 != (Object)null)
			{
				val2 = ((Component)component2).transform.TransformPoint(component2.center);
				Vector3 lossyScale = ((Component)component2).transform.lossyScale;
				((Vector3)(ref lossyScale))..ctor(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z));
				val3 = Vector3.Scale(component2.size * 0.5f, lossyScale);
				rotation = ((Component)component2).transform.rotation;
			}
			Collider[] array = Physics.OverlapBox(val2, val3, rotation, -1, (QueryTriggerInteraction)2);
			HashSet<PhysGrabObject> hashSet = new HashSet<PhysGrabObject>();
			HashSet<ItemAttributes> hashSet2 = new HashSet<ItemAttributes>();
			List<PhysGrabObject> list = ItemsInCartRef.Invoke(__instance);
			list?.Clear();
			int num3 = 0;
			float unscaledTime = Time.unscaledTime;
			HashSet<int> hashSet3 = new HashSet<int>();
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			Collider[] array2 = array;
			foreach (Collider val4 in array2)
			{
				if ((Object)(object)val4 == (Object)null || (Object)(object)((Component)val4).GetComponentInParent<PlayerAvatar>() != (Object)null || (Object)(object)((Component)val4).GetComponentInParent<PlayerTumble>() != (Object)null)
				{
					continue;
				}
				PhysGrabObject componentInParent = ((Component)val4).GetComponentInParent<PhysGrabObject>();
				ItemAttributes val5 = null;
				ValuableObject val6 = null;
				if ((Object)(object)componentInParent != (Object)null)
				{
					val5 = ((Component)componentInParent).GetComponent<ItemAttributes>();
					if ((Object)(object)val5 == (Object)null)
					{
						val5 = ((Component)componentInParent).GetComponentInChildren<ItemAttributes>(true);
					}
					val6 = ((Component)componentInParent).GetComponent<ValuableObject>();
					if ((Object)(object)val6 == (Object)null)
					{
						val6 = ((Component)componentInParent).GetComponentInChildren<ValuableObject>(true);
					}
				}
				else
				{
					val5 = ((Component)val4).GetComponentInParent<ItemAttributes>();
					val6 = ((Component)val4).GetComponentInParent<ValuableObject>();
				}
				if ((Object)(object)componentInParent != (Object)null && (Object)(object)component != (Object)null && (Object)(object)componentInParent == (Object)(object)component)
				{
					continue;
				}
				int instanceID2;
				if ((Object)(object)componentInParent != (Object)null)
				{
					if (!hashSet.Add(componentInParent))
					{
						continue;
					}
					instanceID2 = ((Object)componentInParent).GetInstanceID();
					list?.Add(componentInParent);
					num3++;
				}
				else
				{
					if (!((Object)(object)val5 != (Object)null) || hashSet2.Contains(val5))
					{
						continue;
					}
					hashSet2.Add(val5);
					instanceID2 = ((Object)val5).GetInstanceID();
				}
				int? num7 = null;
				if ((Object)(object)val5 != (Object)null)
				{
					num7 = Mathf.Max(0, val5.value) * 1000;
					num4++;
				}
				else if ((Object)(object)val6 != (Object)null)
				{
					num7 = Mathf.RoundToInt(val6.dollarValueCurrent);
					num5++;
				}
				if (num7.HasValue)
				{
					value.LastSeenTime[instanceID2] = unscaledTime;
					value.LastValueDollars[instanceID2] = num7.Value;
					hashSet3.Add(instanceID2);
					if (ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= _nextDebugTime && num6 < 12)
					{
						string text = LayerMask.LayerToName(((Component)val4).gameObject.layer);
						string text2 = (((Object)(object)componentInParent != (Object)null) ? ((Object)((Component)componentInParent).gameObject).name : "<null>");
						string text3 = (((Object)(object)val5 != (Object)null) ? ((Object)((Component)val5).gameObject).name : "<null>");
						int num8 = (((Object)(object)val5 != (Object)null) ? val5.value : 0);
						bool flag = (Object)(object)val6 != (Object)null;
						ShoppingCart.LogInfo($"[CartValueHit] col='{((Object)val4).name}' layer={((Component)val4).gameObject.layer}('{text}') trig={val4.isTrigger} pgo='{text2}' ia='{text3}' iaValue={num8} hasVal={flag}");
						num6++;
					}
				}
			}
			int num9 = 0;
			if (value.LastSeenTime.Count > 0)
			{
				List<int> list2 = null;
				foreach (KeyValuePair<int, float> item in value.LastSeenTime)
				{
					int key = item.Key;
					float value2 = item.Value;
					if (!hashSet3.Contains(key) && unscaledTime - value2 > 1f)
					{
						if (list2 == null)
						{
							list2 = new List<int>();
						}
						list2.Add(key);
					}
				}
				if (list2 != null)
				{
					foreach (int item2 in list2)
					{
						value.LastSeenTime.Remove(item2);
						value.LastValueDollars.Remove(item2);
					}
				}
				foreach (KeyValuePair<int, int> lastValueDollar in value.LastValueDollars)
				{
					num9 += lastValueDollar.Value;
				}
			}
			ItemsInCartCountRef.Invoke(__instance) = num3;
			ObjectInCartCheckTimerRef.Invoke(__instance) = 0.5f;
			HaulCurrentRef.Invoke(__instance) = num9;
			bool flag2 = num9 != num;
			try
			{
				__instance.valueScreen.UpdateValue(num9);
			}
			catch (Exception ex)
			{
				if (!ScreenFailed.Contains(instanceID))
				{
					ScreenFailed.Add(instanceID);
					ShoppingCart.LogError("PhysGrabCartShopTotalPatch: ValueScreen.UpdateValue failed on '" + ((Object)((Component)__instance).gameObject).name + "': " + ex.GetType().Name + ": " + ex.Message);
				}
			}
			if (ShoppingCart.CartValueDebugLogging.Value && Time.unscaledTime >= _nextDebugTime)
			{
				if (flag2)
				{
					ShoppingCart.LogInfo($"[CartValue] Updated haulCurrent from {num} to {num9}. itemsSeen={num4} valuablesSeen={num5} overlap={array.Length} retained={value.LastValueDollars.Count} grace={1f:F1}s");
				}
				_nextDebugTime = Time.unscaledTime + 1f;
			}
			return false;
		}

		private static bool TryAttachValueScreen(PhysGrabCart cart)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			Transform val = ((Component)cart).transform.Find("Screen/Text");
			TextMeshPro val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TextMeshPro>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				string text = (((Object)(object)val == (Object)null) ? "child missing" : string.Join(",", Array.ConvertAll(((Component)val).GetComponents<Component>(), (Component comp) => ((object)comp).GetType().Name)));
				ShoppingCart.LogError("PhysGrabCartShopTotalPatch: no TextMeshPro at 'Screen/Text' on '" + ((Object)((Component)cart).gameObject).name + "' (" + text + "); cart screen stays static.");
				return false;
			}
			ValueScreen val3 = ((Component)cart).gameObject.AddComponent<ValueScreen>();
			val3.displayText = val2;
			val3.soundValueIncrease = new Sound
			{
				Sounds = Array.Empty<AudioClip>()
			};
			val3.soundValueDecrease = new Sound
			{
				Sounds = Array.Empty<AudioClip>()
			};
			ValueScreen val4 = FindSoundDonor(val3);
			if ((Object)(object)val4 != (Object)null)
			{
				Sound.CopySound(val4.soundValueIncrease, val3.soundValueIncrease);
				Sound.CopySound(val4.soundValueDecrease, val3.soundValueDecrease);
				val3.soundValueIncrease.Source = null;
				val3.soundValueDecrease.Source = null;
			}
			cart.valueScreen = val3;
			ShoppingCart.LogInfo("PhysGrabCartShopTotalPatch: attached ValueScreen to '" + ((Object)((Component)cart).gameObject).name + "' (sounds=" + (((Object)(object)val4 != (Object)null) ? "vanilla" : "none") + ").");
			return true;
		}

		private static ValueScreen? FindSoundDonor(ValueScreen self)
		{
			ValueScreen[] array = Resources.FindObjectsOfTypeAll<ValueScreen>();
			foreach (ValueScreen val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)self) && val.soundValueIncrease?.Sounds != null && val.soundValueIncrease.Sounds.Length != 0 && val.soundValueDecrease?.Sounds != null && val.soundValueDecrease.Sounds.Length != 0)
				{
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(ShopManager), "ShopInitialize")]
	internal static class ShopCartSpawner
	{
		[HarmonyPatch(typeof(RunManager), "ChangeLevel")]
		private static class CleanupCartOnLevelChange
		{
			[HarmonyPostfix]
			private static void Postfix(bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType)
			{
				PhysGrabCartShopTotalPatch.ResetState();
				if (!SemiFunc.RunIsShop() && (Object)(object)spawnedCart != (Object)null)
				{
					if (SemiFunc.IsMultiplayer() && SemiFunc.IsMasterClientOrSingleplayer())
					{
						PhotonNetwork.Destroy(spawnedCart);
					}
					else if (!SemiFunc.IsMultiplayer())
					{
						Object.Destroy((Object)(object)spawnedCart);
					}
					spawnedCart = null;
					spawnedCartInstanceID = 0;
					spawnedCartPhotonViewID = 0;
					spawnedCartPhysGrabObjectID = 0;
				}
			}
		}

		private static GameObject? cartPrefab;

		private static GameObject? spawnedCart;

		private static int spawnedCartInstanceID = 0;

		private static int spawnedCartPhotonViewID = 0;

		private static int spawnedCartPhysGrabObjectID = 0;

		private const string PrefabReadyRoomPropKey = "Tolga.ShoppingCart.PrefabReady";

		private const string PhotonPrefabKey = "Shopping Cart";

		private const string ModItemAssetName = "Item Shopping Cart";

		private static readonly Vector3 FallbackSpawnPosition = new Vector3(0.49f, 0.97f, -1.28f);

		private const float SLOT_OCCUPIED_RADIUS = 0.75f;

		private const float PLACE_GROUND_CLEARANCE = 0.02f;

		private static readonly float[] PlaceSearchRadii = new float[4] { 0f, 0.75f, 1.5f, 2.5f };

		private const int PLACE_SEARCH_DIRECTIONS = 8;

		internal static GameObject? LatestSpawnedCart => spawnedCart;

		internal static int SpawnedCartInstanceID => spawnedCartInstanceID;

		internal static int SpawnedCartPhotonViewID => spawnedCartPhotonViewID;

		internal static int SpawnedCartPhysGrabObjectID => spawnedCartPhysGrabObjectID;

		private static int GroundMask => LayerMask.GetMask(new string[2] { "Default", "StaticGrabObject" });

		private static int SolidMask => LayerMask.GetMask(new string[5] { "Default", "StaticGrabObject", "PhysGrabObject", "PhysGrabObjectCart", "PhysGrabObjectHinge" });

		[HarmonyPostfix]
		private static void Postfix()
		{
			if (SemiFunc.RunIsShop())
			{
				((MonoBehaviour)ShoppingCart.Instance).StartCoroutine(LoadRegisterAndMaybeSpawnCart());
			}
		}

		private static IEnumerator LoadRegisterAndMaybeSpawnCart()
		{
			if ((Object)(object)spawnedCart != (Object)null)
			{
				yield break;
			}
			float timeout = 10f;
			while (timeout > 0f && ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated))
			{
				timeout -= 0.1f;
				yield return (object)new WaitForSeconds(0.1f);
			}
			if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				ShoppingCart.LogError("Level did not finish generating within 10s; not spawning cart.");
				yield break;
			}
			if ((Object)(object)cartPrefab == (Object)null)
			{
				string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)ShoppingCart.Instance).Info.Location) ?? string.Empty, "shoppingcart");
				AssetBundle bundle = null;
				if (File.Exists(text))
				{
					AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(text);
					yield return request;
					bundle = request.assetBundle;
				}
				else
				{
					Assembly assembly = typeof(ShopCartSpawner).GetTypeInfo().Assembly;
					string text2 = null;
					string[] manifestResourceNames = assembly.GetManifestResourceNames();
					foreach (string text3 in manifestResourceNames)
					{
						if (text3.EndsWith(".shoppingcart") || text3.EndsWith("shoppingcart"))
						{
							text2 = text3;
							break;
						}
					}
					if (text2 == null)
					{
						ShoppingCart.LogError("Cart asset bundle not found at: " + text + " and no embedded resource available");
						yield break;
					}
					using Stream s = assembly.GetManifestResourceStream(text2);
					if (s == null)
					{
						ShoppingCart.LogError("Embedded resource '" + text2 + "' could not be opened");
						yield break;
					}
					byte[] array = new byte[s.Length];
					int num = s.Read(array, 0, array.Length);
					if (num != array.Length)
					{
						ShoppingCart.LogWarning($"Read {num} bytes from embedded '{text2}' but expected {array.Length}");
					}
					AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(array);
					yield return request;
					bundle = request.assetBundle;
				}
				if ((Object)(object)bundle == (Object)null)
				{
					ShoppingCart.LogError("Failed to load cart asset bundle!");
					yield break;
				}
				AssetBundleRequest allAssetsRequest = bundle.LoadAllAssetsAsync();
				yield return allAssetsRequest;
				cartPrefab = SelectCartPrefabDeterministically(bundle, allAssetsRequest.allAssets);
				if ((Object)(object)cartPrefab == (Object)null)
				{
					ShoppingCart.LogError("Cart prefab not found in asset bundle!");
					yield break;
				}
			}
			RegisterPrefabForPhoton(cartPrefab);
			if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom)
			{
				MarkLocalPrefabReady();
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				yield break;
			}
			if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom)
			{
				float waitBudget = 8f;
				while (waitBudget > 0f && !AreAllPlayersPrefabReady())
				{
					waitBudget -= 0.25f;
					yield return (object)new WaitForSeconds(0.25f);
				}
				if (!AreAllPlayersPrefabReady())
				{
					ShoppingCart.LogWarning("Not all players reported ShoppingCart prefab ready before spawn; spawning anyway.");
				}
			}
			if (!SemiFunc.RunIsShop() || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				ShoppingCart.LogWarning("Shop left before the cart could spawn; skipping.");
			}
			else
			{
				SpawnCart();
			}
		}

		private static GameObject? SelectCartPrefabDeterministically(AssetBundle bundle, Object[] allAssets)
		{
			string[] array = new string[4] { "Shopping Cart", "shopping_cart", "ShoppingCart", "Cart" };
			foreach (string text in array)
			{
				try
				{
					GameObject val = bundle.LoadAsset<GameObject>(text);
					if ((Object)(object)val != (Object)null)
					{
						ShoppingCart.LogInfo("Selected cart prefab by name '" + text + "'");
						return val;
					}
				}
				catch
				{
				}
			}
			GameObject[] array2 = (from g in allAssets.OfType<GameObject>()
				orderby ((Object)g).name
				select g).ToArray();
			if (array2.Length == 0)
			{
				return null;
			}
			GameObject val2 = null;
			int num = int.MinValue;
			GameObject[] array3 = array2;
			foreach (GameObject val3 in array3)
			{
				int num3 = 0;
				string text2 = ((Object)val3).name.ToLowerInvariant();
				if (text2.Contains("cart"))
				{
					num3 += 10;
				}
				if (text2.Contains("shopping"))
				{
					num3 += 5;
				}
				if ((Object)(object)val3.transform.Find("In Cart") != (Object)null)
				{
					num3 += 25;
				}
				if ((Object)(object)val3.transform.Find("Screen") != (Object)null)
				{
					num3 += 10;
				}
				if ((Object)(object)val3.transform.Find("Screen/Text") != (Object)null)
				{
					num3 += 10;
				}
				if ((Object)(object)val3.GetComponentInChildren<PhysGrabObject>(true) != (Object)null)
				{
					num3 += 10;
				}
				if ((Object)(object)val3.GetComponentInChildren<ShopCartComponent>(true) != (Object)null)
				{
					num3 += 10;
				}
				if ((Object)(object)val3.GetComponentInChildren<PhotonView>(true) != (Object)null)
				{
					num3 += 5;
				}
				if ((Object)(object)val2 == (Object)null || num3 > num)
				{
					val2 = val3;
					num = num3;
				}
			}
			string text3 = string.Join(", ", array2.Select((GameObject c) => ((Object)c).name));
			ShoppingCart.LogInfo("Cart bundle prefab candidates (sorted): " + text3);
			ShoppingCart.LogInfo(string.Format("Selected cart prefab by heuristic: '{0}' (score={1})", ((val2 != null) ? ((Object)val2).name : null) ?? "<null>", num));
			return val2;
		}

		private static void RegisterPrefabForPhoton(GameObject prefab)
		{
			if (!SemiFunc.IsMultiplayer())
			{
				return;
			}
			IPunPrefabPool prefabPool = PhotonNetwork.PrefabPool;
			DefaultPool val = (DefaultPool)(object)((prefabPool is DefaultPool) ? prefabPool : null);
			if (val != null)
			{
				val.ResourceCache["Shopping Cart"] = prefab;
				if (!string.IsNullOrEmpty(((Object)prefab).name))
				{
					val.ResourceCache[((Object)prefab).name] = prefab;
				}
			}
			else
			{
				ShoppingCart.LogWarning("PhotonNetwork.PrefabPool is '" + (((object)PhotonNetwork.PrefabPool)?.GetType().FullName ?? "<null>") + "', expected DefaultPool; cart may fail to spawn on some clients.");
			}
		}

		private static void MarkLocalPrefabReady()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0017: Expected O, but got Unknown
			try
			{
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"Tolga.ShoppingCart.PrefabReady", (object)true);
				Hashtable val2 = val;
				PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
			}
			catch
			{
			}
		}

		private static bool AreAllPlayersPrefabReady()
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val.CustomProperties == null)
				{
					return false;
				}
				if (!((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"Tolga.ShoppingCart.PrefabReady", out object value))
				{
					return false;
				}
				if (!(value is bool) || !(bool)value)
				{
					return false;
				}
			}
			return true;
		}

		private static Camera? GetBestCamera()
		{
			if ((Object)(object)Camera.main != (Object)null && ((Behaviour)Camera.main).isActiveAndEnabled)
			{
				return Camera.main;
			}
			Camera[] array = Object.FindObjectsOfType<Camera>();
			foreach (Camera val in array)
			{
				if (((Behaviour)val).isActiveAndEnabled && ((Component)val).CompareTag("MainCamera"))
				{
					return val;
				}
			}
			array = Object.FindObjectsOfType<Camera>();
			foreach (Camera val2 in array)
			{
				if (((Behaviour)val2).isActiveAndEnabled)
				{
					return val2;
				}
			}
			ShoppingCart.LogWarning("No active camera found for cart spawn");
			return null;
		}

		private static bool TryGetCameraSpawn(out Vector3 spawnPos, out Quaternion spawnRot)
		{
			//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_0011: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00d3: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			spawnPos = Vector3.zero;
			spawnRot = Quaternion.identity;
			Camera bestCamera = GetBestCamera();
			if ((Object)(object)bestCamera == (Object)null)
			{
				return false;
			}
			Vector3 position = ((Component)bestCamera).transform.position;
			Vector3 forward = ((Component)bestCamera).transform.forward;
			float num = 2f;
			float num2 = 3f;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(position, forward, ref val, num2, -1, (QueryTriggerInteraction)1))
			{
				num = Mathf.Clamp(((RaycastHit)(ref val)).distance - 0.4f, 0.8f, 2f);
				ShoppingCart.LogInfo($"F8: Raycast hit '{((Object)((RaycastHit)(ref val)).collider).name}' at {((RaycastHit)(ref val)).distance:F2}m, placing at {num:F2}m");
			}
			spawnPos = position + forward * num;
			spawnRot = Quaternion.Euler(0f, ((Component)bestCamera).transform.eulerAngles.y, 0f);
			ShoppingCart.LogInfo($"Spawned cart in air at: {spawnPos} (2m away, let it fall naturally)");
			return true;
		}

		private static void SpawnCart()
		{
			//IL_0022: 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_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cartPrefab == (Object)null)
			{
				return;
			}
			string text = "Shopping Cart";
			GetDesiredSpawn(out var position, out var rotation);
			ShoppingCart.LogInfo($"Spawning cart near {position} (rotation {((Quaternion)(ref rotation)).eulerAngles}); free-space placement runs next frame");
			if (SemiFunc.IsMultiplayer())
			{
				RegisterPrefabForPhoton(cartPrefab);
				spawnedCart = PhotonNetwork.InstantiateRoomObject(text, position, rotation, (byte)0, (object[])null);
			}
			else
			{
				spawnedCart = Object.Instantiate<GameObject>(cartPrefab, position, rotation);
			}
			if ((Object)(object)spawnedCart == (Object)null)
			{
				ShoppingCart.LogError("Failed to spawn cart! Instantiate returned null (prefab key unresolved?).");
				return;
			}
			if ((Object)(object)LevelGenerator.Instance != (Object)null && (Object)(object)LevelGenerator.Instance.ItemParent != (Object)null)
			{
				spawnedCart.transform.parent = LevelGenerator.Instance.ItemParent.transform;
			}
			spawnedCartInstanceID = ((Object)spawnedCart).GetInstanceID();
			PhotonView component = spawnedCart.GetComponent<PhotonView>();
			spawnedCartPhotonViewID = (((Object)(object)component != (Object)null) ? component.ViewID : 0);
			PhysGrabObject componentInChildren = spawnedCart.GetComponentInChildren<PhysGrabObject>(true);
			spawnedCartPhysGrabObjectID = (((Object)(object)componentInChildren != (Object)null) ? ((Object)componentInChildren).GetInstanceID() : 0);
			DisableVanillaCostUI(spawnedCart);
			ApplyModCartProtection(spawnedCart);
			try
			{
				ShopCartComponent componentInChildren2 = spawnedCart.GetComponentInChildren<ShopCartComponent>(true);
				int num = 0;
				MonoBehaviour[] componentsInChildren = spawnedCart.GetComponentsInChildren<MonoBehaviour>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] == (Object)null)
					{
						num++;
					}
				}
				string text2 = "<no ShopCartComponent>";
				string text3 = "<no ShopCartComponent>";
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					Transform val = ((Component)componentInChildren2).transform.Find("In Cart");
					Collider val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Collider>() : null);
					text2 = (((Object)(object)val2 != (Object)null) ? $"In Cart collider={((object)val2).GetType().Name} isTrigger={val2.isTrigger}" : "In Cart collider=<null>");
					Transform val3 = ((Component)componentInChildren2).transform.Find("Screen/Text");
					TextMeshPro val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<TextMeshPro>() : null);
					text3 = (((Object)(object)val4 != (Object)null) ? ("Screen TMP='" + ((Object)val4).name + "'") : "Screen TMP=<null>");
				}
				ShoppingCart.LogInfo($"Spawn sanity: ShopCartComponent={(Object)(object)componentInChildren2 != (Object)null}, {text2}, {text3}, missingMonoBehaviours={num}");
				ShoppingCart.LogInfo($"Spawn sanity IDs: cartInst={spawnedCartInstanceID}, cartPv={spawnedCartPhotonViewID}, cartPhysGrabObjectInst={spawnedCartPhysGrabObjectID}");
			}
			catch (Exception ex)
			{
				ShoppingCart.LogWarning("Spawn sanity failed: " + ex.GetType().Name + ": " + ex.Message);
			}
			InitializeCart(spawnedCart);
			((MonoBehaviour)ShoppingCart.Instance).StartCoroutine(FixCartPositionAfterSpawn(spawnedCart, position, rotation));
			ShoppingCart.LogInfo($"Cart instantiated (InstanceID: {spawnedCartInstanceID}). Will position via gravity + bounds-fix.");
		}

		internal static bool IsModCart(GameObject? go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			PhysGrabObject componentInParent = go.GetComponentInParent<PhysGrabObject>();
			GameObject val = (GameObject)(((Object)(object)componentInParent != (Object)null) ? ((object)((Component)componentInParent).gameObject) : ((object)go));
			if (spawnedCartInstanceID != 0 && ((Object)val).GetInstanceID() == spawnedCartInstanceID)
			{
				return true;
			}
			ItemAttributes component = val.GetComponent<ItemAttributes>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.item != (Object)null)
			{
				return ((Object)component.item).name == "Item Shopping Cart";
			}
			return false;
		}

		internal static void ApplyModCartProtection(GameObject cart)
		{
			FixWheels(cart);
			PhysGrabObjectImpactDetector component = cart.GetComponent<PhysGrabObjectImpactDetector>();
			if ((Object)(object)component == (Object)null)
			{
				ShoppingCart.LogWarning("No PhysGrabObjectImpactDetector on '" + ((Object)cart).name + "'");
			}
			else if (!component.playerHurtDisable)
			{
				component.playerHurtDisable = true;
				ShoppingCart.LogInfo("Set playerHurtDisable on '" + ((Object)cart).name + "' to match vanilla carts");
			}
		}

		private static void FixWheels(GameObject cart)
		{
			Rigidbody component = cart.GetComponent<Rigidbody>();
			int num = LayerMask.NameToLayer("PhysGrabObject");
			int num2 = ((num >= 0) ? num : cart.layer);
			int num3 = 0;
			Rigidbody[] componentsInChildren = cart.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)component))
				{
					GameObject gameObject = ((Component)val).gameObject;
					val.isKinematic = true;
					val.detectCollisions = false;
					Collider[] components = gameObject.GetComponents<Collider>();
					for (int j = 0; j < components.Length; j++)
					{
						Object.Destroy((Object)(object)components[j]);
					}
					Object.Destroy((Object)(object)val);
					gameObject.layer = num2;
					RestorePrefabLocalPose(cart, gameObject);
					num3++;
				}
			}
			if (num3 > 0)
			{
				ShoppingCart.LogInfo($"Fixed {num3} wheel(s) on '{((Object)cart).name}': removed child rigidbodies/colliders, layer -> {LayerMask.LayerToName(num2)}");
			}
		}

		private static void RestorePrefabLocalPose(GameObject cart, GameObject child)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)cartPrefab == (Object)null))
			{
				Transform val = cartPrefab.transform.Find(((Object)child).name);
				if (!((Object)(object)val == (Object)null))
				{
					child.transform.localPosition = val.localPosition;
					child.transform.localRotation = val.localRotation;
				}
			}
		}

		private static void GetDesiredSpawn(out Vector3 position, out Quaternion rotation)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0064: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: 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_0282: 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_01ef: 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_0225: 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_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: 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_0250: 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_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			Quaternion val = Quaternion.identity;
			ItemAttributes val2 = (((Object)(object)cartPrefab != (Object)null) ? cartPrefab.GetComponent<ItemAttributes>() : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.item != (Object)null)
			{
				Quaternion spawnRotationOffset = val2.item.spawnRotationOffset;
				val = ((spawnRotationOffset.x * spawnRotationOffset.x + spawnRotationOffset.y * spawnRotationOffset.y + spawnRotationOffset.z * spawnRotationOffset.z + spawnRotationOffset.w * spawnRotationOffset.w < 1E-06f) ? Quaternion.identity : Quaternion.Normalize(spawnRotationOffset));
			}
			int mask = LayerMask.GetMask(new string[3] { "PhysGrabObject", "PhysGrabObjectCart", "PhysGrabObjectHinge" });
			foreach (ShopSlotCapturePatch.Slot cartSlot in ShopSlotCapturePatch.CartSlots)
			{
				Collider[] array = Physics.OverlapSphere(cartSlot.Position + Vector3.up * 0.5f, 0.75f, mask, (QueryTriggerInteraction)1);
				bool flag = false;
				Collider[] array2 = array;
				foreach (Collider val3 in array2)
				{
					if ((Object)(object)val3 != (Object)null && (Object)(object)((Component)val3).GetComponentInParent<PhysGrabObject>() != (Object)null)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					position = cartSlot.Position;
					rotation = cartSlot.Rotation * val;
					ShoppingCart.LogInfo($"Using free shop cart slot at {position}");
					return;
				}
			}
			if (ShopSlotCapturePatch.CartSlots.Count > 0)
			{
				ShoppingCart.LogInfo($"All {ShopSlotCapturePatch.CartSlots.Count} shop cart slot(s) occupied; spawning near the player");
			}
			else
			{
				ShoppingCart.LogWarning("No shop cart slots captured on this map; spawning near the player");
			}
			PlayerAvatar instance = PlayerAvatar.instance;
			if ((Object)(object)instance != (Object)null)
			{
				Vector3 forward = ((Component)instance).transform.forward;
				forward.y = 0f;
				if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
				{
					forward = Vector3.forward;
				}
				((Vector3)(ref forward)).Normalize();
				position = ((Component)instance).transform.position + forward * 2f + Vector3.up * 0.5f;
				rotation = Quaternion.LookRotation(-forward, Vector3.up);
			}
			else
			{
				ShoppingCart.LogWarning("No local PlayerAvatar at spawn time; using fallback coordinates");
				position = FallbackSpawnPosition;
				rotation = Quaternion.identity;
			}
		}

		private static IEnumerator FixCartPositionAfterSpawn(GameObject cart, Vector3 targetPos, Quaternion targetRot)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			yield return null;
			if (!((Object)(object)cart == (Object)null) && !((Object)(object)LevelGenerator.Instance == (Object)null) && LevelGenerator.Instance.Generated)
			{
				PlaceCartSafely(cart, targetPos, targetRot, "spawn");
			}
		}

		internal static void PlaceCartSafely(GameObject cart, Vector3 desired, Quaternion rotation, string reason)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_002c: 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_01ed: 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_01c0: 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_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00d0: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0116: 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_00f1: 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_013a: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: 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)
			PhysGrabObject component = cart.GetComponent<PhysGrabObject>();
			if ((Object)(object)component == (Object)null)
			{
				ShoppingCart.LogWarning($"PlaceCartSafely({reason}): no PhysGrabObject on cart; leaving it at {desired}");
				cart.transform.SetPositionAndRotation(desired, rotation);
				return;
			}
			Vector3 halfExtents = component.boundingBox * 0.45f;
			Vector3 val = rotation * component.midPointOffset;
			float num = component.midPointOffset.y - component.boundingBox.y * 0.5f;
			Vector3? val2 = null;
			int num2 = 0;
			float[] placeSearchRadii = PlaceSearchRadii;
			RaycastHit val4 = default(RaycastHit);
			Vector3 val5 = default(Vector3);
			foreach (float num3 in placeSearchRadii)
			{
				int num4 = ((num3 <= 0f) ? 1 : 8);
				for (int j = 0; j < num4; j++)
				{
					if (val2.HasValue)
					{
						break;
					}
					float num5 = 360f * (float)j / (float)num4;
					Vector3 val3 = desired + Quaternion.Euler(0f, num5, 0f) * (Vector3.forward * num3);
					num2++;
					if ((!(num3 > 0f) || !Physics.Linecast(desired, val3, GroundMask, (QueryTriggerInteraction)1)) && Physics.Raycast(val3 + Vector3.up * 1f, Vector3.down, ref val4, 6f, GroundMask, (QueryTriggerInteraction)1))
					{
						((Vector3)(ref val5))..ctor(val3.x, ((RaycastHit)(ref val4)).point.y + 0.02f - num, val3.z);
						if (!OverlapsForeignSolid(cart.transform, val5 + val, halfExtents, rotation))
						{
							val2 = val5;
						}
					}
				}
				if (val2.HasValue)
				{
					break;
				}
			}
			if (!val2.HasValue)
			{
				ShoppingCart.LogWarning($"PlaceCartSafely({reason}): no free spot among {num2} candidates around {desired}; using it anyway");
				val2 = desired;
			}
			else
			{
				ShoppingCart.LogInfo($"PlaceCartSafely({reason}): placed at {val2.Value} after {num2} candidate(s), desired {desired}");
			}
			component.Teleport(val2.Value, rotation);
		}

		private static bool OverlapsForeignSolid(Transform self, Vector3 center, Vector3 halfExtents, Quaternion rotation)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapBox(center, halfExtents, rotation, SolidMask, (QueryTriggerInteraction)1);
			foreach (Collider val in array)
			{
				if (!((Object)(object)val == (Object)null) && !val.isTrigger && !((Component)val).transform.IsChildOf(self) && !((Object)(object)((Component)val).GetComponentInParent<PlayerController>() != (Object)null) && !((Object)(object)((Component)val).GetComponentInParent<PlayerAvatar>() != (Object)null))
				{
					return true;
				}
			}
			return false;
		}

		private static void InitializeCart(GameObject cart)
		{
		}

		private static void DisableVanillaCostUI(GameObject cart)
		{
			int num = 0;
			MonoBehaviour[] componentsInChildren = cart.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					switch (((object)val).GetType().Name)
					{
					case "WorldSpaceUIValue":
					case "ShopCostUI":
					case "CurrencyUI":
						((Behaviour)val).enabled = false;
						num++;
						break;
					}
				}
			}
			if (num > 0)
			{
				ShoppingCart.LogInfo($"Disabled {num} vanilla cost UI component(s) on spawned cart");
			}
		}
	}
	[BepInPlugin("Tolga.ShoppingCart", "ShoppingCart", "1.0.4")]
	public class ShoppingCart : BaseUnityPlugin
	{
		private float _nextMoveTime;

		internal static ShoppingCart Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		internal static ConfigEntry<float> CartWalkDistance { get; private set; }

		internal static ConfigEntry<float> CartSprintDistance { get; private set; }

		internal static ConfigEntry<float> CartTurnMultiplier { get; private set; }

		internal static ConfigEntry<float> CartTurnMinFactor { get; private set; }

		internal static ConfigEntry<float> CartTurnMaxClamp { get; private set; }

		internal static ConfigEntry<bool> CartDebugLogging { get; private set; }

		internal static ConfigEntry<bool> CartPriceDebugLogging { get; private set; }

		internal static ConfigEntry<bool> CartValueDebugLogging { get; private set; }

		internal static ConfigEntry<bool> CartCostPopupDebugLogging { get; private set; }

		internal static ConfigEntry<bool> CartSteerDebugLogging { get; private set; }

		internal static ConfigEntry<bool> CartInfoLogging { get; private set; }

		internal static ConfigEntry<bool> CartWarningLogging { get; private set; }

		internal static ConfigEntry<bool> CartErrorLogging { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> MoveCartKey { get; private set; }

		internal static bool AnyInfoLoggingEnabled
		{
			get
			{
				if (!IsEnabled(CartInfoLogging) && !IsEnabled(CartDebugLogging) && !IsEnabled(CartPriceDebugLogging) && !IsEnabled(CartValueDebugLogging) && !IsEnabled(CartCostPopupDebugLogging))
				{
					return IsEnabled(CartSteerDebugLogging);
				}
				return true;
			}
		}

		internal static bool AnyWarningLoggingEnabled
		{
			get
			{
				if (!IsEnabled(CartWarningLogging))
				{
					return IsEnabled(CartDebugLogging);
				}
				return true;
			}
		}

		internal static bool AnyErrorLoggingEnabled
		{
			get
			{
				if (!IsEnabled(CartErrorLogging))
				{
					return IsEnabled(CartDebugLogging);
				}
				return true;
			}
		}

		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			BindConfig();
			LogInfo($"Config: InfoLogging={CartInfoLogging.Value}, WarningLogging={CartWarningLogging.Value}, ErrorLogging={CartErrorLogging.Value}, DebugLogging={CartDebugLogging.Value}, PriceDebugLogging={CartPriceDebugLogging.Value}, ValueDebugLogging={CartValueDebugLogging.Value}, CostPopupDebugLogging={CartCostPopupDebugLogging.Value}, SteerDebugLogging={CartSteerDebugLogging.Value}");
			Patch();
			LogInfo($"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		private void BindConfig()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			AcceptableValueRange<float> val = new AcceptableValueRange<float>(0.7f, 4f);
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				Increment = 0.01f
			};
			CartWalkDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "WalkDistance", 1.1f, new ConfigDescription("How far the cart stays from you while walking.", (AcceptableValueBase)(object)val, new object[1] { configurationManagerAttributes }));
			CartSprintDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "SprintDistance", 1.75f, new ConfigDescription("How far the cart stays from you while sprinting (and moving forward with the cart).", (AcceptableValueBase)(object)val, new object[1] { configurationManagerAttributes }));
			CartTurnMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "TurnMultiplier", 20f, "Turn speed multiplier used when steering the cart.");
			CartTurnMinFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "TurnMinFactor", 0.2f, "Minimum turning factor clamp (vanilla is 0.2). Higher = more responsive at small angles.");
			CartTurnMaxClamp = ((BaseUnityPlugin)this).Config.Bind<float>("Cart", "TurnMaxClamp", 4f, "Maximum turn clamp used for angular velocity (vanilla is 4). Higher = faster snap turns.");
			CartDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "DebugLogging", false, "Enable verbose debug logging for cart patches.");
			CartPriceDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "PriceDebugLogging", false, "Enable verbose debug logging for cart price display.");
			CartValueDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "ValueDebugLogging", false, "Enable debug logging for cart item scanning and total calculation.");
			CartCostPopupDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "CostPopupDebugLogging", false, "Enable debug logging for WorldSpaceUIValue (the '-$...K' popup) suppression.");
			CartSteerDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "SteerDebugLogging", false, "Enable debug logging for CartSteer distance/turn calculations.");
			CartInfoLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "InfoLogging", false, "Enable informational logs from the mod.");
			CartWarningLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "WarningLogging", false, "Enable warning logs from the mod.");
			CartErrorLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Cart", "ErrorLogging", false, "Enable error logs from the mod.");
			MoveCartKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Cart", "MoveCartKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Brings the shopping cart to the spot you are looking at (shop only). Set to None to disable.");
		}

		private static bool IsEnabled(ConfigEntry<bool>? entry)
		{
			return entry?.Value ?? false;
		}

		internal static void LogInfo(string message)
		{
			if (AnyInfoLoggingEnabled)
			{
				Logger.LogInfo((object)message);
			}
		}

		internal static void LogWarning(string message)
		{
			if (AnyWarningLoggingEnabled)
			{
				Logger.LogWarning((object)message);
			}
		}

		internal static void LogError(string message)
		{
			if (AnyErrorLoggingEnabled)
			{
				Logger.LogError((object)message);
			}
		}

		internal void Patch()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			int num = 0;
			int num2 = 0;
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
			foreach (Type type in typesFromAssembly)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0)
				{
					try
					{
						Harmony.CreateClassProcessor(type).Patch();
						num++;
					}
					catch (Exception arg)
					{
						num2++;
						Logger.LogError((object)$"Harmony patch class {type.FullName} failed to apply: {arg}");
					}
				}
			}
			if (num2 > 0)
			{
				Logger.LogError((object)$"Harmony: {num} patch class(es) applied, {num2} FAILED. The mod is partially active.");
			}
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)RunManager.instance == (Object)null) && SemiFunc.RunIsShop())
			{
				KeyboardShortcut value = MoveCartKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && Time.time >= _nextMoveTime)
				{
					_nextMoveTime = Time.time + 0.25f;
					LogInfo("MoveCartKey pressed - triggering MoveCartToLook()");
					MoveCartToLook();
				}
			}
		}

		private Camera? GetBestCamera()
		{
			if (Object.op_Implicit((Object)(object)Camera.main) && ((Behaviour)Camera.main).isActiveAndEnabled)
			{
				return Camera.main;
			}
			Camera val = ((IEnumerable<Camera>)Object.FindObjectsOfType<Camera>()).FirstOrDefault((Func<Camera, bool>)((Camera c) => ((Behaviour)c).isActiveAndEnabled && ((Component)c).CompareTag("MainCamera")));
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Camera? obj = ((IEnumerable<Camera>)Object.FindObjectsOfType<Camera>()).FirstOrDefault((Func<Camera, bool>)((Camera c) => ((Behaviour)c).isActiveAndEnabled));
			if ((Object)(object)obj == (Object)null)
			{
				LogWarning("No active camera found!");
			}
			return obj;
		}

		private void MoveCartToLook()
		{
			//IL_005d: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			Camera bestCamera = GetBestCamera();
			if ((Object)(object)bestCamera == (Object)null)
			{
				LogWarning("F8: No active camera found");
				return;
			}
			GameObject val = ShopCartSpawner.LatestSpawnedCart;
			if ((Object)(object)val == (Object)null)
			{
				val = GameObject.Find("Shopping Cart(Clone)") ?? GameObject.Find("shopping_cart(Clone)");
			}
			if ((Object)(object)val == (Object)null)
			{
				LogWarning("F8 pressed but shopping_cart(Clone) not found. Cart may not have spawned yet.");
				return;
			}
			Vector3 position = ((Component)bestCamera).transform.position;
			Vector3 forward = ((Component)bestCamera).transform.forward;
			float num = 2f;
			float num2 = 3f;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(position, forward, ref val2, num2, -1, (QueryTriggerInteraction)1))
			{
				num = Mathf.Clamp(((RaycastHit)(ref val2)).distance - 0.4f, 0.8f, 2f);
				LogInfo($"F8: Raycast hit '{((Object)((RaycastHit)(ref val2)).collider).name}' at {((RaycastHit)(ref val2)).distance:F2}m, placing at {num:F2}m");
			}
			Vector3 desired = position + forward * num;
			ShopCartSpawner.PlaceCartSafely(val, desired, Quaternion.Euler(0f, ((Component)bestCamera).transform.eulerAngles.y, 0f), "F8");
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public float? Increment { get; set; }
	}
	[HarmonyPatch(typeof(ShopManager), "ShoppingListItemAdd")]
	internal static class ShoppingListPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemAttributes item)
		{
			if ((Object)(object)item == (Object)null || !ShopCartSpawner.IsModCart(((Component)item).gameObject))
			{
				return true;
			}
			ShoppingCart.LogInfo("Mod cart entered the extraction area; not adding it to the shopping list");
			return false;
		}
	}
	[HarmonyPatch(typeof(PunManager), "ShopPopulateItemVolumes")]
	internal static class ShopSlotCapturePatch
	{
		internal readonly struct Slot
		{
			public readonly Vector3 Position;

			public readonly Quaternion Rotation;

			public Slot(Vector3 position, Quaternion rotation)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: 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)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Position = position;
				Rotation = rotation;
			}
		}

		internal const itemVolume CartVolumeType = (itemVolume)3;

		internal static readonly List<Slot> CartSlots = new List<Slot>();

		[HarmonyPrefix]
		private static void Prefix()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Invalid comparison between Unknown and I4
			//IL_0055: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CartSlots.Clear();
				if ((Object)(object)ShopManager.instance == (Object)null || ShopManager.instance.itemVolumes == null)
				{
					return;
				}
				foreach (ItemVolume itemVolume in ShopManager.instance.itemVolumes)
				{
					if (!((Object)(object)itemVolume == (Object)null) && (int)itemVolume.itemVolume == 3 && (int)itemVolume.itemSecretShopType == 0)
					{
						CartSlots.Add(new Slot(((Component)itemVolume).transform.position, ((Component)itemVolume).transform.rotation));
					}
				}
				ShoppingCart.LogInfo($"Captured {CartSlots.Count} shop cart slot(s) of type {(object)(itemVolume)3}");
			}
			catch (Exception ex)
			{
				CartSlots.Clear();
				ShoppingCart.LogError("ShopSlotCapturePatch failed: " + ex.GetType().Name + ": " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(WorldSpaceUIValue), "Show", new Type[]
	{
		typeof(PhysGrabObject),
		typeof(int),
		typeof(bool),
		typeof(Vector3)
	})]
	internal static class WorldSpaceUIValuePatch
	{
		private static float _nextCostPopupDebugTime;

		[HarmonyPrefix]
		private static bool Prefix(PhysGrabObject _grabObject, int _value, bool _cost)
		{
			if ((Object)(object)_grabObject == (Object)null)
			{
				return true;
			}
			bool flag = ShopCartSpawner.IsModCart(((Component)_grabObject).gameObject);
			if (ShoppingCart.CartCostPopupDebugLogging.Value && Time.unscaledTime >= _nextCostPopupDebugTime)
			{
				ShoppingCart.LogInfo(string.Format("[CostPopup] Show(value={0}, cost={1}) grab='{2}' => {3}", _value, _cost, ((Object)((Component)_grabObject).gameObject).name, flag ? "BLOCK" : "ALLOW"));
				_nextCostPopupDebugTime = Time.unscaledTime + 1f;
			}
			return !flag;
		}
	}
}