Decompiled source of ObjectDropLaser v1.1.5

ObjectDropLaserMod.dll

Decompiled 3 months 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.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ObjectDropLaserMod.Components;
using ObjectDropLaserMod.GrabDetection;
using ObjectDropLaserMod.Patches;
using ObjectDropLaserMod.Systems;
using ObjectDropLaserMod.Utils;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ObjectDropLaserMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+bfefc7cb04246bdb1169ab9baaa5193d4862c04a")]
[assembly: AssemblyProduct("ObjectDropLaserMod")]
[assembly: AssemblyTitle("ObjectDropLaserMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ObjectDropLaserMod
{
	[BepInPlugin("com.repo.droplaser", "Drop Laser Mod", "1.0.9")]
	public class Plugin : BaseUnityPlugin
	{
		private const string ConfigSchemaVersion = "2026-05-10.2";

		public static ManualLogSource log;

		public static ConfigEntry<bool> EnableLogging;

		public static ConfigEntry<bool> EnableLaser;

		public static ConfigEntry<bool> UseCustomColor;

		public static ConfigEntry<Color> CustomLaserColor;

		public static ConfigEntry<float> LaserStartWidth;

		public static ConfigEntry<float> LaserEndWidth;

		public static ConfigEntry<float> LaserMaxDistance;

		public static ConfigEntry<float> LaserLightIntensity;

		public static ConfigEntry<float> LaserLightRange;

		public static ConfigEntry<string> ToggleLaserKey;

		public static ConfigEntry<bool> AutoEnableOnGrab;

		public static ConfigEntry<bool> EnableDropBeamInnerWhite;

		public static ConfigEntry<int> GhostPreviewMode;

		public static ConfigEntry<bool> UseCustomGhostColor;

		public static ConfigEntry<Color> CustomGhostColor;

		public static ConfigEntry<float> GhostOpacity;

		public static ConfigEntry<float> GhostEmissionIntensity;

		public static ConfigEntry<int> GhostUpdateFrameInterval;

		public static ConfigEntry<string> HighlightCycleForwardKey;

		public static ConfigEntry<string> HighlightCycleBackwardKey;

		public static ConfigEntry<string> DebugStopOverrideKey;

		public static ConfigEntry<bool> EnableDebugVisuals;

		public static ConfigEntry<bool> EnableHitDiagnostics;

		public static ConfigEntry<string> AppliedConfigSchemaVersion;

		public static ConfigEntry<string> PendingMigrationBackupPath;

		private void Awake()
		{
			log = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, (string)null);
			log.LogInfo((object)"[DropLaser] Harmony patches applied.");
			BindGeneralConfig();
			BindLaserConfig();
			BindInternalConfig();
			ConfigMigrationService.ApplyIfOutdated(((BaseUnityPlugin)this).Config, AppliedConfigSchemaVersion, PendingMigrationBackupPath, "2026-05-10.2", log);
		}

		private void BindGeneralConfig()
		{
			EnableLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableLogging", false, "Enable detailed log output (disable for cleaner console)");
		}

		private void BindLaserConfig()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			EnableLaser = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableLaser", true, "Master toggle for enabling/disabling the laser.");
			UseCustomColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "UseCustomColor", false, "If true, forces the laser to use a custom color instead of copying the beam's color.");
			CustomLaserColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Laser Settings", "CustomLaserColor", Color.red, "The color the laser will use if UseCustomColor is true.");
			LaserStartWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserStartWidth", 0.04f, "The width of the laser at its start.");
			LaserEndWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserEndWidth", 0.03f, "The width of the laser at its end.");
			LaserMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserMaxDistance", 500f, "Maximum distance the laser can scan downward.");
			LaserLightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserLightIntensity", 5.5f, "Intensity (brightness) of the laser glow light.");
			LaserLightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserLightRange", 0.5f, "Range (radius) of the laser glow light.");
			ToggleLaserKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "ToggleLaserKey", "L", "Key to press for toggling the laser on/off.");
			AutoEnableOnGrab = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "AutoEnableOnGrab", true, "If true, the laser will automatically enable when the player grabs an object.");
			EnableDropBeamInnerWhite = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableDropBeamInnerWhite", true, "If true, shows a white inner core in the drop beam when above cart bounds.");
			GhostPreviewMode = ((BaseUnityPlugin)this).Config.Bind<int>("Laser Settings", "GhostPreviewMode", 1, "Ghost preview behavior: 0 = never, 1 = on cart, 2 = always.");
			UseCustomGhostColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "UseCustomGhostColor", false, "If true, the ghost preview uses CustomGhostColor instead of laser color.");
			CustomGhostColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Laser Settings", "CustomGhostColor", new Color(0f, 1f, 1f, 1f), "Ghost preview tint color when UseCustomGhostColor is true.");
			GhostOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "GhostOpacity", 0.35f, "Ghost preview opacity from 0.0 (invisible) to 1.0 (solid).");
			GhostEmissionIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "GhostEmissionIntensity", 0.6f, "Ghost preview emission intensity multiplier.");
			GhostUpdateFrameInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Laser Settings", "GhostUpdateFrameInterval", 1, "Number of frames between ghost position updates. Higher values reduce update frequency.");
			HighlightCycleForwardKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "HighlightCycleForwardKey", "UpArrow", "Key used in debug mode to cycle cart highlight layers forward.");
			HighlightCycleBackwardKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "HighlightCycleBackwardKey", "DownArrow", "Key used in debug mode to cycle cart highlight layers backward.");
			DebugStopOverrideKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "DebugStopOverrideKey", "Return", "Debug-only key that temporarily changes laser/ghost stop behavior while held.");
			EnableDebugVisuals = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableDebugVisuals", true, "If true, allows debug visualizers/highlighters when debug mode is active.");
			EnableHitDiagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableHitDiagnostics", false, "If true, emits periodic hit diagnostics and stop-selection logs.");
		}

		private void BindInternalConfig()
		{
			AppliedConfigSchemaVersion = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "AppliedConfigSchemaVersion", "2026-05-10.2", "");
			PendingMigrationBackupPath = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "PendingMigrationBackupPath", string.Empty, "");
		}
	}
}
namespace ObjectDropLaserMod.Utils
{
	public static class CartStateAccessors
	{
		private const float CartVolumeRefreshIntervalSeconds = 0.25f;

		private static readonly Type PhysGrabInCartType = AccessTools.TypeByName("PhysGrabInCart");

		private static readonly FieldInfo InCartObjectsField = ((PhysGrabInCartType != null) ? AccessTools.Field(PhysGrabInCartType, "inCartObjects") : null);

		private static readonly Type CartObjectType = AccessTools.TypeByName("PhysGrabInCart+CartObject");

		private static readonly FieldInfo CartObjectPhysGrabObjectField = ((CartObjectType != null) ? AccessTools.Field(CartObjectType, "physGrabObject") : null);

		private static readonly Type PhysGrabCartType = AccessTools.TypeByName("PhysGrabCart");

		private static readonly FieldInfo PhysGrabCartInCartField = ((PhysGrabCartType != null) ? AccessTools.Field(PhysGrabCartType, "inCart") : null);

		private static readonly List<BoxCollider> CachedCartInCartVolumes = new List<BoxCollider>();

		private static float nextCartVolumeRefreshTime;

