Decompiled source of CiCisLidarVision v0.5.1

plugins/CiCisLidarVision/LidarMod.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TrinketAndBindingFramework;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LidarMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LidarMod")]
[assembly: AssemblyTitle("LidarMod")]
[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 LidarMod
{
	[BepInPlugin("com.cicismods.lidar", "CiCi's Lidar Vision", "0.5.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.cicismods.lidar";

		public const string NAME = "CiCi's Lidar Vision";

		public const string VERSION = "0.5.1";

		public const string BindingId = "cici_lidar";

		public const string ItemTag = "cici_lidar";

		public const string PrefabName = "Item_Lidar";

		public static ManualLogSource Log;

		public static Item_Object LidarTemplate;

		public static Sprite LidarHeldSprite;

		public static Sprite[] LidarSpriteFrames;

		public static Texture2D LidarTexture;

		public static Mesh LidarMesh;

		public static Material LidarMaterial;

		public static Shader LidarDotShader;

		public static GameObject LidarPrefab;

		public const float LidarVisualScale = 1.5f;

		public static readonly Vector3 OutlineHaloScale = new Vector3(1.04f, 1.04f, 1.04f);

		public static readonly Vector3 OutlineHaloOffset = Vector3.zero;

		public static Material OutlineMaterial;

		public static AudioClip ScanLoopClip;

		public static AudioClip ScanInitiateClip;

		public static AudioClip SwitchClip;

		public static Sprite BindingIcon;

		private static bool _bindingActiveCached;

		private static float _bindingActiveCacheUntil;

		private static AudioSource _scanAudioSource;

		private static AudioSource _oneShotAudioSource;

		private static readonly Dictionary<Mesh, Mesh> _invertedMeshCache = new Dictionary<Mesh, Mesh>();

		public static bool LidarBindingActive
		{
			get
			{
				if (Time.time < _bindingActiveCacheUntil)
				{
					return _bindingActiveCached;
				}
				_bindingActiveCached = IsBindingActiveNow() && IsRunLoaded();
				_bindingActiveCacheUntil = Time.time + 0.5f;
				return _bindingActiveCached;
			}
		}

		private void Awake()
		{
			//IL_0010: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("com.cicismods.lidar").PatchAll();
			LoadBundleAssets();
			LoadSideAssets();
			TrinketRegistry.RegisterBinding("cici_lidar", "Lidar Vision", "The world goes pitch black. Start with a handheld lidar scanner. Hold to scan — sprays a strip of dots wherever you look. Click to switch the line between vertical and horizontal. Enemies <color=#ED4040>red</color>, items <color=#FFD81A>yellow</color>, handholds <color=#C77BFF>purple</color>, buttons & levers <color=#4DF24D>green</color>, boxes & props <color=#C7C7C7>grey</color>.", "Trust the dots.", 1, 1f, 0f, BindingIcon, (Func<List<Item_Object>>)delegate
			{
				try
				{
					EnsureLidarTemplate();
				}
				catch (Exception ex)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)("[Lidar] EnsureLidarTemplate threw: " + ex.Message));
					}
				}
				return ((Object)(object)LidarTemplate == (Object)null) ? new List<Item_Object>() : new List<Item_Object> { LidarTemplate };
			}, (Func<List<Perk>>)null, 0);
			GameObject val = new GameObject("LidarMod_Handler")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<LidarHandler>();
			val.AddComponent<LidarDarknessHandler>();
			Log.LogInfo((object)"CiCi's Lidar Vision 0.5.1 loaded");
		}

		private static bool IsRunLoaded()
		{
			try
			{
				return (Object)(object)ENT_Player.playerObject != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsBindingActiveNow()
		{
			try
			{
				M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
				if ((Object)(object)currentGamemode == (Object)null)
				{
					return false;
				}
				SaveData saveData = StatManager.saveData;
				List<string> list = ((saveData != null) ? saveData.GetGamemodeTrinkets(currentGamemode.GetGamemodeName(true)) : null);
				if (list == null)
				{
					return false;
				}
				foreach (string item in list)
				{
					if (!string.IsNullOrEmpty(item) && item.ToLowerInvariant().Contains("cici_lidar"))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private void LoadBundleAssets()
		{
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Expected O, but got Unknown
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lidarmod");
				if (!File.Exists(text))
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)("[Lidar] Bundle not found at " + text + " — held sprite swap disabled"));
					}
					return;
				}
				AssetBundle val = AssetBundle.LoadFromFile(text);
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"[Lidar] AssetBundle.LoadFromFile returned null");
					}
					return;
				}
				Shader[] array = val.LoadAllAssets<Shader>();
				foreach (Shader val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						ManualLogSource log3 = Log;
						if (log3 != null)
						{
							log3.LogInfo((object)("[Lidar] bundle shader: " + ((Object)val2).name));
						}
						if (((Object)val2).name == "LidarMod/InstancedDot")
						{
							LidarDotShader = val2;
						}
					}
				}
				Material[] array2 = val.LoadAllAssets<Material>();
				foreach (Material val3 in array2)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					ManualLogSource log4 = Log;
					if (log4 != null)
					{
						log4.LogInfo((object)("[Lidar] bundle material: " + ((Object)val3).name));
					}
					if (!((Object)(object)LidarTexture == (Object)null) || !val3.HasProperty("_MainTex"))
					{
						continue;
					}
					Texture texture = val3.GetTexture("_MainTex");
					Texture2D val4 = (Texture2D)(object)((texture is Texture2D) ? texture : null);
					if ((Object)(object)val4 != (Object)null)
					{
						LidarTexture = val4;
						ManualLogSource log5 = Log;
						if (log5 != null)
						{
							log5.LogInfo((object)("[Lidar] using mesh texture from material: " + ((Object)val4).name));
						}
					}
				}
				if ((Object)(object)LidarTexture == (Object)null)
				{
					Texture2D[] array3 = val.LoadAllAssets<Texture2D>();
					foreach (Texture2D val5 in array3)
					{
						if (!((Object)(object)val5 == (Object)null))
						{
							ManualLogSource log6 = Log;
							if (log6 != null)
							{
								log6.LogInfo((object)("[Lidar] bundle texture: " + ((Object)val5).name));
							}
							if (((Object)val5).name == null || ((Object)val5).name.IndexOf("lidarmod", StringComparison.OrdinalIgnoreCase) < 0)
							{
								LidarTexture = val5;
								break;
							}
						}
					}
				}
				Sprite[] array4 = val.LoadAllAssets<Sprite>();
				List<Sprite> list = new List<Sprite>();
				Texture2D val6 = null;
				Sprite[] array5 = array4;
				foreach (Sprite val7 in array5)
				{
					if (!((Object)(object)val7 == (Object)null))
					{
						ManualLogSource log7 = Log;
						if (log7 != null)
						{
							log7.LogInfo((object)("[Lidar] bundle sprite: " + ((Object)val7).name));
						}
						list.Add(val7);
						if ((Object)(object)val6 == (Object)null && (Object)(object)val7.texture != (Object)null)
						{
							val6 = val7.texture;
						}
					}
				}
				list.Sort((Sprite a, Sprite b) => ExtractTrailingInt(((Object)a).name).CompareTo(ExtractTrailingInt(((Object)b).name)));
				LidarSpriteFrames = list.ToArray();
				ManualLogSource log8 = Log;
				if (log8 != null)
				{
					log8.LogInfo((object)$"[Lidar] {LidarSpriteFrames.Length} sprite frame(s) loaded from bundle");
				}
				if (LidarSpriteFrames.Length <= 1)
				{
					Texture2D val8 = val6 ?? LidarTexture;
					if ((Object)(object)val8 != (Object)null)
					{
						LidarSpriteFrames = SliceSpriteSheetWithStride(val8, 70, 134, 70, 134);
						ManualLogSource log9 = Log;
						if (log9 != null)
						{
							log9.LogInfo((object)$"[Lidar] Manual slice on '{((Object)val8).name}' produced {LidarSpriteFrames.Length} frames");
						}
					}
					else
					{
						ManualLogSource log10 = Log;
						if (log10 != null)
						{
							log10.LogWarning((object)"[Lidar] Slice fallback skipped — no atlas texture available");
						}
					}
				}
				if (LidarSpriteFrames.Length != 0)
				{
					LidarHeldSprite = LidarSpriteFrames[0];
				}
				Mesh[] array6 = val.LoadAllAssets<Mesh>();
				foreach (Mesh val9 in array6)
				{
					if (!((Object)(object)val9 == (Object)null))
					{
						Bounds bounds = val9.bounds;
						Vector3 size = ((Bounds)(ref bounds)).size;
						ManualLogSource log11 = Log;
						if (log11 != null)
						{
							log11.LogInfo((object)$"[Lidar] bundle mesh: {((Object)val9).name} bounds={size:F2}");
						}
						if ((Object)(object)LidarMesh == (Object)null)
						{
							LidarMesh = val9;
						}
					}
				}
				GameObject[] array7 = val.LoadAllAssets<GameObject>();
				foreach (GameObject val10 in array7)
				{
					if (!((Object)(object)val10 == (Object)null))
					{
						ManualLogSource log12 = Log;
						if (log12 != null)
						{
							log12.LogInfo((object)("[Lidar] bundle prefab: " + ((Object)val10).name));
						}
						if ((Object)(object)LidarPrefab == (Object)null)
						{
							LidarPrefab = val10;
						}
					}
				}
				if ((Object)(object)LidarTexture != (Object)null)
				{
					Shader val11 = Shader.Find("Dark Machine/SHDR_Base") ?? Shader.Find("Unlit/Texture");
					if ((Object)(object)val11 != (Object)null)
					{
						LidarMaterial = new Material(val11);
						if (LidarMaterial.HasProperty("_MainTex"))
						{
							LidarMaterial.SetTexture("_MainTex", (Texture)(object)LidarTexture);
						}
						else
						{
							LidarMaterial.mainTexture = (Texture)(object)LidarTexture;
						}
					}
				}
				val.Unload(false);
			}
			catch (Exception arg)
			{
				ManualLogSource log13 = Log;
				if (log13 != null)
				{
					log13.LogError((object)$"[Lidar] LoadBundleAssets failed: {arg}");
				}
			}
		}

		private void LoadSideAssets()
		{
			string? directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			ScanLoopClip = TryLoadWav(directoryName, "Lidar_Sound_Alt.wav");
			ScanInitiateClip = TryLoadWav(directoryName, "LiDAR_initiate.wav");
			SwitchClip = TryLoadWav(directoryName, "LiDAR_Switch.wav");
			BindingIcon = TryLoadSpritePng(directoryName, "LiDAR_binding.png");
		}

		private static AudioClip TryLoadWav(string dir, string filename)
		{
			string text = Path.Combine(dir, filename);
			if (!File.Exists(text))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[Lidar] Audio not found: " + filename + " (at " + text + ")"));
				}
				return null;
			}
			try
			{
				return LidarWavLoader.LoadFromFile(text, filename);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)("[Lidar] WAV load failed for " + filename + ": " + ex.Message));
				}
				return null;
			}
		}

		private static Sprite TryLoadSpritePng(string dir, string filename)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0096: 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)
			string text = Path.Combine(dir, filename);
			if (!File.Exists(text))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[Lidar] Icon not found: " + filename + " (at " + text + ")"));
				}
				return null;
			}
			try
			{
				byte[] array = File.ReadAllBytes(text);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val, array))
				{
					return null;
				}
				((Texture)val).filterMode = (FilterMode)0;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				((Object)obj).name = filename;
				Object.DontDestroyOnLoad((Object)(object)obj);
				Object.DontDestroyOnLoad((Object)(object)val);
				return obj;
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Lidar] Icon load failed for " + filename + ": " + ex.Message));
				}
				return null;
			}
		}

		public static AudioSource GetScanAudioSource()
		{
			//IL_0029: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_scanAudioSource != (Object)null)
			{
				return _scanAudioSource;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("LidarMod_ScanAudio");
			val.transform.SetParent(((Component)main).transform, false);
			val.transform.localPosition = Vector3.zero;
			((Object)val).hideFlags = (HideFlags)61;
			AudioSource val2 = val.AddComponent<AudioSource>();
			val2.spatialBlend = 0f;
			val2.playOnAwake = false;
			val2.loop = true;
			val2.volume = 0.7f;
			if ((Object)(object)ScanLoopClip != (Object)null)
			{
				val2.clip = ScanLoopClip;
			}
			_scanAudioSource = val2;
			return val2;
		}

		public static AudioSource GetOneShotAudioSource()
		{
			//IL_0029: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_oneShotAudioSource != (Object)null)
			{
				return _oneShotAudioSource;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("LidarMod_OneShotAudio");
			val.transform.SetParent(((Component)main).transform, false);
			val.transform.localPosition = Vector3.zero;
			((Object)val).hideFlags = (HideFlags)61;
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.spatialBlend = 0f;
			obj.playOnAwake = false;
			obj.loop = false;
			obj.volume = 1f;
			_oneShotAudioSource = obj;
			return obj;
		}

		public static void PlayOneShotSound(AudioClip clip)
		{
			if ((Object)(object)clip == (Object)null)
			{
				return;
			}
			AudioSource oneShotAudioSource = GetOneShotAudioSource();
			if (!((Object)(object)oneShotAudioSource == (Object)null))
			{
				oneShotAudioSource.Stop();
				if ((Object)(object)oneShotAudioSource.clip != (Object)(object)clip)
				{
					oneShotAudioSource.clip = clip;
				}
				oneShotAudioSource.Play();
			}
		}

		private static Sprite[] SliceSpriteSheetWithStride(Texture2D tex, int cellW, int cellH, int strideX, int strideY)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)tex == (Object)null || cellW <= 0 || cellH <= 0 || strideX <= 0 || strideY <= 0)
			{
				return (Sprite[])(object)new Sprite[0];
			}
			int num = (((Texture)tex).width - cellW) / strideX + 1;
			int num2 = (((Texture)tex).height - cellH) / strideY + 1;
			if (num < 1)
			{
				num = 1;
			}
			if (num2 < 1)
			{
				num2 = 1;
			}
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)($"[Lidar] Slicer — tex={((Object)tex).name} {((Texture)tex).width}x{((Texture)tex).height}, " + $"cell={cellW}x{cellH} stride={strideX}x{strideY} → cols={num} rows={num2}"));
			}
			List<Sprite> list = new List<Sprite>(num * num2);
			Rect val = default(Rect);
			for (int i = 0; i < num2; i++)
			{
				for (int j = 0; j < num; j++)
				{
					int num3 = j * strideX;
					int num4 = ((Texture)tex).height - i * strideY - cellH;
					((Rect)(ref val))..ctor((float)num3, (float)num4, (float)cellW, (float)cellH);
					Sprite val2 = Sprite.Create(tex, val, new Vector2(0.5f, 0.5f), 100f);
					((Object)val2).name = $"LiDARMod_{i * num + j}";
					list.Add(val2);
				}
			}
			return list.ToArray();
		}

		private static int ExtractTrailingInt(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return 0;
			}
			int num = s.Length - 1;
			while (num >= 0 && char.IsDigit(s[num]))
			{
				num--;
			}
			if (num == s.Length - 1)
			{
				return 0;
			}
			if (!int.TryParse(s.Substring(num + 1), out var result))
			{
				return 0;
			}
			return result;
		}

		private static void ConfigureBundlePrefabAsPickup(GameObject go)
		{
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			go.layer = 10;
			Transform[] componentsInChildren = go.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.layer = 10;
			}
			try
			{
				go.tag = "Pickupable";
			}
			catch
			{
			}
			ObjectTagger val = go.GetComponent<ObjectTagger>() ?? go.AddComponent<ObjectTagger>();
			if (val.tags == null)
			{
				val.tags = new List<string>();
			}
			if (!val.tags.Contains("Pickupable"))
			{
				val.tags.Add("Pickupable");
			}
			if (!val.tags.Contains("Item"))
			{
				val.tags.Add("Item");
			}
			if ((Object)(object)go.GetComponentInChildren<Collider>() == (Object)null)
			{
				MeshFilter[] componentsInChildren2 = go.GetComponentsInChildren<MeshFilter>(true);
				Bounds? val2 = null;
				MeshFilter[] array = componentsInChildren2;
				foreach (MeshFilter val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null))
					{
						if (!val2.HasValue)
						{
							val2 = val3.sharedMesh.bounds;
							continue;
						}
						Bounds value = val2.Value;
						((Bounds)(ref value)).Encapsulate(val3.sharedMesh.bounds);
						val2 = value;
					}
				}
				if (val2.HasValue)
				{
					BoxCollider obj2 = go.AddComponent<BoxCollider>();
					Bounds value2 = val2.Value;
					obj2.center = ((Bounds)(ref value2)).center;
					value2 = val2.Value;
					obj2.size = ((Bounds)(ref value2)).size;
				}
				else
				{
					go.AddComponent<BoxCollider>().size = new Vector3(0.6f, 0.3f, 0.3f);
				}
			}
			(go.GetComponent<Rigidbody>() ?? go.AddComponent<Rigidbody>()).mass = 0.4f;
			CL_Prop val4 = go.GetComponent<CL_Prop>() ?? go.AddComponent<CL_Prop>();
			if (val4.hitSounds == null)
			{
				val4.hitSounds = new List<PropAudioEffect>();
			}
			if (val4.dragSounds == null)
			{
				val4.dragSounds = new List<PropAudioEffect>();
			}
			if (val4.breakSounds == null)
			{
				val4.breakSounds = new List<PropAudioEffect>();
			}
			if (val4.unstickSounds == null)
			{
				val4.unstickSounds = new List<PropAudioEffect>();
			}
			if (val4.damageSounds == null)
			{
				val4.damageSounds = new List<PropAudioEffect>();
			}
		}

		internal static void ApplyGameShader(GameObject target, bool addShimmer = true)
		{
			Shader val = Shader.Find("Dark Machine/SHDR_Base") ?? Shader.Find("Unlit/Texture");
			if ((Object)(object)val == (Object)null || (Object)(object)target == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (((Object)((Component)val2).gameObject).name.StartsWith("LidarHalo_"))
				{
					continue;
				}
				Material[] materials = val2.materials;
				for (int j = 0; j < materials.Length; j++)
				{
					if (!((Object)(object)materials[j] == (Object)null))
					{
						Texture val3 = (materials[j].HasProperty("_MainTex") ? materials[j].GetTexture("_MainTex") : null);
						materials[j].shader = val;
						if ((Object)(object)val3 != (Object)null && materials[j].HasProperty("_MainTex"))
						{
							materials[j].SetTexture("_MainTex", val3);
						}
						else if ((Object)(object)LidarTexture != (Object)null && materials[j].HasProperty("_MainTex"))
						{
							materials[j].SetTexture("_MainTex", (Texture)(object)LidarTexture);
						}
						if (addShimmer)
						{
							ApplyItemShimmer(materials[j]);
						}
					}
				}
				val2.materials = materials;
			}
		}

		public static void ApplyItemShimmer(Material m)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m == (Object)null))
			{
				if (m.HasProperty("_Shimmer"))
				{
					m.SetFloat("_Shimmer", 1f);
				}
				if (m.HasProperty("_ShimmerFrequency"))
				{
					m.SetFloat("_ShimmerFrequency", 1f);
				}
				if (m.HasProperty("_ShimmerSpeed"))
				{
					m.SetFloat("_ShimmerSpeed", 1f);
				}
				if (m.HasProperty("_ShimmerOver"))
				{
					m.SetFloat("_ShimmerOver", 0f);
				}
				if (m.HasProperty("_ShimmerOffset"))
				{
					m.SetFloat("_ShimmerOffset", 0f);
				}
				if (m.HasProperty("_ShimmerTextureMix"))
				{
					m.SetFloat("_ShimmerTextureMix", 1f);
				}
				if (m.HasProperty("_ShimmerColor"))
				{
					m.SetColor("_ShimmerColor", Color.white);
				}
				if (m.HasProperty("_Shading"))
				{
					m.SetFloat("_Shading", 0.96f);
				}
				if (m.HasProperty("_DitherAmount"))
				{
					m.SetFloat("_DitherAmount", 0.63f);
				}
				if (m.HasProperty("_ROUNDMULT"))
				{
					m.SetFloat("_ROUNDMULT", 1.27f);
				}
				if (m.HasProperty("_Wiggle"))
				{
					m.SetFloat("_Wiggle", 0.0003f);
				}
				if (m.HasProperty("_WiggleFreq"))
				{
					m.SetFloat("_WiggleFreq", 2f);
				}
				if (m.HasProperty("_WiggleSpeed"))
				{
					m.SetFloat("_WiggleSpeed", 5f);
				}
			}
		}

		public static Material TryBuildGameOutlineMaterial()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Dark Machine/SHDR_Outline");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val)
			{
				name = "LidarMod_Outline_Cyan"
			};
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.6901961f, 14f / 15f, 1f, 1f);
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", val3);
			}
			if (val2.HasProperty("_Brightness"))
			{
				val2.SetFloat("_Brightness", 1f);
			}
			Object.DontDestroyOnLoad((Object)(object)val2);
			return val2;
		}

		public static Mesh GetInvertedHullMesh(Mesh source)
		{
			//IL_0058: 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_0074: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (_invertedMeshCache.TryGetValue(source, out var value))
			{
				return value;
			}
			if (!source.isReadable)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[Outline] Mesh '" + ((Object)source).name + "' is not readable (Read/Write disabled at FBX import). Halo skipped — re-export the bundle with Read/Write enabled."));
				}
				_invertedMeshCache[source] = null;
				return null;
			}
			try
			{
				Mesh val = new Mesh
				{
					name = ((Object)source).name + "_Inverted"
				};
				val.indexFormat = source.indexFormat;
				val.vertices = source.vertices;
				val.normals = source.normals;
				val.uv = source.uv;
				val.subMeshCount = source.subMeshCount;
				for (int i = 0; i < source.subMeshCount; i++)
				{
					int[] triangles = source.GetTriangles(i);
					for (int j = 0; j < triangles.Length; j += 3)
					{
						int num = triangles[j + 1];
						triangles[j + 1] = triangles[j + 2];
						triangles[j + 2] = num;
					}
					val.SetTriangles(triangles, i);
				}
				val.RecalculateBounds();
				Object.DontDestroyOnLoad((Object)(object)val);
				_invertedMeshCache[source] = val;
				return val;
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Outline] Failed to invert mesh '" + ((Object)source).name + "': " + ex.Message));
				}
				_invertedMeshCache[source] = null;
				return null;
			}
		}

		public static void EnsureHaloOnGameObject(GameObject go, Material outlineOverride = null)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			if ((Object)(object)OutlineMaterial == (Object)null)
			{
				OutlineMaterial = TryBuildGameOutlineMaterial();
			}
			Material val = outlineOverride ?? OutlineMaterial;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			MeshRenderer[] componentsInChildren = go.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null || ((Object)((Component)val2).gameObject).name.StartsWith("LidarHalo_"))
				{
					continue;
				}
				Transform val3 = null;
				foreach (Transform item in ((Component)val2).transform)
				{
					Transform val4 = item;
					if (((Object)val4).name.StartsWith("LidarHalo_"))
					{
						val3 = val4;
						break;
					}
				}
				MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
				{
					if ((Object)(object)val3 != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)val3).gameObject);
					}
					continue;
				}
				Mesh invertedHullMesh = GetInvertedHullMesh(component.sharedMesh);
				if ((Object)(object)invertedHullMesh == (Object)null)
				{
					if ((Object)(object)val3 != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)val3).gameObject);
					}
				}
				else if ((Object)(object)val3 != (Object)null)
				{
					MeshFilter component2 = ((Component)val3).GetComponent<MeshFilter>();
					if ((Object)(object)component2 != (Object)null && (Object)(object)component2.sharedMesh != (Object)(object)invertedHullMesh)
					{
						component2.sharedMesh = invertedHullMesh;
					}
					MeshRenderer component3 = ((Component)val3).GetComponent<MeshRenderer>();
					if ((Object)(object)component3 != (Object)null && (Object)(object)((Renderer)component3).sharedMaterial != (Object)(object)val)
					{
						((Renderer)component3).sharedMaterial = val;
					}
				}
				else
				{
					GameObject val5 = new GameObject("LidarHalo_" + ((Object)val2).name)
					{
						layer = ((Component)val2).gameObject.layer
					};
					val5.transform.SetParent(((Component)val2).transform, false);
					val5.transform.localPosition = OutlineHaloOffset;
					val5.transform.localRotation = Quaternion.identity;
					val5.transform.localScale = OutlineHaloScale;
					val5.AddComponent<MeshFilter>().sharedMesh = invertedHullMesh;
					MeshRenderer obj = val5.AddComponent<MeshRenderer>();
					((Renderer)obj).sharedMaterial = val;
					((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)obj).receiveShadows = false;
					((Renderer)obj).lightProbeUsage = (LightProbeUsage)0;
					((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0;
				}
			}
		}

		public static void EnsureLidarTemplate()
		{
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Expected O, but got Unknown
			if ((Object)(object)LidarTemplate != (Object)null && (Object)(object)((Component)LidarTemplate).gameObject != (Object)null)
			{
				return;
			}
			GameObject val = null;
			try
			{
				val = CL_AssetManager.GetAssetGameObject("Item_EntityScanner", "");
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[Lidar] Asset lookup threw: " + ex.Message));
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"[Lidar] Item_EntityScanner not found in asset DB — cannot build template");
				}
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val);
			val2.SetActive(false);
			((Object)val2).name = "Lidar_Template";
			((Object)val2).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val2);
			MeshFilter[] componentsInChildren = val2.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val3 in componentsInChildren)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val3);
				}
			}
			MeshRenderer[] componentsInChildren2 = val2.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val4 in componentsInChildren2)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val4);
				}
			}
			if ((Object)(object)LidarPrefab != (Object)null)
			{
				GameObject obj = Object.Instantiate<GameObject>(LidarPrefab);
				((Object)obj).name = "LidarVisual";
				obj.transform.SetParent(val2.transform, false);
				obj.transform.localPosition = Vector3.zero;
				obj.transform.localRotation = Quaternion.identity;
				obj.transform.localScale = Vector3.one * 1.5f;
			}
			else if ((Object)(object)LidarMesh != (Object)null)
			{
				GameObject val5 = new GameObject("LidarVisual");
				val5.transform.SetParent(val2.transform, false);
				val5.transform.localPosition = Vector3.zero;
				val5.transform.localRotation = Quaternion.identity;
				val5.transform.localScale = Vector3.one * 1.5f;
				val5.AddComponent<MeshFilter>().sharedMesh = LidarMesh;
				val5.AddComponent<MeshRenderer>();
			}
			ApplyGameShader(val2);
			if ((Object)(object)OutlineMaterial == (Object)null)
			{
				OutlineMaterial = TryBuildGameOutlineMaterial();
			}
			EnsureHaloOnGameObject(val2);
			if ((Object)(object)LidarMaterial == (Object)null)
			{
				componentsInChildren2 = val2.GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val6 in componentsInChildren2)
				{
					if (!((Object)(object)val6 == (Object)null) && !((Object)((Component)val6).gameObject).name.StartsWith("LidarHalo_") && (Object)(object)((Renderer)val6).sharedMaterial != (Object)null)
					{
						LidarMaterial = ((Renderer)val6).sharedMaterial;
						break;
					}
				}
			}
			Item_Object val7 = val2.GetComponent<Item_Object>();
			if ((Object)(object)val7 == (Object)null)
			{
				val7 = val2.AddComponent<Item_Object>();
			}
			if (val7.itemData == null)
			{
				val7.itemData = new Item();
			}
			val7.itemData.itemName = "Lidar Scanner";
			val7.itemData.itemTag = "cici_lidar";
			if (val7.itemData.itemTags == null)
			{
				val7.itemData.itemTags = new List<string>();
			}
			if (!val7.itemData.itemTags.Contains("cici_lidar"))
			{
				val7.itemData.itemTags.Add("cici_lidar");
			}
			if (!val7.itemData.itemTags.Contains("tool"))
			{
				val7.itemData.itemTags.Add("tool");
			}
			val7.itemData.prefabName = "Item_Lidar";
			val7.itemData.itemAsset = val7;
			val7.itemData.inventoryScale = 0.6f;
			if (val7.itemData.data == null || val7.itemData.data.Count == 0)
			{
				val7.itemData.data = new List<string> { "charge:1", "maxcharge:20", "chargerate:5", "flipped:False" };
			}
			LidarTemplate = val7;
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogInfo((object)"[Lidar] Lidar template ready (cloned Item_EntityScanner, prefabName=Item_Lidar)");
			}
		}

		public static bool IsLidarHeld()
		{
			try
			{
				ENT_Player playerObject = ENT_Player.playerObject;
				if ((Object)(object)playerObject == (Object)null || playerObject.hands == null)
				{
					return false;
				}
				Hand[] hands = playerObject.hands;
				foreach (Hand val in hands)
				{
					if (val != null)
					{
						HandItem handItem = val.GetHandItem();
						if (handItem?.item?.itemTag == "cici_lidar")
						{
							return true;
						}
						List<string> list = handItem?.item?.itemTags;
						if (list != null && list.Contains("cici_lidar"))
						{
							return true;
						}
						if (handItem?.item?.prefabName == "Item_Lidar")
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(CL_AssetManager), "GetAssetGameObject")]
	public static class LidarAssetLookupPatch
	{
		[HarmonyPostfix]
		public static void Postfix(string name, ref GameObject __result)
		{
			if (!((Object)(object)__result != (Object)null) && !(name != "Item_Lidar"))
			{
				try
				{
					Plugin.EnsureLidarTemplate();
				}
				catch
				{
				}
				if ((Object)(object)Plugin.LidarTemplate != (Object)null)
				{
					__result = ((Component)Plugin.LidarTemplate).gameObject;
				}
			}
		}
	}
	public class LidarHandler : MonoBehaviour
	{
		private struct MoverRedirect
		{
			public FieldInfo Field;
		}

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

			private object <>2__current;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					try
					{
						Plugin.EnsureLidarTemplate();
					}
					catch
					{
					}
					if ((Object)(object)Plugin.LidarTemplate == (Object)null)
					{
						return false;
					}
					Inventory instance = Inventory.instance;
					if ((Object)(object)instance == (Object)null)
					{
						return false;
					}
					if (HasLidarInInventory(instance))
					{
						return false;
					}
					try
					{
						Item clone = Plugin.LidarTemplate.itemData.GetClone((Item)null);
						instance.AddItemToInventoryScreen(new Vector3(0f, 0.1f, 1f), clone, true, false, true);
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogInfo((object)"[Lidar] Revive top-up — granted scanner");
						}
					}
					catch (Exception ex)
					{
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogWarning((object)("[Lidar] Revive top-up failed: " + ex.Message));
						}
					}
					return false;
				}
				}
			}

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

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

		private const int RaysPerFrame = 25;

		private const float MaxScanDistance = 60f;

		private const float DotSize = 0.05f;

		private const int MaxDotsTotal = 1000000;

		private const float StripVerticalHalfDeg = 25f;

		private const float DotLifetimeSec = 30f;

		private const float NearDistance = 5f;

		private const float FarDistance = 50f;

		public const float OriginSideOffset = 0.3f;

		public const float OriginUpOffset = 0.05f;

		public const float OriginForwardOffset = 0.2f;

		public const float ClickThresholdSec = 0.15f;

		private static readonly Color ColorEnemy = new Color(0.93f, 0.25f, 0.25f, 1f);

		private static readonly Color ColorItem = new Color(1f, 0.85f, 0.1f, 1f);

		private static readonly Color ColorHandhold = new Color(0.78f, 0.48f, 1f, 1f);

		private static readonly Color ColorInteractable = new Color(0.3f, 0.95f, 0.3f, 1f);

		private static readonly Color ColorProp = new Color(0.78f, 0.78f, 0.78f, 1f);

		private static readonly Color ColorNear = new Color(0.69f, 0.93f, 1f, 1f);

		private static readonly Color ColorMid = new Color(0.5f, 0.78f, 0.92f, 1f);

		private static readonly Color ColorFar = new Color(0.28f, 0.55f, 0.78f, 1f);

		private static readonly Color ColorVeryFar = new Color(0.1f, 0.3f, 0.55f, 1f);

		private LidarGPURenderer _gpu;

		private const float DotMinPixelSize = 6f;

		private readonly Dictionary<int, ParticleSystem> _stickyPS = new Dictionary<int, ParticleSystem>();

		private readonly LinkedList<int> _stickyLRU = new LinkedList<int>();

		private readonly Dictionary<int, LinkedListNode<int>> _stickyLRUNodes = new Dictionary<int, LinkedListNode<int>>();

		private const int StickyPSMaxParticles = 20000;

		private const int StickyPoolMax = 50;

		private const float StickyDotSize = 0.1f;

		private readonly Dictionary<int, Color> _colorByColliderID = new Dictionary<int, Color>();

		private const int ColorCacheMax = 5000;

		private readonly RaycastHit[] _raycastHitBuf = (RaycastHit[])(object)new RaycastHit[8];

		private bool _wasActive;

		private int _activeSeed;

		private bool _wasDead;

		private static readonly FieldInfo _gManDeadField = AccessTools.Field(typeof(CL_GameManager), "dead");

		public static bool _initiateFiredThisPress;

		private float _scanLoopReadyAt;

		public static bool IsScanning;

		public static bool HorizontalScan;

		private const float StripHorizontalHalfDeg = 25f;

		private float _animTime;

		private const float AnimFrameSec = 0.08f;

		private static Material _cleanSpriteMaterial;

		private static readonly List<MeshFilter> _ovMeshFilters = new List<MeshFilter>(8);

		private static readonly List<MeshRenderer> _ovMeshRenderers = new List<MeshRenderer>(8);

		private static readonly List<SpriteRenderer> _ovSpriteRenderers = new List<SpriteRenderer>(16);

		private static readonly List<CL_Lamp> _ovLamps = new List<CL_Lamp>(4);

		private static readonly List<Light> _ovLights = new List<Light>(4);

		public const string HeldLightName = "LidarMod_HeldLight";

		private static readonly Color HeldLightColor = new Color(0.6901961f, 14f / 15f, 1f);

		private const float HeldLightRange = 2f;

		private const float HeldLightIntensityScanning = 3f;

		private const float HeldLightIntensityIdle = 0f;

		private const int LaserPoolSize = 200;

		private const float LaserLifetimeSec = 0.08f;

		private const float LaserWidth = 0.01f;

		private LineRenderer[] _laserPool;

		private float[] _laserExpireTime;

		private int _laserNextSlot;

		private bool _laserPoolReady;

		private const float LaserVisibleFraction = 0.75f;

		private const int SaveFileMagic = 1279537665;

		private static readonly Color GradientSentinel = new Color(0f, 0f, 0f, 0f);

		private static readonly List<MonoBehaviour> _mbScratch = new List<MonoBehaviour>(8);

		private static readonly HashSet<string> MoverTypeNames = new HashSet<string> { "UT_Move", "UT_PathMover", "UT_LerpBetween", "UT_SoftParent", "UT_RotateToFaceDirection", "UT_Platform", "UT_Door", "UT_Spin" };

		private static readonly Dictionary<Type, MoverRedirect> _moverRedirectCache = new Dictionary<Type, MoverRedirect>();

		private static readonly Dictionary<int, Transform> _movingParentCache = new Dictionary<int, Transform>();

		private static readonly HashSet<int> _meshScanAugmented = new HashSet<int>();

		private static readonly Dictionary<Type, bool> _isPusheableType = new Dictionary<Type, bool>();

		private static readonly List<MeshFilter> _meshScanScratch = new List<MeshFilter>(16);

		public static bool ScanInputActive { get; internal set; }

		public static float ScanPressTime { get; internal set; }

		private void Update()
		{
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			IsScanning = false;
			bool lidarBindingActive = Plugin.LidarBindingActive;
			int num = (lidarBindingActive ? TryGetCurrentSeed() : 0);
			if (lidarBindingActive != _wasActive)
			{
				if (lidarBindingActive)
				{
					ClearAllDotState();
					_activeSeed = num;
					LoadDotsFromDisk(_activeSeed);
				}
				else
				{
					SaveDotsToDisk(_activeSeed);
					ClearAllDotState();
				}
				_wasActive = lidarBindingActive;
			}
			else if (lidarBindingActive && num != 0 && num != _activeSeed)
			{
				SaveDotsToDisk(_activeSeed);
				ClearAllDotState();
				_activeSeed = num;
				LoadDotsFromDisk(_activeSeed);
			}
			if (!lidarBindingActive)
			{
				return;
			}
			DetectRespawnAndTopUp();
			UpdateLaserPool();
			int num2;
			float num3;
			if (Plugin.IsLidarHeld())
			{
				num2 = (ScanInputActive ? 1 : 0);
				if (num2 != 0)
				{
					num3 = Time.time - ScanPressTime;
					goto IL_00c2;
				}
			}
			else
			{
				num2 = 0;
			}
			num3 = 0f;
			goto IL_00c2;
			IL_00c2:
			float num4 = num3;
			if (num2 != 0 && !_initiateFiredThisPress && num4 >= 0.15f)
			{
				_initiateFiredThisPress = true;
				Plugin.PlayOneShotSound(Plugin.ScanInitiateClip);
				float num5 = (((Object)(object)Plugin.ScanInitiateClip != (Object)null) ? Plugin.ScanInitiateClip.length : 1f);
				_scanLoopReadyAt = Time.time + num5;
			}
			bool num6 = (IsScanning = num2 != 0 && _initiateFiredThisPress && Time.time >= _scanLoopReadyAt);
			DriveScanAudio(num6);
			if (Plugin.LidarSpriteFrames != null && Plugin.LidarSpriteFrames.Length != 0)
			{
				int num7 = Plugin.LidarSpriteFrames.Length;
				if (IsScanning && num7 > 1)
				{
					_animTime += Time.deltaTime;
					int num8 = num7 - 1;
					int num9 = 1 + (int)(_animTime / 0.08f) % num8;
					Plugin.LidarHeldSprite = Plugin.LidarSpriteFrames[num9];
				}
				else
				{
					_animTime = 0f;
					Plugin.LidarHeldSprite = Plugin.LidarSpriteFrames[0];
				}
			}
			if (!num6)
			{
				return;
			}
			EnsureGPURenderer();
			if (_gpu == null || !_gpu.IsReady)
			{
				return;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return;
			}
			Vector3 val = ComputeOriginForCurrentHand(((Component)main).transform);
			ENT_Player playerObject = ENT_Player.playerObject;
			Transform val2 = (((Object)(object)playerObject != (Object)null) ? ((Component)playerObject).transform : null);
			for (int i = 0; i < 25; i++)
			{
				Quaternion val3;
				if (HorizontalScan)
				{
					float num10 = Random.Range(-25f, 25f);
					val3 = Quaternion.Euler(0f, num10, 0f);
				}
				else
				{
					val3 = Quaternion.Euler(Random.Range(-25f, 25f), 0f, 0f);
				}
				Vector3 val4 = ((Component)main).transform.rotation * (val3 * Vector3.forward);
				int num11 = Physics.RaycastNonAlloc(val, val4, _raycastHitBuf, 60f, -1, (QueryTriggerInteraction)2);
				if (num11 == 0)
				{
					continue;
				}
				int num12 = -1;
				float num13 = float.MaxValue;
				for (int j = 0; j < num11; j++)
				{
					Collider collider = ((RaycastHit)(ref _raycastHitBuf[j])).collider;
					if (!((Object)(object)collider == (Object)null) && (!((Object)(object)val2 != (Object)null) || !((Component)collider).transform.IsChildOf(val2)) && (!collider.isTrigger || !((Object)(object)((Component)collider).GetComponent<LidarMeshScanMarker>() == (Object)null)) && ((RaycastHit)(ref _raycastHitBuf[j])).distance < num13)
					{
						num13 = ((RaycastHit)(ref _raycastHitBuf[j])).distance;
						num12 = j;
					}
				}
				if (num12 >= 0)
				{
					RaycastHit hit = _raycastHitBuf[num12];
					Color color = ChooseDotColor(hit);
					Transform val5 = ResolveMovingParent(hit);
					if ((Object)(object)val5 != (Object)null)
					{
						EmitStickyDot(val5, ((RaycastHit)(ref hit)).point, color);
					}
					else
					{
						EmitDot(((RaycastHit)(ref hit)).point, color);
					}
					EmitLaser(val, ((RaycastHit)(ref hit)).point, color);
				}
			}
		}

		private void EnsureLaserPool()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (_laserPoolReady)
			{
				return;
			}
			_laserPool = (LineRenderer[])(object)new LineRenderer[200];
			_laserExpireTime = new float[200];
			Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
			Material val2 = ((!((Object)(object)val != (Object)null)) ? ((Material)null) : new Material(val));
			for (int i = 0; i < 200; i++)
			{
				GameObject val3 = new GameObject("LidarLaser_" + i)
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)val3);
				val3.SetActive(false);
				LineRenderer val4 = val3.AddComponent<LineRenderer>();
				val4.useWorldSpace = true;
				val4.positionCount = 2;
				val4.startWidth = 0.01f;
				val4.endWidth = 0.01f;
				((Renderer)val4).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val4).receiveShadows = false;
				((Renderer)val4).lightProbeUsage = (LightProbeUsage)0;
				((Renderer)val4).reflectionProbeUsage = (ReflectionProbeUsage)0;
				if ((Object)(object)val2 != (Object)null)
				{
					((Renderer)val4).material = val2;
				}
				_laserPool[i] = val4;
				_laserExpireTime[i] = 0f;
			}
			_laserPoolReady = true;
		}

		private void EmitLaser(Vector3 from, Vector3 to, Color color)
		{
			//IL_001e: 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_002d: 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_0034: 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)
			EnsureLaserPool();
			if (_laserPool != null)
			{
				LineRenderer val = _laserPool[_laserNextSlot];
				val.startColor = color;
				val.endColor = color;
				val.SetPosition(0, Vector3.Lerp(from, to, 0.25f));
				val.SetPosition(1, to);
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
				}
				_laserExpireTime[_laserNextSlot] = Time.time + 0.08f;
				_laserNextSlot = (_laserNextSlot + 1) % 200;
			}
		}

		private void UpdateLaserPool()
		{
			//IL_001d: 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_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_007b: 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)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (!_laserPoolReady)
			{
				return;
			}
			float time = Time.time;
			Camera main = Camera.main;
			bool flag = (Object)(object)main != (Object)null;
			Vector3 val = Vector3.zero;
			if (flag)
			{
				val = ComputeOriginForCurrentHand(((Component)main).transform);
			}
			for (int i = 0; i < 200; i++)
			{
				LineRenderer val2 = _laserPool[i];
				if (!((Object)(object)val2 == (Object)null) && ((Component)val2).gameObject.activeSelf)
				{
					if (_laserExpireTime[i] <= time)
					{
						((Component)val2).gameObject.SetActive(false);
					}
					else if (flag)
					{
						Vector3 position = val2.GetPosition(1);
						val2.SetPosition(0, Vector3.Lerp(val, position, 0.25f));
					}
				}
			}
		}

		private static void OverrideHeldVisuals()
		{
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			ENT_Player playerObject = ENT_Player.playerObject;
			if (playerObject?.hands == null)
			{
				return;
			}
			Hand[] hands = playerObject.hands;
			foreach (Hand val in hands)
			{
				if (val == null)
				{
					continue;
				}
				HandItem handItem = val.GetHandItem();
				if ((Object)(object)handItem == (Object)null || !LidarItemId.IsOurs(handItem))
				{
					continue;
				}
				if ((Object)(object)Plugin.LidarMesh != (Object)null)
				{
					((Component)handItem).GetComponentsInChildren<MeshFilter>(true, _ovMeshFilters);
					for (int j = 0; j < _ovMeshFilters.Count; j++)
					{
						MeshFilter val2 = _ovMeshFilters[j];
						if (!((Object)(object)val2 == (Object)null) && (Object)(object)val2.sharedMesh != (Object)(object)Plugin.LidarMesh)
						{
							val2.sharedMesh = Plugin.LidarMesh;
						}
					}
					if ((Object)(object)Plugin.LidarMaterial != (Object)null)
					{
						((Component)handItem).GetComponentsInChildren<MeshRenderer>(true, _ovMeshRenderers);
						for (int k = 0; k < _ovMeshRenderers.Count; k++)
						{
							MeshRenderer val3 = _ovMeshRenderers[k];
							if (!((Object)(object)val3 == (Object)null) && (Object)(object)((Renderer)val3).sharedMaterial != (Object)(object)Plugin.LidarMaterial)
							{
								((Renderer)val3).sharedMaterial = Plugin.LidarMaterial;
							}
						}
					}
				}
				if ((Object)(object)Plugin.LidarHeldSprite != (Object)null)
				{
					((Component)handItem).GetComponentsInChildren<SpriteRenderer>(true, _ovSpriteRenderers);
					for (int l = 0; l < _ovSpriteRenderers.Count; l++)
					{
						SpriteRenderer val4 = _ovSpriteRenderers[l];
						if ((Object)(object)val4 == (Object)null)
						{
							continue;
						}
						string obj = ((Object)((Component)val4).gameObject).name ?? "";
						string text = (((Object)(object)val4.sprite != (Object)null) ? ((Object)val4.sprite).name : "");
						bool flag = text.StartsWith("HND_F") || text.StartsWith("HND_B");
						if (obj == "Item_EntityScanner")
						{
							if ((Object)(object)val4.sprite != (Object)(object)Plugin.LidarHeldSprite)
							{
								val4.sprite = Plugin.LidarHeldSprite;
							}
							if (val4.flipX)
							{
								val4.flipX = false;
							}
							if (val4.flipY)
							{
								val4.flipY = false;
							}
							if (val4.color != Color.white)
							{
								val4.color = Color.white;
							}
							if (!((Renderer)val4).enabled)
							{
								((Renderer)val4).enabled = true;
							}
							if ((Object)(object)_cleanSpriteMaterial == (Object)null)
							{
								Shader val5 = Shader.Find("Sprites/Default");
								if ((Object)(object)val5 != (Object)null)
								{
									_cleanSpriteMaterial = new Material(val5);
								}
							}
							if ((Object)(object)_cleanSpriteMaterial != (Object)null && (Object)(object)((Renderer)val4).sharedMaterial != (Object)(object)_cleanSpriteMaterial)
							{
								((Renderer)val4).sharedMaterial = _cleanSpriteMaterial;
							}
						}
						else if (!flag && ((Renderer)val4).enabled)
						{
							((Renderer)val4).enabled = false;
						}
					}
				}
				((Component)handItem).GetComponentsInChildren<CL_Lamp>(true, _ovLamps);
				for (int m = 0; m < _ovLamps.Count; m++)
				{
					CL_Lamp val6 = _ovLamps[m];
					if (!((Object)(object)val6 == (Object)null))
					{
						if (((Behaviour)val6).enabled)
						{
							((Behaviour)val6).enabled = false;
						}
						val6.lampActive = false;
					}
				}
				((Component)handItem).GetComponentsInChildren<Light>(true, _ovLights);
				for (int n = 0; n < _ovLights.Count; n++)
				{
					Light val7 = _ovLights[n];
					if (!((Object)(object)val7 == (Object)null) && (!((Object)(object)((Component)val7).gameObject != (Object)null) || ((Object)((Component)val7).gameObject).name == null || !((Object)((Component)val7).gameObject).name.StartsWith("LidarMod_")) && ((Behaviour)val7).enabled)
					{
						((Behaviour)val7).enabled = false;
					}
				}
				((Component)handItem).GetComponentsInChildren<MeshRenderer>(true, _ovMeshRenderers);
				for (int num = 0; num < _ovMeshRenderers.Count; num++)
				{
					MeshRenderer val8 = _ovMeshRenderers[num];
					if (!((Object)(object)val8 == (Object)null) && (!((Object)(object)((Component)val8).gameObject != (Object)null) || ((Object)((Component)val8).gameObject).name == null || !((Object)((Component)val8).gameObject).name.StartsWith("LidarMod_")) && ((Renderer)val8).enabled)
					{
						((Renderer)val8).enabled = false;
					}
				}
				UpdateHeldLight(((Component)handItem).gameObject, IsScanning);
			}
		}

		private static void UpdateHeldLight(GameObject hiGo, bool scanning)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hiGo == (Object)null)
			{
				return;
			}
			Transform val = hiGo.transform.Find("LidarMod_HeldLight");
			Light val2;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).GetComponent<Light>();
			}
			else
			{
				GameObject val3 = new GameObject("LidarMod_HeldLight");
				val3.transform.SetParent(hiGo.transform, false);
				val3.transform.localPosition = new Vector3(0f, 0f, 0.2f);
				val2 = val3.AddComponent<Light>();
				val2.type = (LightType)2;
				val2.shadows = (LightShadows)0;
				val2.color = HeldLightColor;
				val2.range = 2f;
			}
			if (!((Object)(object)val2 == (Object)null))
			{
				if (val2.color != HeldLightColor)
				{
					val2.color = HeldLightColor;
				}
				if (val2.range != 2f)
				{
					val2.range = 2f;
				}
				float num = (scanning ? 3f : 0f);
				if (val2.intensity != num)
				{
					val2.intensity = num;
				}
				if (((Behaviour)val2).enabled != scanning)
				{
					((Behaviour)val2).enabled = scanning;
				}
			}
		}

		private void LateUpdate()
		{
			OverrideHeldVisuals();
			_gpu?.Render();
		}

		private void OnDestroy()
		{
			_gpu?.Dispose();
			_gpu = null;
		}

		private static Vector3 ComputeOriginForCurrentHand(Transform camT)
		{
			//IL_006c: 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)
			//IL_007e: 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_0089: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f;
			try
			{
				ENT_Player playerObject = ENT_Player.playerObject;
				if (playerObject?.hands != null)
				{
					for (int i = 0; i < playerObject.hands.Length; i++)
					{
						Hand val = playerObject.hands[i];
						if (val != null)
						{
							HandItem handItem = val.GetHandItem();
							if (!((Object)(object)handItem == (Object)null) && LidarItemId.IsOurs(handItem))
							{
								num = ((i == 0) ? (-1f) : 1f);
								break;
							}
						}
					}
				}
			}
			catch
			{
			}
			return camT.position + camT.right * (0.3f * num) + camT.up * 0.05f + camT.forward * 0.2f;
		}

		private static Vector3 GetLidarOrigin(Transform camFallback)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ENT_Player playerObject = ENT_Player.playerObject;
				if (playerObject?.hands != null)
				{
					Hand[] hands = playerObject.hands;
					foreach (Hand val in hands)
					{
						if (val == null)
						{
							continue;
						}
						HandItem handItem = val.GetHandItem();
						if (!((Object)(object)handItem == (Object)null))
						{
							Item item = handItem.item;
							if (item != null && (item.itemTag == "cici_lidar" || (item.itemTags != null && item.itemTags.Contains("cici_lidar")) || item.prefabName == "Item_Lidar") && (Object)(object)((Component)handItem).transform != (Object)null)
							{
								return ((Component)handItem).transform.position;
							}
						}
					}
				}
			}
			catch
			{
			}
			return camFallback.position;
		}

		private static int TryGetCurrentSeed()
		{
			try
			{
				return ((Object)(object)WorldLoader.instance != (Object)null) ? WorldLoader.instance.startingSeed : 0;
			}
			catch
			{
				return 0;
			}
		}

		private static string GetSaveDir()
		{
			return Path.Combine(Paths.ConfigPath, "lidardots");
		}

		private static string GetSavePath(int seed)
		{
			return Path.Combine(GetSaveDir(), seed + ".bin");
		}

		private void SaveDotsToDisk(int seed)
		{
			//IL_0088: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (seed == 0 || _gpu == null || _gpu.LiveCount <= 0)
				{
					return;
				}
				int liveCount = _gpu.LiveCount;
				Vector3[] positionsBuffer = _gpu.PositionsBuffer;
				Vector4[] colorsBuffer = _gpu.ColorsBuffer;
				Directory.CreateDirectory(GetSaveDir());
				using (FileStream output = File.Create(GetSavePath(seed)))
				{
					using BinaryWriter binaryWriter = new BinaryWriter(output);
					binaryWriter.Write(1279537665);
					binaryWriter.Write(seed);
					binaryWriter.Write(liveCount);
					for (int i = 0; i < liveCount; i++)
					{
						Vector3 val = positionsBuffer[i];
						Vector4 val2 = colorsBuffer[i];
						binaryWriter.Write(val.x);
						binaryWriter.Write(val.y);
						binaryWriter.Write(val.z);
						binaryWriter.Write((byte)Mathf.Clamp(Mathf.RoundToInt(val2.x * 255f), 0, 255));
						binaryWriter.Write((byte)Mathf.Clamp(Mathf.RoundToInt(val2.y * 255f), 0, 255));
						binaryWriter.Write((byte)Mathf.Clamp(Mathf.RoundToInt(val2.z * 255f), 0, 255));
						binaryWriter.Write((byte)Mathf.Clamp(Mathf.RoundToInt(val2.w * 255f), 0, 255));
					}
				}
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Lidar] Saved {liveCount} dots → seed {seed}");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Lidar] Save failed: " + ex.Message));
				}
			}
		}

		private void LoadDotsFromDisk(int seed)
		{
			//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)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (seed == 0)
				{
					return;
				}
				string savePath = GetSavePath(seed);
				if (!File.Exists(savePath))
				{
					return;
				}
				EnsureGPURenderer();
				if (_gpu == null || !_gpu.IsReady)
				{
					return;
				}
				using FileStream input = File.OpenRead(savePath);
				using BinaryReader binaryReader = new BinaryReader(input);
				if (binaryReader.ReadInt32() != 1279537665 || binaryReader.ReadInt32() != seed)
				{
					return;
				}
				int num = binaryReader.ReadInt32();
				if (num > 0)
				{
					if (num > 1000000)
					{
						num = 1000000;
					}
					Vector3[] array = (Vector3[])(object)new Vector3[num];
					Vector4[] array2 = (Vector4[])(object)new Vector4[num];
					for (int i = 0; i < num; i++)
					{
						float num2 = binaryReader.ReadSingle();
						float num3 = binaryReader.ReadSingle();
						float num4 = binaryReader.ReadSingle();
						byte b = binaryReader.ReadByte();
						byte b2 = binaryReader.ReadByte();
						byte b3 = binaryReader.ReadByte();
						byte b4 = binaryReader.ReadByte();
						array[i] = new Vector3(num2, num3, num4);
						array2[i] = new Vector4((float)(int)b / 255f, (float)(int)b2 / 255f, (float)(int)b3 / 255f, (float)(int)b4 / 255f);
					}
					_gpu.LoadBulk(array, array2, num);
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"[Lidar] Loaded {num} dots ← seed {seed}");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Lidar] Load failed: " + ex.Message));
				}
			}
		}

		private void DetectRespawnAndTopUp()
		{
			bool flag;
			try
			{
				flag = _gManDeadField != null && (bool)_gManDeadField.GetValue(null);
			}
			catch
			{
				return;
			}
			bool num = _wasDead && !flag;
			_wasDead = flag;
			if (num && Plugin.LidarBindingActive)
			{
				((MonoBehaviour)this).StartCoroutine(TopUpLidarNextFrame());
			}
		}

		[IteratorStateMachine(typeof(<TopUpLidarNextFrame>d__87))]
		private IEnumerator TopUpLidarNextFrame()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TopUpLidarNextFrame>d__87(0);
		}

		private static bool HasLidarInInventory(Inventory inv)
		{
			if (inv.bagItems != null)
			{
				foreach (Item bagItem in inv.bagItems)
				{
					if (IsLidarItem(bagItem))
					{
						return true;
					}
				}
			}
			if (inv.itemHands != null)
			{
				ItemHand[] itemHands = inv.itemHands;
				foreach (ItemHand val in itemHands)
				{
					if (val != null && IsLidarItem(val.currentItem))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool IsLidarItem(Item it)
		{
			if (it == null)
			{
				return false;
			}
			if (it.prefabName == "Item_Lidar")
			{
				return true;
			}
			if (it.itemTag == "cici_lidar")
			{
				return true;
			}
			if (it.itemTags != null && it.itemTags.Contains("cici_lidar"))
			{
				return true;
			}
			return false;
		}

		private static Color DistanceGradient(float distance)
		{
			//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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.InverseLerp(5f, 50f, distance);
			if (num < 0.33f)
			{
				return Color.Lerp(ColorNear, ColorMid, num / 0.33f);
			}
			if (num < 0.67f)
			{
				return Color.Lerp(ColorMid, ColorFar, (num - 0.33f) / 0.34f);
			}
			return Color.Lerp(ColorFar, ColorVeryFar, (num - 0.67f) / 0.33f);
		}

		private Color ChooseDotColor(RaycastHit hit)
		{
			//IL_0066: 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_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_0032: 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_0064: 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)
			Collider collider = ((RaycastHit)(ref hit)).collider;
			if ((Object)(object)collider != (Object)null)
			{
				int instanceID = ((Object)collider).GetInstanceID();
				if (_colorByColliderID.TryGetValue(instanceID, out var value))
				{
					return value;
				}
				Color val = ChooseDotColorUncached(hit);
				if (!IsDistanceGradient(val))
				{
					if (_colorByColliderID.Count >= 5000)
					{
						_colorByColliderID.Clear();
					}
					_colorByColliderID[instanceID] = val;
				}
				return val;
			}
			return GradientSentinel;
		}

		private static bool IsDistanceGradient(Color c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return c.a < 0.5f;
		}

		private Color ChooseDotColorUncached(RaycastHit hit)
		{
			//IL_00b1: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0097: 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)
			if ((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null)
			{
				if ((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Item_Object>() != (Object)null)
				{
					return ColorItem;
				}
				if (HasDenizenInParent(((RaycastHit)(ref hit)).collider))
				{
					return ColorEnemy;
				}
				ObjectTagger componentInParent = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<ObjectTagger>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.HasTag("Enemy"))
				{
					return ColorEnemy;
				}
				if ((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<CL_Handhold>() != (Object)null)
				{
					return ColorHandhold;
				}
				if ((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<CL_Prop>() != (Object)null)
				{
					return ColorProp;
				}
				if (((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Clickable>() != null)
				{
					return ColorInteractable;
				}
			}
			return GradientSentinel;
		}

		private static bool HasDenizenInParent(Collider col)
		{
			if ((Object)(object)col == (Object)null)
			{
				return false;
			}
			((Component)col).GetComponentsInParent<MonoBehaviour>(true, _mbScratch);
			for (int i = 0; i < _mbScratch.Count; i++)
			{
				MonoBehaviour val = _mbScratch[i];
				if (!((Object)(object)val == (Object)null) && ((object)val).GetType().Name.StartsWith("DEN_"))
				{
					return true;
				}
			}
			return false;
		}

		private static void DriveScanAudio(bool shouldPlay)
		{
			AudioSource scanAudioSource = Plugin.GetScanAudioSource();
			if ((Object)(object)scanAudioSource == (Object)null)
			{
				return;
			}
			if ((Object)(object)Plugin.ScanLoopClip != (Object)null && (Object)(object)scanAudioSource.clip != (Object)(object)Plugin.ScanLoopClip)
			{
				scanAudioSource.clip = Plugin.ScanLoopClip;
			}
			if (shouldPlay)
			{
				if ((Object)(object)scanAudioSource.clip != (Object)null && !scanAudioSource.isPlaying)
				{
					scanAudioSource.Play();
				}
			}
			else if (scanAudioSource.isPlaying)
			{
				scanAudioSource.Stop();
			}
		}

		private void EnsureGPURenderer()
		{
			//IL_004e: 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_0058: 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)
			if (_gpu == null || !_gpu.IsReady)
			{
				if (_gpu == null)
				{
					_gpu = new LidarGPURenderer(1000000, 0.05f, 6f);
				}
				_gpu.Initialize(Plugin.LidarDotShader);
				_gpu.SetGradient(ColorNear, ColorMid, ColorFar, ColorVeryFar, 5f, 50f);
			}
		}

		private void EmitDot(Vector3 pos, Color color)
		{
			//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)
			if (_gpu == null || !_gpu.IsReady)
			{
				EnsureGPURenderer();
			}
			_gpu?.Emit(pos, color);
		}

		private static Transform ResolveMoverAnchor(MonoBehaviour mb)
		{
			Type type = ((object)mb).GetType();
			if (!_moverRedirectCache.TryGetValue(type, out var value))
			{
				value = default(MoverRedirect);
				if (type.Name == "UT_PathMover")
				{
					value.Field = type.GetField("moveObject", BindingFlags.Instance | BindingFlags.Public);
				}
				_moverRedirectCache[type] = value;
			}
			if (value.Field != null)
			{
				object? value2 = value.Field.GetValue(mb);
				Transform val = (Transform)((value2 is Transform) ? value2 : null);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return ((Component)mb).transform;
		}

		private static bool ImplementsPusheable(Type t)
		{
			if (_isPusheableType.TryGetValue(t, out var value))
			{
				return value;
			}
			Type[] interfaces = t.GetInterfaces();
			bool flag = false;
			for (int i = 0; i < interfaces.Length; i++)
			{
				if (interfaces[i].Name == "Pusheable")
				{
					flag = true;
					break;
				}
			}
			_isPusheableType[t] = flag;
			return flag;
		}

		private static Transform ResolveMovingParent(RaycastHit hit)
		{
			if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
			{
				return null;
			}
			if ((Object)(object)((RaycastHit)(ref hit)).rigidbody != (Object)null)
			{
				return ((Component)((RaycastHit)(ref hit)).rigidbody).transform;
			}
			int instanceID = ((Object)((RaycastHit)(ref hit)).collider).GetInstanceID();
			if (_movingParentCache.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			Transform val = null;
			Transform val2 = ((Component)((RaycastHit)(ref hit)).collider).transform;
			while ((Object)(object)val2 != (Object)null)
			{
				if ((Object)(object)((Component)val2).GetComponent<Animator>() != (Object)null)
				{
					val = val2;
					break;
				}
				if ((Object)(object)((Component)val2).GetComponent<NavMeshAgent>() != (Object)null)
				{
					val = val2;
					break;
				}
				((Component)val2).GetComponents<MonoBehaviour>(_mbScratch);
				for (int i = 0; i < _mbScratch.Count; i++)
				{
					MonoBehaviour val3 = _mbScratch[i];
					if (!((Object)(object)val3 == (Object)null))
					{
						Type type = ((object)val3).GetType();
						string name = type.Name;
						if (name.StartsWith("DEN_"))
						{
							val = val2;
							break;
						}
						if (MoverTypeNames.Contains(name))
						{
							val = ResolveMoverAnchor(val3);
							break;
						}
						if (ImplementsPusheable(type))
						{
							val = val2;
							break;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
				val2 = val2.parent;
			}
			_movingParentCache[instanceID] = val;
			if ((Object)(object)val != (Object)null && _meshScanAugmented.Add(((Object)val).GetInstanceID()))
			{
				AugmentMeshScanColliders(val);
			}
			try
			{
				string name2 = ((Object)((Component)((RaycastHit)(ref hit)).collider).gameObject).name;
				string text = (((Object)(object)((Component)((RaycastHit)(ref hit)).collider).transform.root != (Object)null) ? ((Object)((Component)((RaycastHit)(ref hit)).collider).transform.root).name : "(no-root)");
				if ((Object)(object)val != (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[MoverDbg] HIT col='" + name2 + "' root='" + text + "' -> sticky parent='" + ((Object)val).name + "'"));
					}
				}
				else
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("[MoverDbg] HIT col='" + name2 + "' root='" + text + "' -> STATIC (no mover detected)"));
					}
				}
			}
			catch
			{
			}
			return val;
		}

		private static void AugmentMeshScanColliders(Transform parent)
		{
			if ((Object)(object)parent == (Object)null)
			{
				return;
			}
			try
			{
				((Component)parent).GetComponentsInChildren<MeshFilter>(true, _meshScanScratch);
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				int num4 = 0;
				for (int i = 0; i < _meshScanScratch.Count; i++)
				{
					num++;
					MeshFilter val = _meshScanScratch[i];
					if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null)
					{
						num4++;
						continue;
					}
					GameObject gameObject = ((Component)val).gameObject;
					if ((Object)(object)gameObject.GetComponent<LidarMeshScanMarker>() != (Object)null)
					{
						continue;
					}
					if ((Object)(object)gameObject.GetComponent<Collider>() != (Object)null)
					{
						num3++;
						continue;
					}
					try
					{
						MeshCollider obj = gameObject.AddComponent<MeshCollider>();
						obj.sharedMesh = val.sharedMesh;
						obj.convex = true;
						((Collider)obj).isTrigger = true;
						gameObject.AddComponent<LidarMeshScanMarker>();
						num2++;
					}
					catch (Exception ex)
					{
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogInfo((object)("[MeshScan] augment failed '" + ((Object)gameObject).name + "': " + ex.Message));
						}
					}
				}
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[MeshScan] augmented parent='{((Object)parent).name}': considered={num} added={num2} alreadyCollider={num3} noMesh={num4}");
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("[MeshScan] augment error: " + ex2.Message));
				}
			}
		}

		private void ClearAllDotState()
		{
			_gpu?.Clear();
			ClearStickyPool();
			_colorByColliderID.Clear();
			_movingParentCache.Clear();
		}

		private void EmitStickyDot(Transform parentTransform, Vector3 worldPos, Color color)
		{
			//IL_000a: 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_006d: 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_0073: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00b5: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parentTransform == (Object)null)
			{
				EmitDot(worldPos, color);
				return;
			}
			int instanceID = ((Object)parentTransform).GetInstanceID();
			if (!_stickyPS.TryGetValue(instanceID, out var value) || (Object)(object)value == (Object)null)
			{
				if (_stickyPS.Count >= 50)
				{
					EvictOldestSticky();
				}
				value = CreateStickyParticleSystem(parentTransform);
				_stickyPS[instanceID] = value;
				TouchSticky(instanceID);
			}
			else
			{
				TouchSticky(instanceID);
			}
			Vector3 position = parentTransform.InverseTransformPoint(worldPos);
			EmitParams val = default(EmitParams);
			((EmitParams)(ref val)).position = position;
			((EmitParams)(ref val)).startColor = Color32.op_Implicit(color);
			((EmitParams)(ref val)).startSize = 0.1f;
			((EmitParams)(ref val)).startLifetime = 30f;
			((EmitParams)(ref val)).velocity = Vector3.zero;
			EmitParams val2 = val;
			value.Emit(val2, 1);
		}

		private void TouchSticky(int key)
		{
			if (_stickyLRUNodes.TryGetValue(key, out var value))
			{
				_stickyLRU.Remove(value);
				_stickyLRU.AddLast(value);
			}
			else
			{
				LinkedListNode<int> value2 = _stickyLRU.AddLast(key);
				_stickyLRUNodes[key] = value2;
			}
		}

		private void EvictOldestSticky()
		{
			while (_stickyLRU.Count > 0)
			{
				int value = _stickyLRU.First.Value;
				_stickyLRU.RemoveFirst();
				_stickyLRUNodes.Remove(value);
				if (_stickyPS.TryGetValue(value, out var value2))
				{
					_stickyPS.Remove(value);
					if ((Object)(object)value2 != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)value2).gameObject);
					}
					break;
				}
			}
		}

		private void ClearStickyPool()
		{
			foreach (KeyValuePair<int, ParticleSystem> stickyP in _stickyPS)
			{
				if ((Object)(object)stickyP.Value != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)stickyP.Value).gameObject);
				}
			}
			_stickyPS.Clear();
			_stickyLRU.Clear();
			_stickyLRUNodes.Clear();
		}

		private ParticleSystem CreateStickyParticleSystem(Transform parent)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_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_002e: 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_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_004a: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			GameObject val = new GameObject("LidarMod_StickyPS");
			val.transform.SetParent(parent, false);
			ParticleSystem val2 = val.AddComponent<ParticleSystem>();
			EmissionModule emission = val2.emission;
			((EmissionModule)(ref emission)).enabled = false;
			ShapeModule shape = val2.shape;
			((ShapeModule)(ref shape)).enabled = false;
			MainModule main = val2.main;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(30f);
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.1f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0f);
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)0;
			((MainModule)(ref main)).maxParticles = 20000;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).loop = false;
			((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(0f);
			((MainModule)(ref main)).ringBufferMode = (ParticleSystemRingBufferMode)2;
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			component.renderMode = (ParticleSystemRenderMode)0;
			component.alignment = (ParticleSystemRenderSpace)0;
			component.sortMode = (ParticleSystemSortMode)0;
			Shader val3 = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
			if ((Object)(object)val3 != (Object)null)
			{
				((Renderer)component).material = new Material(val3);
			}
			val2.Play();
			return val2;
		}
	}
	public class LidarMeshScanMarker : MonoBehaviour
	{
	}
	public class LidarGPURenderer
	{
		private readonly int _capacity;

		private readonly float _worldDotSize;

		private readonly float _minPixelSize;

		private Vector3[] _positions;

		private Vector4[] _colors;

		private int _writeIndex;

		private int _liveCount;

		private int _dirtyMin = int.MaxValue;

		private int _dirtyMax = -1;

		private bool _wrappedThisFrame;

		private ComputeBuffer _positionsBuf;

		private ComputeBuffer _colorsBuf;

		private ComputeBuffer _argsBuf;

		private Material _material;

		private Mesh _quadMesh;

		private readonly uint[] _args = new uint[5];

		private readonly Bounds _bounds = new Bounds(Vector3.zero, Vector3.one * 100000f);

		public int LiveCount => _liveCount;

		public int Capacity => _capacity;

		public bool IsReady => _positionsBuf != null;

		public Vector3[] PositionsBuffer => _positions;

		public Vector4[] ColorsBuffer => _colors;

		public LidarGPURenderer(int capacity, float worldDotSize, float minPixelSize)
		{
			//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_002e: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			_capacity = capacity;
			_worldDotSize = worldDotSize;
			_minPixelSize = minPixelSize;
		}

		public void Initialize(Shader shader)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			if ((Object)(object)shader == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[LidarGPU] Shader null — renderer disabled");
				}
				return;
			}
			_positions = (Vector3[])(object)new Vector3[_capacity];
			_colors = (Vector4[])(object)new Vector4[_capacity];
			_positionsBuf = new ComputeBuffer(_capacity, 12);
			_colorsBuf = new ComputeBuffer(_capacity, 16);
			_argsBuf = new ComputeBuffer(1, 20, (ComputeBufferType)256);
			_quadMesh = BuildQuadMesh();
			_material = new Material(shader);
			_material.SetBuffer("_Positions", _positionsBuf);
			_material.SetBuffer("_Colors", _colorsBuf);
			_material.SetFloat("_WorldDotSize", _worldDotSize);
			_material.SetFloat("_MinPixelSize", _minPixelSize);
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"[LidarGPU] Initialized: capacity={_capacity:N0}");
			}
		}

		public void SetGradient(Color near, Color mid, Color far, Color veryFar, float nearDist, float farDist)
		{
			//IL_001a: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_material == (Object)null))
			{
				_material.SetColor("_GradColor0", near);
				_material.SetColor("_GradColor1", mid);
				_material.SetColor("_GradColor2", far);
				_material.SetColor("_GradColor3", veryFar);
				_material.SetFloat("_GradNearDist", nearDist);
				_material.SetFloat("_GradFarDist", farDist);
			}
		}

		public void Emit(Vector3 pos, Color color)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0033: 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_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 (IsReady)
			{
				_positions[_writeIndex] = pos;
				_colors[_writeIndex] = new Vector4(color.r, color.g, color.b, color.a);
				if (_writeIndex < _dirtyMin)
				{
					_dirtyMin = _writeIndex;
				}
				if (_writeIndex + 1 > _dirtyMax)
				{
					_dirtyMax = _writeIndex + 1;
				}
				_writeIndex++;
				if (_writeIndex >= _capacity)
				{
					_writeIndex = 0;
					_wrappedThisFrame = true;
				}
				if (_liveCount < _capacity)
				{
					_liveCount++;
				}
			}
		}

		public void Render()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			if (!IsReady || _liveCount == 0)
			{
				return;
			}
			if (_dirtyMax > _dirtyMin)
			{
				if (_wrappedThisFrame)
				{
					_positionsBuf.SetData((Array)_positions);
					_colorsBuf.SetData((Array)_colors);
				}
				else
				{
					int num = _dirtyMax - _dirtyMin;
					_positionsBuf.SetData((Array)_positions, _dirtyMin, _dirtyMin, num);
					_colorsBuf.SetData((Array)_colors, _dirtyMin, _dirtyMin, num);
				}
				_dirtyMin = int.MaxValue;
				_dirtyMax = -1;
				_wrappedThisFrame = false;
			}
			_args[0] = _quadMesh.GetIndexCount(0);
			_args[1] = (uint)_liveCount;
			_argsBuf.SetData((Array)_args);
			Graphics.DrawMeshInstancedIndirect(_quadMesh, 0, _material, _bounds, _argsBuf, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)1, true, 0, (Camera)null, (LightProbeUsage)1);
		}

		public void Clear()
		{
			_writeIndex = 0;
			_liveCount = 0;
			_dirtyMin = int.MaxValue;
			_dirtyMax = -1;
			_wrappedThisFrame = false;
		}

		public void LoadBulk(Vector3[] positions, Vector4[] colors, int count)
		{
			if (IsReady)
			{
				Clear();
				int num = Mathf.Min(count, _capacity);
				if (num > 0)
				{
					Array.Copy(positions, 0, _positions, 0, num);
					Array.Copy(colors, 0, _colors, 0, num);
					_writeIndex = num % _capacity;
					_liveCount = num;
					_dirtyMin = 0;
					_dirtyMax = num;
				}
			}
		}

		public void Dispose()
		{
			ComputeBuffer positionsBuf = _positionsBuf;
			if (positionsBuf != null)
			{
				positionsBuf.Release();
			}
			ComputeBuffer colorsBuf = _colorsBuf;
			if (colorsBuf != null)
			{
				colorsBuf.Release();
			}
			ComputeBuffer argsBuf = _argsBuf;
			if (argsBuf != null)
			{
				argsBuf.Release();
			}
			_positionsBuf = null;
			_colorsBuf = null;
			_argsBuf = null;
		}

		private static Mesh BuildQuadMesh()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0029: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = new Mesh
			{
				name = "LidarMod_DotQuad"
			};
			val.vertices = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(-0.5f, -0.5f, 0f),
				new Vector3(0.5f, -0.5f, 0f),
				new Vector3(0.5f, 0.5f, 0f),
				new Vector3(-0.5f, 0.5f, 0f)
			};
			val.triangles = new int[6] { 0, 1, 2, 0, 2, 3 };
			val.bounds = new Bounds(Vector3.zero, Vector3.one);
			return val;
		}
	}
	internal static class LidarItemId
	{
		public static bool IsOurs(HandItem hi)
		{
			Item val = hi?.item;
			if (val == null)
			{
				return false;
			}
			if (val.itemTag == "cici_lidar")
			{
				return true;
			}
			if (val.itemTags != null && val.itemTags.Contains("cici_lidar"))
			{
				return true;
			}
			if (val.prefabName == "Item_Lidar")
			{
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(HandItem), "TryUse")]
	public static class LidarTryUsePatch
	{
		[HarmonyPrefix]
		public static bool Prefix(HandItem __instance)
		{
			if (!LidarItemId.IsOurs(__instance))
			{
				return true;
			}
			if (!LidarHandler.ScanInputActive)
			{
				LidarHandler.ScanPressTime = Time.time;
				LidarHandler._initiateFiredThisPress = false;
			}
			LidarHandler.ScanInputActive = true;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[Lidar] TryUse → ScanInputActive=TRUE");
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(HandItem), "StopUse")]
	public static class LidarStopUsePatch
	{
		[HarmonyPostfix]
		public static void Postfix(HandItem __instance)
		{
			if (!LidarItemId.IsOurs(__instance))
			{
				return;
			}
			if (!LidarHandler._initiateFiredThisPress)
			{
				LidarHandler.HorizontalScan = !LidarHandler.HorizontalScan;
				Plugin.PlayOneShotSound(Plugin.SwitchClip);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Lidar] Click → HorizontalScan={LidarHandler.HorizontalScan}");
				}
			}
			else
			{
				AudioSource oneShotAudioSource = Plugin.GetOneShotAudioSource();
				if ((Object)(object)oneShotAudioSource != (Object)null && oneShotAudioSource.isPlaying)
				{
					oneShotAudioSource.Stop();
				}
			}
			LidarHandler.ScanInputActive = false;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"[Lidar] StopUse → ScanInputActive=FALSE");
			}
		}
	}
	public class LidarDarknessHandler : MonoBehaviour
	{
		private bool _applied;

		private float _nextRescanTime;

		private const float RescanIntervalSec = 1f;

		private readonly List<GameObject> _sceneRootsScratch = new List<GameObject>(64);

		private readonly List<Renderer> _rendererBatchScratch = new List<Renderer>(1024);

		private Color _savedAmbient;

		private AmbientMode _savedAmbientMode;

		private bool _savedFog;

		private Color _savedFogColor;

		private CameraClearFlags _savedClearFlags;

		private Color _savedBgColor;

		private readonly List<Light> _disabledLights = new List<Light>();

		private readonly HashSet<Renderer> _disabledRenderers = new HashSet<Renderer>();

		private Transform _massTransform;

		private static readonly Color MassDarkRed = new Color(0.45f, 0.04f, 0.04f, 1f);

		private static Material _massMaterial;

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

		private GameObject _vignetteCanvas;

		private RawImage _vignetteImage;

		private M_Level _activeSafeLevel;

		private static FieldInfo _invFieldInventory;

		private static FieldInfo _invFieldItemRoot;

		private static FieldInfo _invFieldPlayerInventoryRoot;

		private static FieldInfo _bagFieldPouchRoot;

		private static FieldInfo _bagFieldLeftPocket;

		private static FieldInfo _bagFieldRightPocket;

		private static FieldInfo _levelInfoLevelField;

		private readonly List<Transform> _invRootsScratch = new List<Transform>(8);

		private void Update()
		{
			bool lidarBindingActive = Plugin.LidarBindingActive;
			if (lidarBindingActive && !_applied)
			{
				Apply();
			}
			else if (!lidarBindingActive && _applied)
			{
				Restore();
			}
			if (_applied)
			{
				M_Level currentSafeLevel = GetCurrentSafeLevel();
				if ((Object)(object)currentSafeLevel != (Object)(object)_activeSafeLevel)
				{
					_activeSafeLevel = currentSafeLevel;
					RefreshSafeAreaExclusion();
				}