		public static bool IsObjectTrackedInCart(PhysGrabObject heldObject)
		{
			if ((Object)(object)heldObject == (Object)null || InCartObjectsField == null || CartObjectPhysGrabObjectField == null)
			{
				return false;
			}
			Object val = Object.FindObjectOfType(PhysGrabInCartType);
			if (val == (Object)null)
			{
				return false;
			}
			if (!(InCartObjectsField.GetValue(val) is IEnumerable enumerable))
			{
				return false;
			}
			foreach (object item in enumerable)
			{
				if (item != null && (Object)/*isinst with value type is only supported in some contexts*/ == (Object)(object)heldObject)
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsGameObjectTrackedInCart(GameObject hitObject)
		{
			if ((Object)(object)hitObject == (Object)null)
			{
				return false;
			}
			PhysGrabObject componentInParent = hitObject.GetComponentInParent<PhysGrabObject>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				return false;
			}
			return IsObjectTrackedInCart(componentInParent);
		}

		public static bool IsPointInsideAnyCartInCartBounds(Vector3 point)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			RefreshCartVolumeCacheIfNeeded();
			for (int i = 0; i < CachedCartInCartVolumes.Count; i++)
			{
				BoxCollider val = CachedCartInCartVolumes[i];
				if ((Object)(object)val != (Object)null)
				{
					Bounds bounds = ((Collider)val).bounds;
					if (((Bounds)(ref bounds)).Contains(point))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool IsPointAboveAnyCartInCartBounds(Vector3 point)
		{
			//IL_0025: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			RefreshCartVolumeCacheIfNeeded();
			for (int i = 0; i < CachedCartInCartVolumes.Count; i++)
			{
				BoxCollider val = CachedCartInCartVolumes[i];
				if (!((Object)(object)val == (Object)null))
				{
					Bounds bounds = ((Collider)val).bounds;
					bool num = point.x >= ((Bounds)(ref bounds)).min.x && point.x <= ((Bounds)(ref bounds)).max.x;
					bool flag = point.z >= ((Bounds)(ref bounds)).min.z && point.z <= ((Bounds)(ref bounds)).max.z;
					bool flag2 = point.y >= ((Bounds)(ref bounds)).max.y;
					if (num && flag && flag2)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void RefreshCartVolumeCacheIfNeeded()
		{
			if (Time.time < nextCartVolumeRefreshTime)
			{
				return;
			}
			nextCartVolumeRefreshTime = Time.time + 0.25f;
			CachedCartInCartVolumes.Clear();
			if (PhysGrabCartType == null || PhysGrabCartInCartField == null)
			{
				return;
			}
			Object[] array = Object.FindObjectsOfType(PhysGrabCartType);
			foreach (object obj in array)
			{
				if (obj == null)
				{
					continue;
				}
				object? value = PhysGrabCartInCartField.GetValue(obj);
				Transform val = (Transform)((value is Transform) ? value : null);
				if (!((Object)(object)val == (Object)null))
				{
					BoxCollider component = ((Component)val).GetComponent<BoxCollider>();
					if ((Object)(object)component != (Object)null)
					{
						CachedCartInCartVolumes.Add(component);
					}
				}
			}
		}
	}
	internal static class ConfigMigrationService
	{
		public static void ApplyIfOutdated(ConfigFile configFile, ConfigEntry<string> appliedSchemaVersion, ConfigEntry<string> pendingBackupPath, string targetSchemaVersion, ManualLogSource logger)
		{
			if (configFile == null || appliedSchemaVersion == null || pendingBackupPath == null || string.IsNullOrWhiteSpace(targetSchemaVersion))
			{
				return;
			}
			string text = appliedSchemaVersion.Value ?? string.Empty;
			bool flag = FileContainsSchemaMarker(configFile.ConfigFilePath);
			bool num = string.Equals(text, targetSchemaVersion, StringComparison.Ordinal);
			if (num)
			{
				TryFinalizePreviousMigrationBackup(configFile, pendingBackupPath, logger);
			}
			if (!(num && flag))
			{
				string text2 = (string.IsNullOrWhiteSpace(text) ? "<none>" : text);
				if (logger != null)
				{
					logger.LogInfo((object)("[DropLaser][ConfigMigration] Updating config schema from " + text2 + " to " + targetSchemaVersion + "."));
				}
				string text3 = TryCreateBackup(configFile.ConfigFilePath, logger);
				pendingBackupPath.Value = text3 ?? string.Empty;
				appliedSchemaVersion.Value = targetSchemaVersion;
				configFile.Save();
				if (logger != null)
				{
					logger.LogInfo((object)"[DropLaser][ConfigMigration] Config migration complete.");
				}
			}
		}

		private static string TryCreateBackup(string configPath, ManualLogSource logger)
		{
			if (string.IsNullOrWhiteSpace(configPath) || !File.Exists(configPath))
			{
				return null;
			}
			try
			{
				string directoryName = Path.GetDirectoryName(configPath);
				string? fileName = Path.GetFileName(configPath);
				string text = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss");
				string text2 = fileName + ".bak-" + text;
				string text3 = (string.IsNullOrWhiteSpace(directoryName) ? text2 : Path.Combine(directoryName, text2));
				File.Copy(configPath, text3, overwrite: false);
				if (logger != null)
				{
					logger.LogInfo((object)("[DropLaser][ConfigMigration] Backup created: " + text3));
				}
				return text3;
			}
			catch (Exception ex)
			{
				if (logger != null)
				{
					logger.LogWarning((object)("[DropLaser][ConfigMigration] Failed to create config backup: " + ex.Message));
				}
				return null;
			}
		}

		private static void TryFinalizePreviousMigrationBackup(ConfigFile configFile, ConfigEntry<string> pendingBackupPath, ManualLogSource logger)
		{
			string text = pendingBackupPath.Value ?? string.Empty;
			if (string.IsNullOrWhiteSpace(text))
			{
				return;
			}
			try
			{
				if (File.Exists(text))
				{
					File.Delete(text);
					if (logger != null)
					{
						logger.LogInfo((object)("[DropLaser][ConfigMigration] Removed migration backup after successful load: " + text));
					}
				}
				else if (logger != null)
				{
					logger.LogInfo((object)("[DropLaser][ConfigMigration] Pending backup already missing (treated as clean): " + text));
				}
			}
			catch (Exception ex)
			{
				if (logger != null)
				{
					logger.LogWarning((object)("[DropLaser][ConfigMigration] Failed to remove migration backup: " + ex.Message));
				}
				return;
			}
			pendingBackupPath.Value = string.Empty;
			configFile.Save();
		}

		private static bool FileContainsSchemaMarker(string configPath)
		{
			if (string.IsNullOrWhiteSpace(configPath) || !File.Exists(configPath))
			{
				return false;
			}
			try
			{
				return File.ReadAllText(configPath).IndexOf("AppliedConfigSchemaVersion", StringComparison.Ordinal) >= 0;
			}
			catch
			{
				return false;
			}
		}
	}
	public static class DropLaserInputHelper
	{
		public static bool IsConfiguredKeyDown(string configuredKey)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParseKey(configuredKey, out var keyCode))
			{
				return false;
			}
			return Input.GetKeyDown(keyCode);
		}

		public static bool IsConfiguredKeyHeld(string configuredKey)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!TryParseKey(configuredKey, out var keyCode))
			{
				return false;
			}
			return Input.GetKey(keyCode);
		}

		public static bool TryParseKey(string configuredKey, out KeyCode keyCode)
		{
			keyCode = (KeyCode)0;
			if (string.IsNullOrWhiteSpace(configuredKey))
			{
				return false;
			}
			return Enum.TryParse<KeyCode>(configuredKey, ignoreCase: true, out keyCode);
		}
	}
	public static class DropLaserLogger
	{
		public static void Info(string message)
		{
			if (Plugin.EnableLogging.Value)
			{
				Plugin.log.LogInfo((object)message);
			}
		}

		public static void Warning(string message)
		{
			if (Plugin.EnableLogging.Value)
			{
				Plugin.log.LogWarning((object)message);
			}
		}

		public static void Error(string message)
		{
			Plugin.log.LogError((object)message);
		}
	}
	public static class PhysGrabberAccessors
	{
		private static readonly FieldInfo grabbedObjField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject");

		private static readonly FieldInfo beamField = AccessTools.Field(typeof(PhysGrabber), "physGrabBeam");

		public static PhysGrabObject GetGrabbedObject(this PhysGrabber instance)
		{
			object? value = grabbedObjField.GetValue(instance);
			return (PhysGrabObject)((value is PhysGrabObject) ? value : null);
		}

		public static GameObject GetBeamObject(this PhysGrabber instance)
		{
			object? value = beamField.GetValue(instance);
			return (GameObject)((value is GameObject) ? value : null);
		}
	}
}
namespace ObjectDropLaserMod.Systems
{
	public sealed class DropLaserBeamDebugService
	{
		private const float DoublePressWindowSeconds = 0.35f;

		private readonly DropLaserCartDebugVisualizer cartDebugVisualizer;

		private readonly DropLaserCartPartHighlighter cartPartHighlighter;

		private bool cartDebugModeActive;

		private float lastDebugTogglePressTime = -999f;

		private bool debugStopOverrideLoggedActive;

		private bool debugVisualsWereRunning;

		public bool IsDebugModeActive => cartDebugModeActive;

		public DropLaserBeamDebugService()
		{
			cartDebugVisualizer = new DropLaserCartDebugVisualizer();
			cartPartHighlighter = new DropLaserCartPartHighlighter();
		}

		public void Tick()
		{
			if (!AreDebugSystemsEnabled())
			{
				ForceDisableDebugSystems();
				return;
			}
			UpdateDebugModeToggle();
			UpdateDebugStopOverrideLogState();
			bool flag = ShouldRunDebugVisuals();
			if (flag)
			{
				cartPartHighlighter.Update();
			}
			else if (debugVisualsWereRunning)
			{
				cartPartHighlighter.Dispose();
			}
			debugVisualsWereRunning = flag;
		}

		public void RenderBeamHits(Vector3 beamStart, RaycastHit[] hitBuffer, int hitCount, PhysGrabObject heldObject)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (!AreDebugSystemsEnabled())
			{
				cartDebugVisualizer.Hide();
			}
			else if (ShouldRunDebugVisuals())
			{
				cartDebugVisualizer.RenderHits(beamStart, hitBuffer, hitCount, heldObject);
			}
			else
			{
				cartDebugVisualizer.Hide();
			}
		}

		public bool IsDebugStopOverrideActive()
		{
			if (!AreDebugSystemsEnabled())
			{
				return false;
			}
			if (!cartDebugModeActive)
			{
				return false;
			}
			return DropLaserInputHelper.IsConfiguredKeyHeld(Plugin.DebugStopOverrideKey.Value);
		}

		public void HideVisuals()
		{
			cartDebugVisualizer.Hide();
		}

		public void Dispose()
		{
			cartDebugVisualizer.Dispose();
			cartPartHighlighter.Dispose();
			debugVisualsWereRunning = false;
		}

		private void UpdateDebugModeToggle()
		{
			if (!AreDebugSystemsEnabled() || !DropLaserInputHelper.IsConfiguredKeyDown(Plugin.DebugStopOverrideKey.Value))
			{
				return;
			}
			if (Time.time - lastDebugTogglePressTime <= 0.35f)
			{
				cartDebugModeActive = !cartDebugModeActive;
				lastDebugTogglePressTime = -999f;
				if (!cartDebugModeActive)
				{
					cartPartHighlighter.Dispose();
					cartDebugVisualizer.Hide();
				}
				Plugin.log.LogWarning((object)("[DropLaser] Cart debug mode is now " + (cartDebugModeActive ? "ENABLED" : "DISABLED") + "."));
			}
			else
			{
				lastDebugTogglePressTime = Time.time;
			}
		}

		private void UpdateDebugStopOverrideLogState()
		{
			if (AreDebugSystemsEnabled() && Plugin.EnableHitDiagnostics.Value)
			{
				bool flag = IsDebugStopOverrideActive();
				if (flag != debugStopOverrideLoggedActive)
				{
					debugStopOverrideLoggedActive = flag;
					DropLaserLogger.Info("[DropLaser] Debug stop override (hold " + Plugin.DebugStopOverrideKey.Value + ") is now " + (flag ? "ACTIVE" : "INACTIVE") + ".");
				}
			}
		}

		private bool ShouldRunDebugVisuals()
		{
			if (AreDebugSystemsEnabled() && cartDebugModeActive)
			{
				return Plugin.EnableDebugVisuals.Value;
			}
			return false;
		}

		private static bool AreDebugSystemsEnabled()
		{
			return Plugin.EnableLogging.Value;
		}

		private void ForceDisableDebugSystems()
		{
			cartDebugModeActive = false;
			debugStopOverrideLoggedActive = false;
			debugVisualsWereRunning = false;
			cartPartHighlighter.Dispose();
			cartDebugVisualizer.Hide();
		}
	}
	public sealed class DropLaserCartDebugVisualizer
	{
		private const int MaxDebugLines = 64;

		private const float LineWidth = 0.01f;

		private readonly int physGrabObjectCartLayer;

		private readonly int cartWheelsLayer;

		private readonly int physGrabObjectTriggerLayer;

		private readonly LineRenderer[] linePool = (LineRenderer[])(object)new LineRenderer[64];

		private readonly GameObject root;

		public DropLaserCartDebugVisualizer()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			physGrabObjectCartLayer = LayerMask.NameToLayer("PhysGrabObjectCart");
			cartWheelsLayer = LayerMask.NameToLayer("CartWheels");
			physGrabObjectTriggerLayer = LayerMask.NameToLayer("PhysGrabObjectTrigger");
			root = new GameObject("DropLaserCartDebugVisualizer");
			Object.DontDestroyOnLoad((Object)(object)root);
			root.SetActive(false);
		}

		public void RenderHits(Vector3 origin, RaycastHit[] hits, int hitCount, PhysGrabObject heldObject)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null || hits == null || hitCount <= 0)
			{
				Hide();
				return;
			}
			root.SetActive(true);
			int num = 0;
			for (int i = 0; i < hitCount; i++)
			{
				if (num >= 64)
				{
					break;
				}
				RaycastHit val = hits[i];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null))
				{
					LineRenderer orCreateLine = GetOrCreateLine(num);
					num++;
					Color endColor = (orCreateLine.startColor = ClassifyColor(((Component)((RaycastHit)(ref val)).collider).gameObject, heldObject));
					orCreateLine.endColor = endColor;
					orCreateLine.SetPosition(0, origin);
					orCreateLine.SetPosition(1, ((RaycastHit)(ref val)).point);
					((Renderer)orCreateLine).enabled = true;
				}
			}
			for (int j = num; j < 64; j++)
			{
				if ((Object)(object)linePool[j] != (Object)null)
				{
					((Renderer)linePool[j]).enabled = false;
				}
			}
		}

		public void Hide()
		{
			if ((Object)(object)root != (Object)null)
			{
				root.SetActive(false);
			}
		}

		public void Dispose()
		{
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
		}

		private LineRenderer GetOrCreateLine(int index)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			if ((Object)(object)linePool[index] != (Object)null)
			{
				return linePool[index];
			}
			GameObject val = new GameObject("DropLaserDebugHitLine_" + index);
			val.transform.SetParent(root.transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			val2.useWorldSpace = true;
			val2.textureMode = (LineTextureMode)0;
			val2.positionCount = 2;
			val2.numCapVertices = 4;
			val2.numCornerVertices = 2;
			val2.startWidth = 0.01f;
			val2.endWidth = 0.01f;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			((Renderer)val2).enabled = false;
			Shader val3 = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
			if ((Object)(object)val3 != (Object)null)
			{
				Material material = new Material(val3);
				((Renderer)val2).material = material;
			}
			linePool[index] = val2;
			return val2;
		}

		private Color ClassifyColor(GameObject hitObject, PhysGrabObject heldObject)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			if ((Object)(object)hitObject == (Object)null)
			{
				return Color.white;
			}
			if (IsPartOfHeldObject(hitObject, heldObject))
			{
				return Color.gray;
			}
			if (hitObject.CompareTag("Cart"))
			{
				return Color.green;
			}
			int layer = hitObject.layer;
			if (physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer)
			{
				return Color.green;
			}
			if (physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer)
			{
				return new Color(1f, 0.5f, 0f);
			}
			if (cartWheelsLayer >= 0 && layer == cartWheelsLayer)
			{
				return Color.yellow;
			}
			return Color.cyan;
		}

		private static bool IsPartOfHeldObject(GameObject candidate, PhysGrabObject heldObject)
		{
			if ((Object)(object)candidate == (Object)null || (Object)(object)heldObject == (Object)null)
			{
				return false;
			}
			Transform val = candidate.transform;
			Transform transform = ((Component)heldObject).transform;
			while ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val == (Object)(object)transform)
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}
	}
	public sealed class DropLaserCartPartHighlighter
	{
		private enum HighlightCategory
		{
			InCartTrigger,
			CartBody,
			CartWheels,
			OtherCart
		}

		public enum HighlightMode
		{
			All,
			InCartOnly,
			CartBodyOnly,
			CartWheelsOnly,
			OtherCartOnly
		}

		private readonly Dictionary<Collider, GameObject> markersByCollider = new Dictionary<Collider, GameObject>();

		private readonly HashSet<Collider> liveColliders = new HashSet<Collider>();

		private readonly int physGrabObjectCartLayer;

		private readonly int cartWheelsLayer;

		private readonly int physGrabObjectTriggerLayer;

		private readonly Shader debugShader;

		private float nextRefreshTime;

		private HighlightMode currentMode;

		public static HighlightMode ActiveMode { get; private set; }

		public static bool IsGameObjectHighlightedForCurrentMode(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			if (!TryGetCategoryForGameObject(gameObject, out var category))
			{
				return false;
			}
			return ShouldShowCategoryStatic(category, ActiveMode);
		}

		public static bool IsGameObjectCartBody(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			if (!TryGetCategoryForGameObject(gameObject, out var category))
			{
				return false;
			}
			return category == HighlightCategory.CartBody;
		}

		public DropLaserCartPartHighlighter()
		{
			physGrabObjectCartLayer = LayerMask.NameToLayer("PhysGrabObjectCart");
			cartWheelsLayer = LayerMask.NameToLayer("CartWheels");
			physGrabObjectTriggerLayer = LayerMask.NameToLayer("PhysGrabObjectTrigger");
			debugShader = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color");
		}

		public void Update()
		{
			HandleCycleInput();
			if (Time.time >= nextRefreshTime)
			{
				nextRefreshTime = Time.time + 0.5f;
				RebuildColliderSet();
			}
			UpdateMarkerTransforms();
		}

		public void Dispose()
		{
			ClearAllMarkers();
		}

		private void RebuildColliderSet()
		{
			liveColliders.Clear();
			PhysGrabCart[] array = Object.FindObjectsOfType<PhysGrabCart>();
			foreach (PhysGrabCart val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true);
				foreach (Collider val2 in componentsInChildren)
				{
					if ((Object)(object)val2 == (Object)null || !ShouldHighlight(val2))
					{
						continue;
					}
					liveColliders.Add(val2);
					if (!markersByCollider.ContainsKey(val2))
					{
						GameObject val3 = CreateMarkerForCollider(val2);
						if ((Object)(object)val3 != (Object)null)
						{
							markersByCollider[val2] = val3;
						}
					}
				}
			}
			List<Collider> list = new List<Collider>();
			foreach (KeyValuePair<Collider, GameObject> item in markersByCollider)
			{
				if ((Object)(object)item.Key == (Object)null || !liveColliders.Contains(item.Key))
				{
					if ((Object)(object)item.Value != (Object)null)
					{
						Object.Destroy((Object)(object)item.Value);
					}
					list.Add(item.Key);
				}
			}
			for (int k = 0; k < list.Count; k++)
			{
				markersByCollider.Remove(list[k]);
			}
		}

		private void UpdateMarkerTransforms()
		{
			foreach (KeyValuePair<Collider, GameObject> item in markersByCollider)
			{
				Collider key = item.Key;
				GameObject value = item.Value;
				if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null))
				{
					HighlightCategory category = GetCategory(key);
					bool flag = ShouldShowCategory(category);
					value.SetActive(flag);
					if (flag)
					{
						SyncMarkerTransform(key, value.transform);
					}
				}
			}
		}

		private GameObject CreateMarkerForCollider(Collider collider)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			PrimitiveType val = (PrimitiveType)3;
			if (collider is SphereCollider)
			{
				val = (PrimitiveType)0;
			}
			else if (collider is CapsuleCollider)
			{
				val = (PrimitiveType)1;
			}
			GameObject val2 = GameObject.CreatePrimitive(val);
			((Object)val2).name = "DropLaserCartDebugMarker_" + ((Object)collider).name;
			Object.DontDestroyOnLoad((Object)(object)val2);
			Collider component = val2.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				component.enabled = false;
			}
			Renderer component2 = val2.GetComponent<Renderer>();
			if ((Object)(object)component2 == (Object)null || (Object)(object)debugShader == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			Material val3 = new Material(debugShader);
			val3.color = GetColorForCollider(collider);
			component2.material = val3;
			component2.shadowCastingMode = (ShadowCastingMode)0;
			component2.receiveShadows = false;
			SyncMarkerTransform(collider, val2.transform);
			return val2;
		}

		private void SyncMarkerTransform(Collider source, Transform markerTransform)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: 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_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: 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_00f6: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			BoxCollider val = (BoxCollider)(object)((source is BoxCollider) ? source : null);
			if (val != null)
			{
				markerTransform.SetPositionAndRotation(((Component)source).transform.TransformPoint(val.center), ((Component)source).transform.rotation);
				markerTransform.localScale = Vector3.Scale(val.size, ((Component)source).transform.lossyScale);
				return;
			}
			SphereCollider val2 = (SphereCollider)(object)((source is SphereCollider) ? source : null);
			if (val2 != null)
			{
				float num = val2.radius * 2f;
				markerTransform.position = ((Component)source).transform.TransformPoint(val2.center);
				markerTransform.rotation = ((Component)source).transform.rotation;
				markerTransform.localScale = new Vector3(num * ((Component)source).transform.lossyScale.x, num * ((Component)source).transform.lossyScale.y, num * ((Component)source).transform.lossyScale.z);
				return;
			}
			CapsuleCollider val3 = (CapsuleCollider)(object)((source is CapsuleCollider) ? source : null);
			if (val3 != null)
			{
				float num2 = val3.radius * 2f;
				Vector3 lossyScale = ((Component)source).transform.lossyScale;
				Vector3 localScale = default(Vector3);
				((Vector3)(ref localScale))..ctor(num2 * lossyScale.x, num2 * lossyScale.y, num2 * lossyScale.z);
				float height = val3.height;
				if (val3.direction == 0)
				{
					localScale.x = height * lossyScale.x;
				}
				else if (val3.direction == 1)
				{
					localScale.y = height * lossyScale.y;
				}
				else
				{
					localScale.z = height * lossyScale.z;
				}
				markerTransform.position = ((Component)source).transform.TransformPoint(val3.center);
				markerTransform.rotation = ((Component)source).transform.rotation;
				markerTransform.localScale = localScale;
			}
			else
			{
				Bounds bounds = source.bounds;
				markerTransform.position = ((Bounds)(ref bounds)).center;
				markerTransform.rotation = Quaternion.identity;
				bounds = source.bounds;
				markerTransform.localScale = ((Bounds)(ref bounds)).size;
			}
		}

		private bool ShouldHighlight(Collider collider)
		{
			GameObject gameObject = ((Component)collider).gameObject;
			if (gameObject.CompareTag("Cart"))
			{
				return true;
			}
			int layer = gameObject.layer;
			if ((physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer) || (physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer) || (cartWheelsLayer >= 0 && layer == cartWheelsLayer))
			{
				return true;
			}
			string name = ((Object)gameObject).name;
			if (!name.StartsWith("Capsule", StringComparison.OrdinalIgnoreCase) && !name.Contains("Cart Wall Collider"))
			{
				return name.Equals("In Cart", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private Color GetColorForCollider(Collider collider)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			return (Color)(GetCategory(collider) switch
			{
				HighlightCategory.InCartTrigger => new Color(0f, 1f, 0f, 0.25f), 
				HighlightCategory.CartBody => new Color(1f, 0.5f, 0f, 0.25f), 
				HighlightCategory.CartWheels => new Color(1f, 1f, 0f, 0.25f), 
				_ => new Color(0f, 1f, 1f, 0.2f), 
			});
		}

		private HighlightCategory GetCategory(Collider collider)
		{
			GameObject gameObject = ((Component)collider).gameObject;
			int layer = gameObject.layer;
			if (gameObject.CompareTag("Cart") || (physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer))
			{
				return HighlightCategory.InCartTrigger;
			}
			if (physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer)
			{
				return HighlightCategory.CartBody;
			}
			if (cartWheelsLayer >= 0 && layer == cartWheelsLayer)
			{
				return HighlightCategory.CartWheels;
			}
			return HighlightCategory.OtherCart;
		}

		private bool ShouldShowCategory(HighlightCategory category)
		{
			return ShouldShowCategoryStatic(category, currentMode);
		}

		private void HandleCycleInput()
		{
			if (DropLaserInputHelper.IsConfiguredKeyDown(Plugin.HighlightCycleForwardKey.Value))
			{
				CycleMode(1);
			}
			if (DropLaserInputHelper.IsConfiguredKeyDown(Plugin.HighlightCycleBackwardKey.Value))
			{
				CycleMode(-1);
			}
		}

		private void CycleMode(int delta)
		{
			int length = Enum.GetValues(typeof(HighlightMode)).Length;
			int num = (int)(currentMode + delta) % length;
			if (num < 0)
			{
				num += length;
			}
			currentMode = (HighlightMode)num;
			ActiveMode = currentMode;
			DropLaserLogger.Info("[DropLaser] Cart highlight mode: " + currentMode);
		}

		private static bool ShouldShowCategoryStatic(HighlightCategory category, HighlightMode mode)
		{
			return mode switch
			{
				HighlightMode.All => true, 
				HighlightMode.InCartOnly => category == HighlightCategory.InCartTrigger, 
				HighlightMode.CartBodyOnly => category == HighlightCategory.CartBody, 
				HighlightMode.CartWheelsOnly => category == HighlightCategory.CartWheels, 
				HighlightMode.OtherCartOnly => category == HighlightCategory.OtherCart, 
				_ => true, 
			};
		}

		private static bool TryGetCategoryForGameObject(GameObject gameObject, out HighlightCategory category)
		{
			category = HighlightCategory.OtherCart;
			int num = LayerMask.NameToLayer("PhysGrabObjectTrigger");
			int num2 = LayerMask.NameToLayer("PhysGrabObjectCart");
			int num3 = LayerMask.NameToLayer("CartWheels");
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			bool flag4 = false;
			bool flag5 = false;
			bool flag6 = false;
			bool flag7 = false;
			Transform val = gameObject.transform;
			while ((Object)(object)val != (Object)null)
			{
				GameObject gameObject2 = ((Component)val).gameObject;
				int layer = gameObject2.layer;
				string name = ((Object)gameObject2).name;
				if (gameObject2.CompareTag("Cart"))
				{
					flag = true;
				}
				if (num >= 0 && layer == num)
				{
					flag2 = true;
				}
				if (num2 >= 0 && layer == num2)
				{
					flag3 = true;
				}
				if (num3 >= 0 && layer == num3)
				{
					flag4 = true;
				}
				if (name.StartsWith("Capsule", StringComparison.OrdinalIgnoreCase))
				{
					flag5 = true;
				}
				if (name.Contains("Cart Wall Collider"))
				{
					flag6 = true;
				}
				if (name.Equals("In Cart", StringComparison.OrdinalIgnoreCase))
				{
					flag7 = true;
				}
				val = val.parent;
			}
			if (!(flag || flag2 || flag3 || flag4 || flag5 || flag6 || flag7))
			{
				return false;
			}
			if (flag || flag2)
			{
				category = HighlightCategory.InCartTrigger;
				return true;
			}
			if (flag3 || flag6)
			{
				category = HighlightCategory.CartBody;
				return true;
			}
			if (flag4 || flag5)
			{
				category = HighlightCategory.CartWheels;
				return true;
			}
			category = HighlightCategory.OtherCart;
			return true;
		}

		private void ClearAllMarkers()
		{
			foreach (KeyValuePair<Collider, GameObject> item in markersByCollider)
			{
				if ((Object)(object)item.Value != (Object)null)
				{
					Object.Destroy((Object)(object)item.Value);
				}
			}
			markersByCollider.Clear();
			liveColliders.Clear();
		}
	}
	public class DropLaserManager
	{
		private static DropLaserManager _inst;

		private DropLaserController _ctrl;

		public static DropLaserManager Instance => _inst ?? (_inst = new DropLaserManager());

		public void ToggleLaser()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if ((Object)(object)_ctrl == (Object)null)
			{
				GameObject val = new GameObject("DropLaserController");
				_ctrl = val.AddComponent<DropLaserController>();
			}
			_ctrl.Toggle();
		}

		public void ForceDisableLaser()
		{
			if ((Object)(object)_ctrl == (Object)null)
			{
				DropLaserLogger.Info("[DropLaserManager] ForceDisableLaser called but _ctrl is NULL!");
			}
			else if ((Object)(object)((Component)_ctrl).gameObject == (Object)null)
			{
				DropLaserLogger.Info("[DropLaserManager] ForceDisableLaser: _ctrl exists but its GameObject is DESTROYED!");
			}
			else
			{
				DropLaserLogger.Info($"[DropLaserManager] ForceDisableLaser: _ctrl OK. GameObject name: {((Object)((Component)_ctrl).gameObject).name}, Active: {((Component)_ctrl).gameObject.activeSelf}");
			}
			if ((Object)(object)_ctrl != (Object)null)
			{
				_ctrl.DisableLaser();
				DropLaserLogger.Info("[DropLaserManager] Laser force-disabled after item release.");
			}
			else
			{
				DropLaserLogger.Warning("[DropLaserManager] ForceDisableLaser called, but controller was null.");
			}
		}

		public bool HasController()
		{
			if ((Object)(object)_ctrl != (Object)null)
			{
				return (Object)(object)((Component)_ctrl).gameObject != (Object)null;
			}
			return false;
		}
	}
	public static class DropLaserMaterialService
	{
		public static Material CreateTransparentLineMaterial(Shader shader)
		{
			//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_0017: Expected O, but got Unknown
			//IL_0018: Expected O, but got Unknown
			if ((Object)(object)shader == (Object)null)
			{
				return null;
			}
			Material val = new Material(shader);
			ConfigureTransparentMaterial(val);
			return val;
		}

		public static void ConfigureTransparentMaterial(Material material)
		{
			if (!((Object)(object)material == (Object)null))
			{
				if (material.HasProperty("_Mode"))
				{
					material.SetFloat("_Mode", 2f);
				}
				material.SetInt("_SrcBlend", 5);
				material.SetInt("_DstBlend", 10);
				material.SetInt("_ZWrite", 0);
				material.DisableKeyword("_ALPHATEST_ON");
				material.EnableKeyword("_ALPHABLEND_ON");
				material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
				material.renderQueue = 3000;
			}
		}

		public static void SyncFromSourceBeam(Material target, Material source)
		{
			//IL_0048: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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)
			if (!((Object)(object)target == (Object)null) && !((Object)(object)source == (Object)null))
			{
				if (source.HasProperty("_MainTex") && target.HasProperty("_MainTex"))
				{
					target.SetTexture("_MainTex", source.GetTexture("_MainTex"));
					target.mainTextureOffset = source.mainTextureOffset;
					target.mainTextureScale = source.mainTextureScale;
				}
				if (source.HasProperty("_Color") && target.HasProperty("_Color"))
				{
					target.SetColor("_Color", source.GetColor("_Color"));
				}
				if (source.HasProperty("_BaseColor") && target.HasProperty("_BaseColor"))
				{
					target.SetColor("_BaseColor", source.GetColor("_BaseColor"));
				}
				if (source.HasProperty("_EmissionColor") && target.HasProperty("_EmissionColor"))
				{
					target.SetColor("_EmissionColor", source.GetColor("_EmissionColor"));
				}
			}
		}

		public static void MirrorMaterialAppearance(Material target, Material source)
		{
			if (!((Object)(object)target == (Object)null) && !((Object)(object)source == (Object)null))
			{
				if ((Object)(object)target.shader != (Object)(object)source.shader)
				{
					target.shader = source.shader;
				}
				target.CopyPropertiesFromMaterial(source);
				target.shaderKeywords = source.shaderKeywords;
				target.renderQueue = source.renderQueue;
			}
		}

		public static void WriteColor(Material material, Color color)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				if (material.HasProperty("_Color"))
				{
					material.SetColor("_Color", color);
				}
				if (material.HasProperty("_BaseColor"))
				{
					material.SetColor("_BaseColor", color);
				}
			}
		}

		public static void ApplyOpacityToKnownColorProperties(Material material, float opacity)
		{
			if (!((Object)(object)material == (Object)null))
			{
				float alpha = Mathf.Clamp01(opacity);
				ApplyAlphaIfPresent(material, "_Color", alpha);
				ApplyAlphaIfPresent(material, "_BaseColor", alpha);
				ApplyAlphaIfPresent(material, "_TintColor", alpha);
			}
		}

		private static void ApplyAlphaIfPresent(Material material, string propertyName, float alpha)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(propertyName))
			{
				Color color = material.GetColor(propertyName);
				color.a = alpha;
				material.SetColor(propertyName, color);
			}
		}
	}
	public sealed class DropLaserOverlayService
	{
		private const float InnerWidthMultiplier = 0.35f;

		private const float InnerAlphaBoost = 1.8f;

		private const float InnerMinAlpha = 0.2f;

		private const float InnerEmission = 1.1f;

		public void Disable(LineRenderer overlayLine)
		{
			if ((Object)(object)overlayLine != (Object)null)
			{
				((Renderer)overlayLine).enabled = false;
			}
		}

		public void SyncInnerOverlay(LineRenderer overlayLine, LineRenderer sourceLine, bool allowOverlay)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_0131: 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_0162: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)overlayLine == (Object)null || (Object)(object)sourceLine == (Object)null)
			{
				return;
			}
			if (!allowOverlay || !((Renderer)sourceLine).enabled || sourceLine.positionCount < 2)
			{
				((Renderer)overlayLine).enabled = false;
				return;
			}
			Vector3 position = sourceLine.GetPosition(0);
			Vector3 position2 = sourceLine.GetPosition(sourceLine.positionCount - 1);
			overlayLine.positionCount = 2;
			overlayLine.SetPosition(0, position);
			overlayLine.SetPosition(1, position2);
			if (sourceLine.startWidth > 0f)
			{
				overlayLine.startWidth = sourceLine.startWidth * 0.35f;
			}
			if (sourceLine.endWidth > 0f)
			{
				overlayLine.endWidth = sourceLine.endWidth * 0.35f;
			}
			float num = ReadLineAlpha(sourceLine.startColor);
			float num2 = ReadLineAlpha(sourceLine.endColor);
			overlayLine.startColor = new Color(1f, 1f, 1f, num);
			overlayLine.endColor = new Color(1f, 1f, 1f, num2);
			if ((Object)(object)((Renderer)overlayLine).material != (Object)null)
			{
				DropLaserMaterialService.SyncFromSourceBeam(((Renderer)overlayLine).material, ((Renderer)sourceLine).material);
				float num3 = BoostAlpha(ReadMaterialAlpha(((Renderer)sourceLine).material));
				DropLaserMaterialService.WriteColor(((Renderer)overlayLine).material, new Color(1f, 1f, 1f, num3));
				if (((Renderer)overlayLine).material.HasProperty("_EmissionColor"))
				{
					((Renderer)overlayLine).material.SetColor("_EmissionColor", Color.white * 1.1f);
				}
			}
			((Renderer)overlayLine).enabled = true;
		}

		private static float ReadLineAlpha(Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return BoostAlpha(color.a);
		}

		private static float ReadMaterialAlpha(Material sourceMaterial)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sourceMaterial == (Object)null)
			{
				return 1f;
			}
			if (sourceMaterial.HasProperty("_BaseColor"))
			{
				return sourceMaterial.GetColor("_BaseColor").a;
			}
			if (sourceMaterial.HasProperty("_Color"))
			{
				return sourceMaterial.GetColor("_Color").a;
			}
			return 1f;
		}

		private static float BoostAlpha(float alpha)
		{
			return Mathf.Clamp01(Mathf.Max(alpha * 1.8f, 0.2f));
		}
	}
	public sealed class SagaOrchestrator
	{
		private sealed class BranchState
		{
			public int RetryAtFrame;

			public bool IsCutOff;

			public Exception LastFailure;

			public int LastFailureFrame;

			public int LastCutOffLogFrame;
		}

		private readonly ManualLogSource log;

		private readonly int retryDelayFrames;

		private readonly Dictionary<string, BranchState> branches = new Dictionary<string, BranchState>();

		private static bool ShouldLogSagaLifecycle()
		{
			if (Plugin.EnableLogging != null)
			{
				return Plugin.EnableLogging.Value;
			}
			return false;
		}

		public SagaOrchestrator(ManualLogSource log, int retryDelayFrames = 180)
		{
			this.log = log;
			this.retryDelayFrames = Mathf.Max(1, retryDelayFrames);
		}

		public void Execute(string branchName, Action execute, Action compensate)
		{
			if (string.IsNullOrWhiteSpace(branchName))
			{
				branchName = "unnamed";
			}
			BranchState orCreateState = GetOrCreateState(branchName);
			if (orCreateState.IsCutOff && Time.frameCount < orCreateState.RetryAtFrame)
			{
				if (ShouldLogSagaLifecycle() && Time.frameCount >= orCreateState.LastCutOffLogFrame + 120)
				{
					string text = ((orCreateState.LastFailure != null) ? orCreateState.LastFailure.Message : "unknown");
					log.LogWarning((object)$"[DropLaser:Saga] Branch '{branchName}' remains cut off until frame {orCreateState.RetryAtFrame} (last failure frame {orCreateState.LastFailureFrame}: {text})");
					orCreateState.LastCutOffLogFrame = Time.frameCount;
				}
				return;
			}
			try
			{
				execute?.Invoke();
				if (ShouldLogSagaLifecycle() && orCreateState.IsCutOff)
				{
					log.LogInfo((object)("[DropLaser:Saga] Branch '" + branchName + "' recovered and resumed."));
				}
				orCreateState.IsCutOff = false;
				orCreateState.RetryAtFrame = 0;
				orCreateState.LastFailure = null;
				orCreateState.LastFailureFrame = 0;
			}
			catch (Exception lastFailure)
			{
				Exception arg = (orCreateState.LastFailure = lastFailure);
				orCreateState.LastFailureFrame = Time.frameCount;
				log.LogError((object)$"[DropLaser:Saga] Branch '{branchName}' failed at frame {Time.frameCount}: {arg}");
				try
				{
					compensate?.Invoke();
				}
				catch (Exception arg2)
				{
					log.LogError((object)$"[DropLaser:Saga] Branch '{branchName}' compensation failed: {arg2}");
				}
				orCreateState.IsCutOff = true;
				orCreateState.RetryAtFrame = Time.frameCount + retryDelayFrames;
				orCreateState.LastCutOffLogFrame = Time.frameCount;
				if (ShouldLogSagaLifecycle())
				{
					log.LogWarning((object)$"[DropLaser:Saga] Branch '{branchName}' cut off until frame {orCreateState.RetryAtFrame}.");
				}
			}
		}

		private BranchState GetOrCreateState(string branchName)
		{
			if (!branches.TryGetValue(branchName, out var value))
			{
				value = new BranchState();
				branches[branchName] = value;
			}
			return value;
		}
	}
}
namespace ObjectDropLaserMod.Patches
{
	[HarmonyPatch(typeof(PhysGrabber), "Update")]
	public static class DropLaserInputPatch
	{
		private static bool Prefix(PhysGrabber __instance)
		{
			PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
			bool flag = PhotonNetwork.PlayerList.Length < 1;
			if (!flag && (Object)(object)component != (Object)null && !component.IsMine)
			{
				return true;
			}
			if (DropLaserInputHelper.IsConfiguredKeyDown(Plugin.ToggleLaserKey.Value))
			{
				DropLaserLogger.Info("[DropLaserInputPatch] Local player pressed L (singleplayer: " + flag + ").");
				DropLaserLogger.Info("[DropLaserInputPatch] Number on PlayerList = ) " + PhotonNetwork.PlayerList.Length);
				if (!GrabDetectionState.IsHoldingObject)
				{
					DropLaserLogger.Info("[DropLaserInputPatch] L pressed but not holding object ignoring toggle.");
					return true;
				}
				SimulateKeyPress();
			}
			return true;
		}

		public static void SimulateKeyPress()
		{
			DropLaserManager instance = DropLaserManager.Instance;
			if (instance != null)
			{
				instance.ToggleLaser();
			}
			else
			{
				Plugin.log.LogWarning((object)"[DropLaserInputPatch] DropLaserManager instance missing during SimulateKeyPress.");
			}
		}
	}
}
namespace ObjectDropLaserMod.GrabDetection
{
	public static class GrabDetectionState
	{
		public static bool IsHoldingObject;
	}
	[HarmonyPatch(typeof(PhysGrabber), "ReleaseObject")]
	public static class GrabReleasePatch
	{
		private static void Postfix(PhysGrabber __instance)
		{
			string arg = (((Object)(object)__instance != (Object)null) ? ((Object)__instance).name : "null");
			int num = (((Object)(object)__instance != (Object)null) ? ((Object)__instance).GetInstanceID() : (-1));
			DropLaserLogger.Info($"[GrabReleasePatch] ReleaseObject called on PhysGrabber: {arg} (InstanceID: {num})");
			GrabDetectionState.IsHoldingObject = false;
			DropLaserLogger.Info("[GrabReleasePatch] IsHoldingObject = false");
			if (DropLaserManager.Instance.HasController())
			{
				DropLaserManager.Instance.ForceDisableLaser();
				DropLaserLogger.Info("[GrabReleasePatch] ForceDisableLaser() called.");
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabber), "RayCheck")]
	public static class GrabStartPatch
	{
		private static void Postfix(PhysGrabber __instance, bool _grab)
		{
			if (_grab && __instance.grabbed)
			{
				GrabDetectionState.IsHoldingObject = true;
				DropLaserLogger.Info("[GrabStartPatch] Grab confirmed - IsHoldingObject = true");
				if (Plugin.AutoEnableOnGrab.Value)
				{
					DropLaserLogger.Info("[GrabStartPatch] Auto-enabling laser due to object grab.");
					DropLaserInputPatch.SimulateKeyPress();
				}
			}
		}
	}
}
namespace ObjectDropLaserMod.Components
{
	public class DropLaserBeam
	{
		private sealed class GhostRendererState
		{
			public Renderer Renderer;

			public Material Material;
		}

		private readonly struct BeamFrameData
		{
			public readonly PhysGrabObject HeldObject;

			public readonly Vector3 BeamStart;

			public readonly Vector3 BeamHitPoint;

			public readonly bool ShouldShowGhost;

			public readonly bool ShouldRenderOverlay;

			public BeamFrameData(PhysGrabObject heldObject, Vector3 beamStart, Vector3 beamHitPoint, bool shouldShowGhost, bool shouldRenderOverlay)
			{
				//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)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				HeldObject = heldObject;
				BeamStart = beamStart;
				BeamHitPoint = beamHitPoint;
				ShouldShowGhost = shouldShowGhost;
				ShouldRenderOverlay = shouldRenderOverlay;
			}
		}

		private readonly struct HitDebugInfo
		{
			public readonly bool HasHit;

			public readonly string ObjectName;

			public readonly string Tag;

			public readonly int Layer;

			public readonly float Distance;

			public readonly Vector3 Point;

			public HitDebugInfo(RaycastHit hit)
			{
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
				{
					HasHit = false;
					ObjectName = string.Empty;
					Tag = string.Empty;
					Layer = -1;
					Distance = 0f;
					Point = Vector3.zero;
				}
				else
				{
					HasHit = true;
					ObjectName = ((Object)((Component)((RaycastHit)(ref hit)).collider).gameObject).name;
					Tag = ((Component)((RaycastHit)(ref hit)).collider).gameObject.tag;
					Layer = ((Component)((RaycastHit)(ref hit)).collider).gameObject.layer;
					Distance = ((RaycastHit)(ref hit)).distance;
					Point = ((RaycastHit)(ref hit)).point;
				}
			}
		}

		private const float DefaultDowncastDistance = 50f;

		private const float LaserOriginVerticalOffset = 0.05f;

		private const float GhostRayStartOffset = 0.02f;

		private const float MinimumBeamLength = 0.01f;

		private const int RaycastBufferSize = 64;

		private const float FallbackBoundsSize = 0.1f;

		private const float EndTaperPortion = 0.03f;

		private const float EndTaperAlphaMultiplier = 0.6f;

		private const int StopLogIntervalFrames = 1000;

		private const float RegularHitDumpIntervalSeconds = 5f;

		private const float BottomNormalDotThreshold = 0.85f;

		private readonly LineRenderer dropBeamLine;

		private readonly LineRenderer grabBeamOverlayLine;

		private readonly LineRenderer dropBeamOverlayLine;

		private readonly Light dropBeamLight;

		private readonly GameObject sourceBeamObject;

		private readonly LineRenderer sourceBeamLine;

		private readonly PhysGrabber playerGrabber;

		private readonly HashSet<string> ignoredCartParts;

		private readonly RaycastHit[] raycastHitBuffer = (RaycastHit[])(object)new RaycastHit[64];

		private readonly SagaOrchestrator saga;

		private readonly DropLaserOverlayService overlayService;

		private readonly DropLaserBeamDebugService debugService;

		private readonly int physGrabObjectCartLayer;

		private readonly int cartWheelsLayer;

		private readonly int physGrabObjectTriggerLayer;

		private readonly List<GhostRendererState> ghostRenderers = new List<GhostRendererState>();

		private GameObject ghostRoot;

		private PhysGrabObject ghostSource;

		private int nextGhostUpdateFrame;

		private int nextGhostFailureLogFrame;

		private int nextBeamStopLogFrame;

		private int nextGhostStopLogFrame;

		private float nextRegularHitDumpTime;

		private int lastBeamHitCount;

		private HitDebugInfo lastChosenBeamStopInfo;

		private bool hasLastChosenBeamStopInfo;

		private HitDebugInfo lastChosenGhostStopInfo;

		private bool hasLastChosenGhostStopInfo;

		private readonly List<HitDebugInfo> lastGhostCandidateHits = new List<HitDebugInfo>();

		private string lastGhostCandidateSource = "none";

		public DropLaserBeam(LineRenderer dropBeamLine, LineRenderer grabBeamOverlayLine, LineRenderer dropBeamOverlayLine, Light dropBeamLight, GameObject sourceBeamObject, LineRenderer sourceBeamLine, PhysGrabber playerGrabber, HashSet<string> ignoredCartParts)
		{
			this.dropBeamLine = dropBeamLine;
			this.grabBeamOverlayLine = grabBeamOverlayLine;
			this.dropBeamOverlayLine = dropBeamOverlayLine;
			this.dropBeamLight = dropBeamLight;
			this.sourceBeamObject = sourceBeamObject;
			this.sourceBeamLine = sourceBeamLine;
			this.playerGrabber = playerGrabber;
			this.ignoredCartParts = ignoredCartParts;
			saga = new SagaOrchestrator(Plugin.log);
			overlayService = new DropLaserOverlayService();
			debugService = new DropLaserBeamDebugService();
			physGrabObjectCartLayer = LayerMask.NameToLayer("PhysGrabObjectCart");
			cartWheelsLayer = LayerMask.NameToLayer("CartWheels");
			physGrabObjectTriggerLayer = LayerMask.NameToLayer("PhysGrabObjectTrigger");
		}

		public void UpdateBeam()
		{
			//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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (!HasValidReferences())
			{
				return;
			}
			debugService.Tick();
			Material material = ((Renderer)sourceBeamLine).material;
			Material material2 = ((Renderer)dropBeamLine).material;
			Color laserColor = SyncBeamAppearance(material, material2);
			if (!TryBuildFrameData(out var frameData))
			{
				HideBeamAndGhost();
				return;
			}
			bool hasGhostStop = false;
			Vector3 ghostStopPoint = Vector3.zero;
			saga.Execute("ghost", delegate
			{
				hasGhostStop = UpdateGhostPreview(frameData.HeldObject, frameData.ShouldShowGhost, out ghostStopPoint);
			}, delegate
			{
				SetGhostVisible(visible: false);
			});
			saga.Execute("beam", delegate
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				Vector3 targetStopPoint = (hasGhostStop ? ghostStopPoint : frameData.BeamHitPoint);
				UpdateBeamVisuals(frameData.BeamStart, targetStopPoint, laserColor);
			}, delegate
			{
				((Renderer)dropBeamLine).enabled = false;
				((Behaviour)dropBeamLight).enabled = false;
			});
			saga.Execute("overlay", delegate
			{
				overlayService.SyncInnerOverlay(grabBeamOverlayLine, sourceBeamLine, frameData.ShouldRenderOverlay);
				overlayService.SyncInnerOverlay(dropBeamOverlayLine, dropBeamLine, frameData.ShouldRenderOverlay);
			}, delegate
			{
				overlayService.Disable(grabBeamOverlayLine);
				overlayService.Disable(dropBeamOverlayLine);
			});
		}

		public void Dispose()
		{
			SetGhostVisible(visible: false);
			DestroyGhost();
			debugService.Dispose();
		}

		private bool HasValidReferences()
		{
			if ((Object)(object)playerGrabber != (Object)null && (Object)(object)sourceBeamLine != (Object)null && (Object)(object)sourceBeamObject != (Object)null)
			{
				return true;
			}
			Plugin.log.LogWarning((object)"[DropLaser] Critical references lost. Cannot update beam.");
			return false;
		}

		private static bool ShouldLogGhostWarnings()
		{
			if (Plugin.EnableLogging != null)
			{
				return Plugin.EnableLogging.Value;
			}
			return false;
		}

		private bool TryBuildFrameData(out BeamFrameData frameData)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			frameData = default(BeamFrameData);
			PhysGrabObject grabbedObject = playerGrabber.GetGrabbedObject();
			if ((Object)(object)grabbedObject == (Object)null)
			{
				return false;
			}
			Vector3 val = CalculateBeamOrigin(grabbedObject);
			Vector3 beamHitPoint = val + Vector3.down * 50f;
			ResolveBeamHitPoint(val, grabbedObject, ref beamHitPoint, out var hitTrackedCartObject, out var stopInfo);
			LogStopInfoIfNeeded("Beam", stopInfo, ref nextBeamStopLogFrame);
			bool flag = CartStateAccessors.IsPointInsideAnyCartInCartBounds(beamHitPoint);
			bool flag2 = CartStateAccessors.IsPointAboveAnyCartInCartBounds(val);
			bool flag3 = hitTrackedCartObject || flag || flag2;
			DumpBeamHitsIfNeeded(grabbedObject, flag3);
			int num = Mathf.Clamp(Plugin.GhostPreviewMode.Value, 0, 2);
			bool shouldShowGhost = num == 2 || (num == 1 && flag3);
			bool shouldRenderOverlay = Plugin.EnableDropBeamInnerWhite.Value && flag3;
			frameData = new BeamFrameData(grabbedObject, val, beamHitPoint, shouldShowGhost, shouldRenderOverlay);
			return true;
		}

		private void HideBeamAndGhost()
		{
			((Renderer)dropBeamLine).enabled = false;
			((Behaviour)dropBeamLight).enabled = false;
			overlayService.Disable(grabBeamOverlayLine);
			overlayService.Disable(dropBeamOverlayLine);
			SetGhostVisible(visible: false);
			debugService.HideVisuals();
		}

		private Color SyncBeamAppearance(Material sourceMaterial, Material dropMaterial)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.UseCustomColor.Value)
			{
				Color value = Plugin.CustomLaserColor.Value;
				SetLineColor(value);
				ApplyLaserMaterialAppearance(dropMaterial, sourceMaterial, value, 1f, 1f);
				return value;
			}
			Color finalLaserColor = DropLaserColorManager.GetFinalLaserColor(sourceMaterial);
			DropLaserMaterialService.SyncFromSourceBeam(dropMaterial, sourceMaterial);
			SetLineColor(finalLaserColor);
			DropLaserMaterialService.WriteColor(dropMaterial, finalLaserColor);
			return finalLaserColor;
		}

		private void SetLineColor(Color color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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)
			//IL_0104: 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)
			float num = 1f;
			float num2 = 0.6f;
			Gradient val = new Gradient();
			val.SetKeys((GradientColorKey[])(object)new GradientColorKey[4]
			{
				new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 0f),
				new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 0.03f),
				new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 0.97f),
				new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 1f)
			}, (GradientAlphaKey[])(object)new GradientAlphaKey[4]
			{
				new GradientAlphaKey(num2, 0f),
				new GradientAlphaKey(num, 0.03f),
				new GradientAlphaKey(num, 0.97f),
				new GradientAlphaKey(num2, 1f)
			});
			dropBeamLine.colorGradient = val;
		}

		private Vector3 CalculateBeamOrigin(PhysGrabObject heldObject)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return CalculateBeamOrigin(((Component)heldObject).gameObject);
		}

		private Vector3 CalculateBeamOrigin(GameObject targetObject)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Bounds objectBounds = GetObjectBounds(targetObject);
			Vector3 center = ((Bounds)(ref objectBounds)).center;
			center.y += 0.05f;
			center.y -= ((Bounds)(ref objectBounds)).extents.y;
			return center;
		}

		private void UpdateBeamVisuals(Vector3 beamStart, Vector3 targetStopPoint, Color laserColor)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(targetStopPoint.y, beamStart.y - 0.01f);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(beamStart.x, num, beamStart.z);
			((Renderer)dropBeamLine).enabled = true;
			dropBeamLine.SetPosition(0, beamStart);
			dropBeamLine.SetPosition(1, val);
			((Component)dropBeamLight).transform.position = val;
			dropBeamLight.color = new Color(laserColor.r, laserColor.g, laserColor.b, 1f);
			((Behaviour)dropBeamLight).enabled = true;
		}

		private void ResolveBeamHitPoint(Vector3 beamStart, PhysGrabObject heldObject, ref Vector3 beamHitPoint, out bool hitTrackedCartObject, out HitDebugInfo stopInfo)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			hitTrackedCartObject = false;
			stopInfo = default(HitDebugInfo);
			hasLastChosenBeamStopInfo = false;
			int num = (lastBeamHitCount = Physics.RaycastNonAlloc(beamStart, Vector3.down, raycastHitBuffer, Plugin.LaserMaxDistance.Value, -5, (QueryTriggerInteraction)2));
			debugService.RenderBeamHits(beamStart, raycastHitBuffer, num, heldObject);
			float num2 = float.MaxValue;
			for (int i = 0; i < num; i++)
			{
				RaycastHit hit = raycastHitBuffer[i];
				if (IsValidBeamHit(hit, heldObject) && !(((RaycastHit)(ref hit)).distance >= num2))
				{
					num2 = ((RaycastHit)(ref hit)).distance;
					beamHitPoint = ((RaycastHit)(ref hit)).point;
					hitTrackedCartObject = CartStateAccessors.IsGameObjectTrackedInCart(((Component)((RaycastHit)(ref hit)).collider).gameObject);
					stopInfo = new HitDebugInfo(hit);
					lastChosenBeamStopInfo = stopInfo;
					hasLastChosenBeamStopInfo = true;
				}
			}
		}

		private bool IsValidBeamHit(RaycastHit hit, PhysGrabObject heldObject)
		{
			if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
			{
				return false;
			}
			GameObject gameObject = ((Component)((RaycastHit)(ref hit)).collider).gameObject;
			if (ShouldIgnoreCartHit(gameObject, debugService.IsDebugStopOverrideActive()))
			{
				return false;
			}
			return !IsPartOfHeldObject(gameObject, ((Component)heldObject).gameObject);
		}

		private bool ShouldIgnoreCartHit(GameObject hitObject, bool debugStopOverrideActive)
		{
			if ((Object)(object)hitObject == (Object)null)
			{
				return false;
			}
			int layer = hitObject.layer;
			string name = ((Object)hitObject).name;
			bool flag = hitObject.CompareTag("Cart");
			bool flag2 = physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer;
			bool flag3 = cartWheelsLayer >= 0 && layer == cartWheelsLayer;
			bool flag4 = physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer;
			bool flag5 = name.StartsWith("Capsule", StringComparison.OrdinalIgnoreCase);
			if (DropLaserCartPartHighlighter.IsGameObjectCartBody(hitObject))
			{
				return false;
			}
			if (debugStopOverrideActive)
			{
				return !DropLaserCartPartHighlighter.IsGameObjectHighlightedForCurrentMode(hitObject);
			}
			if (flag || flag2 || flag4 || flag3 || flag5)
			{
				return true;
			}
			return ignoredCartParts.Contains(name);
		}

		private bool UpdateGhostPreview(PhysGrabObject heldObject, bool shouldShowGhost, out Vector3 ghostStopPoint)
		{
			//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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			ghostStopPoint = Vector3.zero;
			if (!shouldShowGhost)
			{
				SetGhostVisible(visible: false);
				return false;
			}
			EnsureGhostForHeldObject(heldObject);
			if ((Object)(object)ghostRoot == (Object)null)
			{
				return false;
			}
			if (Time.frameCount >= nextGhostUpdateFrame)
			{
				int num = Mathf.Max(1, Plugin.GhostUpdateFrameInterval.Value);
				nextGhostUpdateFrame = Time.frameCount + num;
				if (!TryUpdateGhostTransform(heldObject))
				{
					if (Time.frameCount >= nextGhostFailureLogFrame)
					{
						if (ShouldLogGhostWarnings())
						{
							Plugin.log.LogWarning((object)"[DropLaser] Ghost transform update failed; hiding ghost for this frame.");
						}
						nextGhostFailureLogFrame = Time.frameCount + 120;
					}
					SetGhostVisible(visible: false);
					return false;
				}
			}
			SetGhostVisible(visible: true);
			ghostStopPoint = GetGhostStopPoint();
			return true;
		}

		private bool TryUpdateGhostTransform(PhysGrabObject heldObject)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00b2: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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)
			lastGhostCandidateHits.Clear();
			lastGhostCandidateSource = "none";
			if (!hasLastChosenBeamStopInfo || !lastChosenBeamStopInfo.HasHit)
			{
				hasLastChosenGhostStopInfo = false;
				return false;
			}
			float y = lastChosenBeamStopInfo.Point.y;
			HitDebugInfo info = lastChosenBeamStopInfo;
			lastGhostCandidateSource = "beam-ray";
			if (TryResolveHighestObjectRaycastHit(heldObject, y, out var bestHigherHit))
			{
				y = ((RaycastHit)(ref bestHigherHit)).point.y;
				info = (lastChosenGhostStopInfo = new HitDebugInfo(bestHigherHit));
				hasLastChosenGhostStopInfo = true;
			}
			Bounds objectBounds = GetObjectBounds(((Component)heldObject).gameObject);
			float num = Mathf.Max(0f, ((Bounds)(ref objectBounds)).min.y - y);
			Vector3 val = ((Component)heldObject).transform.position - Vector3.up * num;
			ghostRoot.transform.SetPositionAndRotation(val, ((Component)heldObject).transform.rotation);
			lastChosenGhostStopInfo = info;
			hasLastChosenGhostStopInfo = true;
			LogStopInfoIfNeeded("Ghost", info, ref nextGhostStopLogFrame);
			return true;
		}

		private bool TryResolveHighestObjectRaycastHit(PhysGrabObject heldObject, float currentSurfaceY, out RaycastHit bestHigherHit)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			bestHigherHit = default(RaycastHit);
			lastGhostCandidateSource = "multi-ray";
			bool result = false;
			float highestSurfaceY = currentSurfaceY;
			Collider[] componentsInChildren = ((Component)heldObject).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && val.enabled && TryResolveHighestRaycastHitFromCollider(val, heldObject, ref highestSurfaceY, ref bestHigherHit))
				{
					result = true;
				}
			}
			return result;
		}

		private bool TryResolveHighestRaycastHitFromCollider(Collider collider, PhysGrabObject heldObject, ref float highestSurfaceY, ref RaycastHit bestHigherHit)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			bool result = false;
			List<Vector3> list = new List<Vector3>();
			CollectBottomFaceSamplePoints(collider, list);
			for (int i = 0; i < list.Count; i++)
			{
				int num = Physics.RaycastNonAlloc(list[i] + Vector3.up * 0.02f, Vector3.down, raycastHitBuffer, Plugin.LaserMaxDistance.Value, -5, (QueryTriggerInteraction)2);
				for (int j = 0; j < num; j++)
				{
					RaycastHit val = raycastHitBuffer[j];
					if (IsValidBeamHit(val, heldObject))
					{
						lastGhostCandidateHits.Add(new HitDebugInfo(val));
						if (!(((RaycastHit)(ref val)).point.y <= highestSurfaceY))
						{
							highestSurfaceY = ((RaycastHit)(ref val)).point.y;
							bestHigherHit = val;
							result = true;
						}
					}
				}
			}
			return result;
		}

		private static void CollectBottomFaceSamplePoints(Collider collider, List<Vector3> points)
		{
			//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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			points.Clear();
			if ((Object)(object)collider == (Object)null)
			{
				return;
			}
			BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null);
			if (val != null)
			{
				AddBoxBottomFacePoints(val, points);
				return;
			}
			MeshCollider val2 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null);
			if (val2 != null)
			{
				AddMeshBottomFacePoints(val2, points);
				if (points.Count > 0)
				{
					return;
				}
			}
			Bounds bounds = collider.bounds;
			points.Add(new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z));
		}

		private static void AddBoxBottomFacePoints(BoxCollider box, List<Vector3> points)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0095: 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_00a2: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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)
			Transform transform = ((Component)box).transform;
			Vector3 center = box.center;
			Vector3 val = box.size * 0.5f;
			float num = center.y - val.y;
			points.Add(transform.TransformPoint(new Vector3(center.x - val.x, num, center.z - val.z)));
			points.Add(transform.TransformPoint(new Vector3(center.x - val.x, num, center.z + val.z)));
			points.Add(transform.TransformPoint(new Vector3(center.x + val.x, num, center.z - val.z)));
			points.Add(transform.TransformPoint(new Vector3(center.x + val.x, num, center.z + val.z)));
			points.Add(transform.TransformPoint(new Vector3(center.x, num, center.z)));
		}

		private static void AddMeshBottomFacePoints(MeshCollider meshCollider, List<Vector3> points)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00de: 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_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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: 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)
			Mesh sharedMesh = meshCollider.sharedMesh;
			if ((Object)(object)sharedMesh == (Object)null)
			{
				return;
			}
			Vector3[] vertices = sharedMesh.vertices;
			Vector3[] normals = sharedMesh.normals;
			int[] triangles = sharedMesh.triangles;
			if (vertices == null || triangles == null || triangles.Length < 3)
			{
				return;
			}
			Transform transform = ((Component)meshCollider).transform;
			bool flag = normals != null && normals.Length == vertices.Length;
			for (int i = 0; i < triangles.Length; i += 3)
			{
				int num = triangles[i];
				int num2 = triangles[i + 1];
				int num3 = triangles[i + 2];
				if (num >= 0 && num2 >= 0 && num3 >= 0 && num < vertices.Length && num2 < vertices.Length && num3 < vertices.Length)
				{
					Vector3 val2;
					bool flag2;
					if (flag)
					{
						Vector3 val = (normals[num] + normals[num2] + normals[num3]) / 3f;
						val2 = transform.TransformDirection(val);
						flag2 = Vector3.Dot(((Vector3)(ref val2)).normalized, Vector3.down) >= 0.85f;
					}
					else
					{
						Vector3 val3 = transform.TransformPoint(vertices[num]);
						Vector3 val4 = transform.TransformPoint(vertices[num2]);
						Vector3 val5 = transform.TransformPoint(vertices[num3]);
						val2 = Vector3.Cross(val4 - val3, val5 - val3);
						flag2 = Vector3.Dot(((Vector3)(ref val2)).normalized, Vector3.down) >= 0.85f;
					}
					if (flag2)
					{
						points.Add(transform.TransformPoint(vertices[num]));
						points.Add(transform.TransformPoint(vertices[num2]));
						points.Add(transform.TransformPoint(vertices[num3]));
					}
				}
			}
		}

		private static void LogStopInfoIfNeeded(string systemName, HitDebugInfo info, ref int nextLogFrame)
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.EnableLogging.Value && Plugin.EnableHitDiagnostics.Value && Time.frameCount >= nextLogFrame)
			{
				nextLogFrame = Time.frameCount + 1000;
				if (!info.HasHit)
				{
					DropLaserLogger.Info("[DropLaser] " + systemName + " stop: no valid hit.");
					return;
				}
				string text = LayerMask.LayerToName(info.Layer);
				string[] obj = new string[14]
				{
					"[DropLaser] ", systemName, " stop: object='", info.ObjectName, "', tag='", info.Tag, "', layer=", null, null, null,
					null, null, null, null
				};
				int layer = info.Layer;
				obj[7] = layer.ToString();
				obj[8] = "('";
				obj[9] = text;
				obj[10] = "'), distance=";
				float distance = info.Distance;
				obj[11] = distance.ToString("0.###");
				obj[12] = ", point=";
				Vector3 point = info.Point;
				obj[13] = ((Vector3)(ref point)).ToString("F3");
				DropLaserLogger.Info(string.Concat(obj));
			}
		}

		private Vector3 GetGhostStopPoint()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ghostRoot == (Object)null)
			{
				return Vector3.zero;
			}
			return CalculateBeamOrigin(ghostRoot);
		}

		private void EnsureGhostForHeldObject(PhysGrabObject heldObject)
		{
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			if ((Object)(object)heldObject == (Object)null || ((Object)(object)heldObject == (Object)(object)ghostSource && (Object)(object)ghostRoot != (Object)null))
			{
				return;
			}
			DestroyGhost();
			ghostSource = heldObject;
			ghostRenderers.Clear();
			ghostRoot = CreateVisualOnlyGhostRoot(((Component)heldObject).gameObject);
			if ((Object)(object)ghostRoot == (Object)null)
			{
				if (ShouldLogGhostWarnings())
				{
					Plugin.log.LogWarning((object)"[DropLaser] Failed to create visual-only ghost root.");
				}
				return;
			}
			((Object)ghostRoot).name = ((Object)((Component)heldObject).gameObject).name + "_DropLaserGhost";
			Object.DontDestroyOnLoad((Object)(object)ghostRoot);
			Renderer[] componentsInChildren = ghostRoot.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (val is LineRenderer || val is TrailRenderer)
				{
					val.enabled = false;
					continue;
				}
				Material val2 = (((Object)(object)sourceBeamLine != (Object)null && (Object)(object)((Renderer)sourceBeamLine).material != (Object)null) ? ((Renderer)sourceBeamLine).material : (((Object)(object)dropBeamLine != (Object)null) ? ((Renderer)dropBeamLine).material : val.sharedMaterial));
				if ((Object)(object)val2 == (Object)null)
				{
					if (ShouldLogGhostWarnings())
					{
						Plugin.log.LogWarning((object)("[DropLaser] Ghost renderer '" + ((Object)val).name + "' has no source material; skipping."));
					}
					val.enabled = false;
				}
				else
				{
					Material material = (val.material = new Material(val2));
					ghostRenderers.Add(new GhostRendererState
					{
						Renderer = val,
						Material = material
					});
				}
			}
			if (ghostRenderers.Count == 0)
			{
				if (ShouldLogGhostWarnings())
				{
					Plugin.log.LogWarning((object)"[DropLaser] Ghost had no supported renderers; disabling ghost preview for this object.");
				}
				DestroyGhost();
			}
			else
			{
				ghostRoot.SetActive(false);
			}
		}

		private static GameObject CreateVisualOnlyGhostRoot(GameObject sourceRoot)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if ((Object)(object)sourceRoot == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject(((Object)sourceRoot).name + "_GhostRoot");
			CopyTransformOnly(sourceRoot.transform, val.transform);
			CopyVisualComponents(sourceRoot, val);
			BuildVisualHierarchy(sourceRoot.transform, val.transform);
			return val;
		}

		private static void BuildVisualHierarchy(Transform source, Transform targetParent)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (!((Object)(object)source == (Object)null) && !((Object)(object)targetParent == (Object)null))
			{
				for (int i = 0; i < source.childCount; i++)
				{
					Transform child = source.GetChild(i);
					GameObject val = new GameObject(((Object)child).name);
					Transform transform = val.transform;
					transform.SetParent(targetParent, false);
					CopyTransformOnly(child, transform);
					CopyVisualComponents(((Component)child).gameObject, val);
					BuildVisualHierarchy(child, transform);
				}
			}
		}

		private static void CopyTransformOnly(Transform source, Transform target)
		{
			//IL_0