Decompiled source of ItemFinder v1.0.6

plugins/ItemFinder.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using HarmonyLib;
using ItemSelector;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ItemFinder")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ItemFinder")]
[assembly: AssemblyTitle("ItemFinder")]
[assembly: AssemblyVersion("1.0.0.0")]
public class ArrowLabelManager : MonoBehaviour
{
	public class Billboard : MonoBehaviour
	{
		private void Update()
		{
			if (!((Object)(object)Camera.main == (Object)null))
			{
				((Component)this).transform.LookAt(((Component)Camera.main).transform);
				((Component)this).transform.Rotate(0f, 180f, 0f);
			}
		}
	}

	public class DynamicBillboard : MonoBehaviour
	{
		public float scaleMultiplier = 1f;

		public float distanceScalingFactor = 0.02f;

		private Vector3 initialScale;

		private void Awake()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			initialScale = ((Component)this).transform.localScale;
		}

		private void Update()
		{
			//IL_004c: 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_006d: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Camera.main == (Object)null))
			{
				((Component)this).transform.LookAt(((Component)Camera.main).transform);
				((Component)this).transform.Rotate(0f, 180f, 0f);
				float num = Vector3.Distance(((Component)this).transform.position, ((Component)Camera.main).transform.position);
				((Component)this).transform.localScale = initialScale * (1f + num * distanceScalingFactor) * scaleMultiplier;
			}
		}
	}

	private Transform parentRoot;

	private readonly List<GameObject> spawnedObjects = new List<GameObject>();

	private bool arrowsVisible = true;

	private bool labelsVisible = true;

	private void Awake()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		Debug.Log((object)$"[ArrowLabelManager] Awake on GameObject '{((Object)((Component)this).gameObject).name}', instanceID {((Object)this).GetInstanceID()}");
		GameObject val = new GameObject("ArrowsAndLabelsRoot");
		val.transform.SetParent(((Component)this).transform, false);
		parentRoot = val.transform;
	}

	public void ClearAll()
	{
		for (int num = spawnedObjects.Count - 1; num >= 0; num--)
		{
			GameObject val = spawnedObjects[num];
			if ((Object)(object)val != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val);
			}
		}
		spawnedObjects.Clear();
	}

	public void SpawnForItems(List<ItemFinder.ItemData> items)
	{
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Expected O, but got Unknown
		//IL_018c: 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_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: 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_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Expected O, but got Unknown
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0328: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Unknown result type (might be due to invalid IL or missing references)
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_0544: Unknown result type (might be due to invalid IL or missing references)
		ClearAll();
		Debug.Log((object)("[ArrowLabelManager] SpawnForItems called. items.count=" + (items?.Count ?? 0)));
		if (items == null || items.Count == 0)
		{
			return;
		}
		if (ConfigManager._settingsConfig == null || ConfigManager._settingsConfig.automation == null)
		{
			Debug.LogWarning((object)"[ArrowLabelManager] Config or settings is null, using defaults");
			return;
		}
		ArrowSettings arrows = ConfigManager._settingsConfig.automation.arrows;
		LabelSettings labels = ConfigManager._settingsConfig.automation.labels;
		List<ItemFinder.ItemData> list = items.Where((ItemFinder.ItemData i) => i.itemType != "Campfire").ToList();
		foreach (ItemFinder.ItemData item2 in list)
		{
			ArrowConfigData topArrow = arrows.topArrow;
			float num = arrows.topArrowYScale / arrows.meshDefaultHeight;
			Vector3 scale = topArrow.GetScale();
			scale.y = num;
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
			Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
			val.transform.SetParent(parentRoot, true);
			val.transform.localScale = scale;
			float num2 = num * arrows.meshDefaultHeight / 2f;
			val.transform.position = item2.position + Vector3.up * (topArrow.hoverHeight + num2);
			Material val2 = new Material(Shader.Find("Unlit/Color"));
			val2.color = topArrow.GetColor();
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.material = val2;
			}
			val.layer = LayerMask.NameToLayer("Default");
			((Object)val).name = "PeakArrow_Top";
			spawnedObjects.Add(val);
			ArrowConfigData bottomArrow = arrows.bottomArrow;
			float num3 = arrows.bottomArrowYScale / arrows.meshDefaultHeight;
			Vector3 scale2 = bottomArrow.GetScale();
			scale2.y = num3;
			GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)2);
			Object.DestroyImmediate((Object)(object)val3.GetComponent<Collider>());
			val3.transform.SetParent(parentRoot, true);
			val3.transform.localScale = scale2;
			float num4 = num3 * arrows.meshDefaultHeight / 2f;
			val3.transform.position = item2.position - Vector3.up * (bottomArrow.hoverHeight + num4);
			Material val4 = new Material(Shader.Find("Unlit/Color"));
			val4.color = bottomArrow.GetColor();
			Renderer component2 = val3.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.material = val4;
			}
			val3.layer = LayerMask.NameToLayer("Default");
			((Object)val3).name = "PeakArrow_Bottom";
			spawnedObjects.Add(val3);
		}
		for (int j = 0; j < list.Count; j++)
		{
			ItemFinder.ItemData itemData = list[j];
			Vector3 position = itemData.position + new Vector3(labels.xOffset, labels.YOffset, labels.zOffset);
			string text;
			if (ConfigManager._settingsConfig.automation.labels.useNiceNames)
			{
				text = ItemNameManager.Instance.GetNiceName(itemData.objectName);
				if (string.IsNullOrEmpty(text) || text == itemData.objectName)
				{
					text = ItemNameManager.Instance.GetNiceName(itemData.itemType);
				}
				if (string.IsNullOrEmpty(text) || text == itemData.itemType)
				{
					text = itemData.displayName;
				}
			}
			else
			{
				text = itemData.itemType ?? itemData.objectName ?? itemData.displayName ?? "Unknown";
			}
			if (ConfigManager._settingsConfig.automation.labels.simplifyMushroomNames)
			{
				string text2 = (itemData.objectName ?? itemData.itemType ?? "").Replace("(Clone)", "").Trim();
				if (text2.Contains("Mushroom"))
				{
					if (text2.Contains("Lace") && text2.Contains("Poison"))
					{
						text = "Bugle Shroom Poison";
					}
					else if (text2.Contains("Lace"))
					{
						text = "Bugle Shroom";
					}
					else if (text2.Contains("Normie") && text2.Contains("Poison"))
					{
						text = "Button Shroom Poison";
					}
					else if (text2.Contains("Normie"))
					{
						text = "Button Shroom";
					}
					else if (text2.Contains("Cluster") && text2.Contains("Poison"))
					{
						text = "Cluster Shroom Poison";
					}
					else if (text2.Contains("Cluster"))
					{
						text = "Cluster Shroom";
					}
				}
				GameObject item = CreateBoldTextLabel(text, position);
				spawnedObjects.Add(item);
			}
			ApplyVisibility();
			Debug.Log((object)("[ArrowLabelManager] SpawnForItems completed. spawnedObjects=" + spawnedObjects.Count));
		}
	}

	public void SpawnForAdditionalItems(List<ItemFinder.ItemData> newItems)
	{
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: 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_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Expected O, but got Unknown
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Expected O, but got Unknown
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_053e: Unknown result type (might be due to invalid IL or missing references)
		Debug.Log((object)("[ArrowLabelManager] SpawnForAdditionalItems called. newItems.count=" + (newItems?.Count ?? 0)));
		if (newItems == null || newItems.Count == 0)
		{
			return;
		}
		if (ConfigManager._settingsConfig == null || ConfigManager._settingsConfig.automation == null)
		{
			Debug.LogWarning((object)"[ArrowLabelManager] Config or settings is null, using defaults");
			return;
		}
		ArrowSettings arrows = ConfigManager._settingsConfig.automation.arrows;
		LabelSettings labels = ConfigManager._settingsConfig.automation.labels;
		List<ItemFinder.ItemData> list = newItems.Where((ItemFinder.ItemData i) => i.itemType != "Campfire").ToList();
		foreach (ItemFinder.ItemData item2 in list)
		{
			ArrowConfigData topArrow = arrows.topArrow;
			float num = arrows.topArrowYScale / arrows.meshDefaultHeight;
			Vector3 scale = topArrow.GetScale();
			scale.y = num;
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
			Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
			val.transform.SetParent(parentRoot, true);
			val.transform.localScale = scale;
			float num2 = num * arrows.meshDefaultHeight / 2f;
			val.transform.position = item2.position + Vector3.up * (topArrow.hoverHeight + num2);
			Material val2 = new Material(Shader.Find("Unlit/Color"));
			val2.color = topArrow.GetColor();
			Renderer component = val.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				component.material = val2;
			}
			val.layer = LayerMask.NameToLayer("Default");
			((Object)val).name = "PeakArrow_Top";
			spawnedObjects.Add(val);
			ArrowConfigData bottomArrow = arrows.bottomArrow;
			float num3 = arrows.bottomArrowYScale / arrows.meshDefaultHeight;
			Vector3 scale2 = bottomArrow.GetScale();
			scale2.y = num3;
			GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)2);
			Object.DestroyImmediate((Object)(object)val3.GetComponent<Collider>());
			val3.transform.SetParent(parentRoot, true);
			val3.transform.localScale = scale2;
			float num4 = num3 * arrows.meshDefaultHeight / 2f;
			val3.transform.position = item2.position - Vector3.up * (bottomArrow.hoverHeight + num4);
			Material val4 = new Material(Shader.Find("Unlit/Color"));
			val4.color = bottomArrow.GetColor();
			Renderer component2 = val3.GetComponent<Renderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.material = val4;
			}
			val3.layer = LayerMask.NameToLayer("Default");
			((Object)val3).name = "PeakArrow_Bottom";
			spawnedObjects.Add(val3);
		}
		for (int j = 0; j < list.Count; j++)
		{
			ItemFinder.ItemData itemData = list[j];
			Vector3 position = itemData.position + new Vector3(labels.xOffset, labels.YOffset, labels.zOffset);
			string text;
			if (ConfigManager._settingsConfig.automation.labels.useNiceNames)
			{
				text = ItemNameManager.Instance.GetNiceName(itemData.objectName);
				if (string.IsNullOrEmpty(text) || text == itemData.objectName)
				{
					text = ItemNameManager.Instance.GetNiceName(itemData.itemType);
				}
				if (string.IsNullOrEmpty(text) || text == itemData.itemType)
				{
					text = itemData.displayName;
				}
			}
			else
			{
				text = itemData.itemType ?? itemData.objectName ?? itemData.displayName ?? "Unknown";
			}
			if (ConfigManager._settingsConfig.automation.labels.simplifyMushroomNames)
			{
				string text2 = (itemData.objectName ?? itemData.itemType ?? "").Replace("(Clone)", "").Trim();
				if (text2.Contains("Mushroom"))
				{
					if (text2.Contains("Lace") && text2.Contains("Poison"))
					{
						text = "Bugle Shroom Poison";
					}
					else if (text2.Contains("Lace"))
					{
						text = "Bugle Shroom";
					}
					else if (text2.Contains("Normie") && text2.Contains("Poison"))
					{
						text = "Button Shroom Poison";
					}
					else if (text2.Contains("Normie"))
					{
						text = "Button Shroom";
					}
					else if (text2.Contains("Cluster") && text2.Contains("Poison"))
					{
						text = "Cluster Shroom Poison";
					}
					else if (text2.Contains("Cluster"))
					{
						text = "Cluster Shroom";
					}
				}
			}
			GameObject item = CreateBoldTextLabel(text, position);
			spawnedObjects.Add(item);
		}
		ApplyVisibility();
		Debug.Log((object)$"[ArrowLabelManager] SpawnForAdditionalItems completed. Total spawnedObjects: {spawnedObjects.Count}");
	}

	private GameObject CreateBoldTextLabel(string text, Vector3 position)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = position;
		Debug.Log((object)("[ArrowLabelManager] Creating text label: " + text + " @ " + ((object)(Vector3)(ref val)).ToString()));
		GameObject val2 = new GameObject("ItemLabel");
		val2.transform.SetParent(parentRoot, true);
		val2.transform.position = position;
		LabelSettings labelSettings = ConfigManager._settingsConfig?.automation?.labels;
		float num = labelSettings?.fontSize ?? 15f;
		float num2 = labelSettings?.faceDilate ?? 0.05f;
		float outlineWidth = labelSettings?.outlineWidth ?? 0.09f;
		Color color = (Color)(((??)labelSettings?.fontColor) ?? new Color(1f, 0.9f, 0.2f, 1f));
		Color val3 = labelSettings?.outlineColor ?? Color.black;
		Color color2 = (Color)(((??)labelSettings?.fallbackFontColor) ?? new Color(1f, 0.8f, 0.1f, 1f));
		TMP_FontAsset val4 = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == "DarumaDropOne-Regular SDF"));
		if ((Object)(object)val4 != (Object)null)
		{
			TextMeshPro val5 = val2.AddComponent<TextMeshPro>();
			((TMP_Text)val5).text = text;
			((TMP_Text)val5).font = val4;
			((TMP_Text)val5).fontSize = num;
			if ((Object)(object)((TMP_Text)val5).fontMaterial != (Object)null)
			{
				((TMP_Text)val5).fontMaterial.SetFloat("_FaceDilate", num2);
			}
			((Graphic)val5).color = color;
			((TMP_Text)val5).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val5).outlineColor = Color32.op_Implicit(val3);
			((TMP_Text)val5).outlineWidth = outlineWidth;
		}
		else
		{
			TextMesh val6 = val2.AddComponent<TextMesh>();
			val6.text = text;
			val6.fontSize = (int)num;
			val6.color = color2;
			val6.anchor = (TextAnchor)4;
			val6.alignment = (TextAlignment)1;
		}
		try
		{
			if (labelSettings != null && labelSettings.followCamera)
			{
				DynamicBillboard dynamicBillboard = val2.AddComponent<DynamicBillboard>();
				dynamicBillboard.scaleMultiplier = labelSettings.scaleMultiplier;
				dynamicBillboard.distanceScalingFactor = labelSettings.distanceScalingFactor;
			}
			else
			{
				val2.AddComponent<Billboard>();
			}
		}
		catch
		{
			val2.AddComponent<Billboard>();
		}
		val2.layer = LayerMask.NameToLayer("Default");
		return val2;
	}

	public void ToggleArrows()
	{
		arrowsVisible = !arrowsVisible;
		ApplyVisibility();
	}

	public void ToggleLabels()
	{
		labelsVisible = !labelsVisible;
		ApplyVisibility();
	}

	public void SetVisibility(bool arrowsActive, bool labelsActive)
	{
		arrowsVisible = arrowsActive;
		labelsVisible = labelsActive;
		ApplyVisibility();
	}

	private void ApplyVisibility()
	{
		foreach (GameObject spawnedObject in spawnedObjects)
		{
			if (!((Object)(object)spawnedObject == (Object)null))
			{
				if (((Object)spawnedObject).name == "ItemLabel")
				{
					spawnedObject.SetActive(labelsVisible);
				}
				else
				{
					spawnedObject.SetActive(arrowsVisible);
				}
			}
		}
	}

	public int GetSpawnedObjectCount()
	{
		return spawnedObjects.Count;
	}

	public void DebugSpawnedObjects()
	{
		Debug.Log((object)$"[ArrowLabelManager] Total spawned objects: {spawnedObjects.Count}");
		Debug.Log((object)$"[ArrowLabelManager] Non-null objects: {spawnedObjects.Count((GameObject obj) => (Object)(object)obj != (Object)null)}");
		Debug.Log((object)$"[ArrowLabelManager] Null objects: {spawnedObjects.Count((GameObject obj) => (Object)(object)obj == (Object)null)}");
		List<GameObject> list = spawnedObjects.Where((GameObject obj) => (Object)(object)obj != (Object)null && obj.activeInHierarchy).ToList();
		Debug.Log((object)$"[ArrowLabelManager] Active objects: {list.Count}");
		List<GameObject> list2 = list.Where((GameObject obj) => ((Object)obj).name.Contains("Arrow")).ToList();
		List<GameObject> list3 = list.Where((GameObject obj) => ((Object)obj).name == "ItemLabel").ToList();
		Debug.Log((object)$"[ArrowLabelManager] Active arrows: {list2.Count}, Active labels: {list3.Count}");
	}
}
public static class BiomeDetector
{
	public static string CurrentBiome { get; private set; }

	static BiomeDetector()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		CurrentBiome = "Unknown";
		Scene activeScene = SceneManager.GetActiveScene();
		string name = ((Scene)(ref activeScene)).name;
		logs.Log("[BiomeDetector] Static constructor - Scene: " + name);
		Application.logMessageReceived += new LogCallback(OnLogMessageReceived);
		logs.Log("[BiomeDetector] Log listener registered - will detect biome changes automatically");
	}

	public static void Initialize()
	{
		logs.Log("[BiomeDetector] Initialized. Current biome: " + CurrentBiome);
	}

	private static string GetFullPath(GameObject obj)
	{
		string text = ((Object)obj).name;
		Transform parent = obj.transform.parent;
		while ((Object)(object)parent != (Object)null)
		{
			text = ((Object)parent).name + "/" + text;
			parent = parent.parent;
		}
		return text;
	}

	public static void DetectInitialBiome()
	{
		GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0);
		GameObject[] array2 = array;
		foreach (GameObject val in array2)
		{
			if (((Object)val).name == "crashed plane")
			{
				string fullPath = GetFullPath(val);
				if (fullPath == "Map/Biome_1/Beach/Beach_Segment/crashed plane")
				{
					CurrentBiome = "SHORE";
					logs.Log("[BiomeDetector] Initial biome detected: " + CurrentBiome + " (found crashed plane)");
					return;
				}
			}
		}
		logs.Log("[BiomeDetector] Could not detect initial biome from scene objects");
	}

	private static void OnLogMessageReceived(string logString, string stackTrace, LogType type)
	{
		if (logString.Contains("Set hero title: "))
		{
			string text = logString.Replace("Set hero title: ", "").Trim();
			if (ConfigManager._settingsConfig?.general?.validBiomes != null && ConfigManager._settingsConfig.general.validBiomes.Contains(text) && CurrentBiome != text)
			{
				string currentBiome = CurrentBiome;
				CurrentBiome = text;
				logs.Log("[BiomeDetector] Biome changed: " + currentBiome + " -> " + CurrentBiome);
			}
		}
	}
}
[Serializable]
public class ItemsConfig
{
	public CustomItemDetectionRule[] customItems = new CustomItemDetectionRule[0];

	public CustomItemDetectionRule[] dbItems = new CustomItemDetectionRule[0];

	public CampfireRule[] campfireRules = new CampfireRule[0];

	[JsonIgnore]
	public ItemDetectionRule[] itemDetectionRules
	{
		get
		{
			List<ItemDetectionRule> list = new List<ItemDetectionRule>();
			if (customItems != null)
			{
				list.AddRange(customItems);
			}
			if (dbItems != null)
			{
				list.AddRange(dbItems);
			}
			return list.ToArray();
		}
	}
}
[Serializable]
public class SettingsConfig
{
	public AutomationSettings automation = new AutomationSettings();

	public GeneralSettings general = new GeneralSettings();

	public UISettings ui = new UISettings();

	public CoordsGUISettings coordsGUI = new CoordsGUISettings();
}
[Serializable]
public class GeneralSettings
{
	public string outputPath = "";

	public string configPath = "";

	public bool LogUnityDebug = false;

	public float levelReadyDelay = 2f;

	public float luggageOpenDelay = 1f;

	public float luggageTimeout = 10f;

	public float biomeChangeTimeout = 30f;

	public int stabilityThreshold = 20;

	public int maxStabilityChecks = 100;

	public float stabilityCheckInterval = 0.1f;

	public float positionToMetersMultiplier = 1.59f;

	public string timestampFormat = "yyyyMMdd_HHmmss";

	public string automationContinueKey = "Alpha0";

	public int? AscentToLoad = null;

	public int? LevelToLoad = null;

	public int? Levelindex = null;

	public string[] validBiomes = new string[12]
	{
		"SHORE", "TROPICS", "JUNGLE", "MESA", "DESERT", "ALPINE", "SNOW", "TUNDRA", "CALDERA", "VOLCANO",
		"KILN", "THE KILN"
	};

	public KeyboardSettings keyboard = new KeyboardSettings();

	public bool OpenLuggageAutomatically = true;

	public bool SkipAirportLobby = false;

	public bool fetchLevelIndexFromServer = false;

	public string levelServerUrl = "https://peaklogin.azurewebsites.net/api/VersionCheck";

	public string _comment_AscentToLoad = "defaults to -1 (tenderfoot)";

	public string _comment_LevelToLoad = "unused";

	public string _comment_Levelindex = "unused";

	public string _comment_SkipAirportLobby = "placeholder";

	public string _comment_fetchLevelIndexFromServer = "unused";

	public string _comment_levelServerUrl = "unused";

	public string GetOutputDirectory()
	{
		if (string.IsNullOrEmpty(outputPath))
		{
			return Path.Combine(Paths.PluginPath, "ItemFinder", "output");
		}
		if (Path.IsPathRooted(outputPath))
		{
			return outputPath;
		}
		return Path.Combine(Paths.PluginPath, "ItemFinder", outputPath);
	}

	public string GetConfigDirectory()
	{
		if (string.IsNullOrEmpty(configPath))
		{
			return Path.Combine(Paths.ConfigPath, "ItemFinder");
		}
		if (Path.IsPathRooted(configPath))
		{
			return configPath;
		}
		return Path.Combine(Paths.ConfigPath, "ItemFinder", configPath);
	}
}
[Serializable]
public class KeyboardSettings
{
	public string _comment_hotkeys = "Case insensitive";

	public string _comment_numpadkeys = "Hotkeys on the numpad require numpadX or keypadX like numpad0 numpad1 Keypad0 Keypad1 case insensitive";

	public string _comment_supportedKeys = "Modifiers: ctrl, shift, alt, cmd, windows; Enter/Return, Esc, Space; Numbers: 0-9 (Alpha), Numpad: numpad0-9/keypad0-9; F1-F12; Arrows: up, down, left, right; Special: ., ,, /, \\, ;, ', [, ], -, =, `";

	public bool requireShiftModifier = false;

	public string itemSelectorToggleKey = "I";

	public string toggleArrowsKey = "F1";

	public string toggleLabelsKey = "F2";

	public string arrowModeKey = "F3";

	public string fullAutomationKey = "F4";

	public string hotReloadKey = "F5";

	public string spawnItemsKey = "F6";

	public string openLuggageKey = "F7";

	public string unityCoordsKey = "F8";

	public string arrowsNoLoadKey = "F9";

	public string triggerCampfireKey = "F10";

	public string _comment_requireShiftModifier = "placeholder";

	public bool IsShiftRequirementMet()
	{
		if (!requireShiftModifier)
		{
			return true;
		}
		return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
	}

	public KeyCode GetAutomationContinueKey(string keyString)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: 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)
		if (Enum.TryParse<KeyCode>(keyString, out KeyCode result))
		{
			return result;
		}
		return (KeyCode)48;
	}

	public KeyCode GetItemSelectorToggleKey()
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(itemSelectorToggleKey, (KeyCode)105);
	}

	public KeyCode GetFullAutomationKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(fullAutomationKey, (KeyCode)285);
	}

	public KeyCode GetArrowModeKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(arrowModeKey, (KeyCode)284);
	}

	public KeyCode GetToggleArrowsKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(toggleArrowsKey, (KeyCode)282);
	}

	public KeyCode GetToggleLabelsKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(toggleLabelsKey, (KeyCode)283);
	}

	public KeyCode GetHotReloadKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(hotReloadKey, (KeyCode)286);
	}

	public KeyCode GetSpawnItemsKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(spawnItemsKey, (KeyCode)287);
	}

	public KeyCode GetOpenLuggageKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(openLuggageKey, (KeyCode)288);
	}

	public KeyCode GetUnityCoordsKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(unityCoordsKey, (KeyCode)289);
	}

	public KeyCode GetArrowsNoLoadKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(arrowsNoLoadKey, (KeyCode)290);
	}

	public KeyCode GetTriggerCampfireKey()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		return ParseKeyCode(triggerCampfireKey, (KeyCode)291);
	}

	public KeyCode ParseKeyCode(string keyString, KeyCode fallback)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(keyString))
		{
			return fallback;
		}
		keyString = keyString.Trim().ToLowerInvariant();
		int result;
		if (keyString.Length == 1 && keyString[0] >= '0' && keyString[0] <= '9')
		{
			keyString = "Alpha" + keyString;
		}
		else if (keyString.StartsWith("numpad") && keyString.Length == 7 && char.IsDigit(keyString[6]))
		{
			keyString = "Keypad" + keyString[6];
		}
		else if (keyString.StartsWith("f") && int.TryParse(keyString.Substring(1), out result) && result >= 1 && result <= 12)
		{
			keyString = "F" + result;
		}
		else
		{
			switch (keyString)
			{
			case "ctrl":
			case "control":
				keyString = "LeftControl";
				break;
			case "shift":
				keyString = "LeftShift";
				break;
			case "alt":
				keyString = "LeftAlt";
				break;
			case "cmd":
				keyString = "LeftCommand";
				break;
			case "windows":
				keyString = "LeftWindows";
				break;
			case "enter":
			case "return":
				keyString = "Return";
				break;
			case "esc":
				keyString = "Escape";
				break;
			case "space":
				keyString = "Space";
				break;
			case ".":
				keyString = "Period";
				break;
			case ",":
				keyString = "Comma";
				break;
			case "/":
				keyString = "Slash";
				break;
			case "\\":
				keyString = "Backslash";
				break;
			case ";":
				keyString = "Semicolon";
				break;
			case "'":
				keyString = "Quote";
				break;
			case "[":
				keyString = "LeftBracket";
				break;
			case "]":
				keyString = "RightBracket";
				break;
			case "-":
				keyString = "Minus";
				break;
			case "=":
				keyString = "Equals";
				break;
			case "`":
				keyString = "BackQuote";
				break;
			case "up":
				keyString = "UpArrow";
				break;
			case "down":
				keyString = "DownArrow";
				break;
			case "left":
				keyString = "LeftArrow";
				break;
			case "right":
				keyString = "RightArrow";
				break;
			}
		}
		if (Enum.TryParse<KeyCode>(keyString, ignoreCase: true, out KeyCode result2))
		{
			return result2;
		}
		return fallback;
	}
}
[Serializable]
public class AutomationSettings
{
	public ArrowSettings arrows = new ArrowSettings();

	public ScreenshotSettings screenshot = new ScreenshotSettings();

	public LabelSettings labels = new LabelSettings();

	public bool skipLuggage = false;

	public bool skipCampfire = false;

	public bool skipScreenshots = false;

	public bool skipArrowSpawning = false;

	public string _comment_skipLuggage = "unused";

	public string _comment_skipCampfire = "unused";

	public string _comment_skipScreenshots = "unused";

	public string _comment_skipArrowSpawning = "unused";
}
[Serializable]
public class ArrowSettings
{
	public ArrowConfigData topArrow = new ArrowConfigData
	{
		color = new float[4] { 1f, 0f, 0f, 1f },
		scale = new float[3] { 0.5f, 1000f, 0.5f },
		hoverHeight = 5f
	};

	public ArrowConfigData bottomArrow = new ArrowConfigData
	{
		color = new float[4] { 1f, 1f, 0f, 1f },
		scale = new float[3] { 0.3f, 500f, 0.3f },
		hoverHeight = 5f
	};

	public float meshDefaultHeight = 2f;

	public float topArrowYScale = 1000f;

	public float bottomArrowYScale = 500f;
}
[Serializable]
public class ArrowConfigData
{
	public float[] color = new float[4];

	public float[] scale = new float[3];

	public float hoverHeight = 5f;

	public Color GetColor()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		return new Color(color[0], color[1], color[2], color[3]);
	}

	public Vector3 GetScale()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(scale[0], scale[1], scale[2]);
	}
}
[Serializable]
public class ScreenshotSettings
{
	public float teleportOffset = 3f;

	public float flySpeedX = 25f;

	public float flySpeedY = 25f;

	public float flySpeedZ = 25f;

	public float safePositionHeight = 2f;

	public float groundDetectionDistance = 10f;

	public Vector3 campfireTeleportOffset = new Vector3(0f, 50f, 5f);

	public string screenshotTriggerKey = "Alpha0";

	public string flyUpKey = "Space";

	public bool enableBiomeScreenshotTeleport = false;

	public Vector3 biomeScreenshotOffset = new Vector3(0f, 100f, 0f);

	public Vector3 biomeScreenshotFacing = Vector3.forward;

	public string _comment_enableBiomeScreenshotTeleport = "unused";
}
[Serializable]
public class LabelSettings
{
	public bool useNiceNames = true;

	public bool followCamera = true;

	public bool simplifyMushroomNames = true;

	public float fontSize = 15f;

	public float faceDilate = 0.05f;

	public float outlineWidth = 0.09f;

	public float[] fontColorArray = new float[4] { 1f, 0.9f, 0.2f, 1f };

	public float[] outlineColorArray = new float[4] { 0f, 0f, 0f, 1f };

	public float scaleMultiplier = 1f;

	public float YOffset = 5f;

	public float stackSpacing = 0.5f;

	public float zOffset = -2f;

	public float xOffset = 0f;

	public float distanceScalingFactor = 0f;

	public float[] fallbackFontColorArray = new float[4] { 1f, 0.8f, 0.1f, 1f };

	[JsonIgnore]
	public Color fontColor => new Color(fontColorArray[0], fontColorArray[1], fontColorArray[2], fontColorArray[3]);

	[JsonIgnore]
	public Color outlineColor => new Color(outlineColorArray[0], outlineColorArray[1], outlineColorArray[2], outlineColorArray[3]);

	[JsonIgnore]
	public Color fallbackFontColor => new Color(fallbackFontColorArray[0], fallbackFontColorArray[1], fallbackFontColorArray[2], fallbackFontColorArray[3]);
}
[Serializable]
public class UISettings
{
	public GridSettings grid = new GridSettings();

	public ColorSettings colors = new ColorSettings();

	public WindowSettings window = new WindowSettings();

	public FontSettings fonts = new FontSettings();

	public ScrollSettings scroll = new ScrollSettings();
}
[Serializable]
public class GridSettings
{
	public int columns = 12;

	public float spacing = 8f;

	public float cellHeightMultiplier = 1.1f;
}
[Serializable]
public class ColorSettings
{
	public float[] selectedColor = new float[4] { 0.4f, 0.7f, 1f, 0.95f };

	public float[] unselectedColor = new float[4] { 0.22f, 0.22f, 0.22f, 0.95f };

	public float[] panelBackgroundColor = new float[4] { 0.2f, 0.2f, 0.2f, 0.95f };

	[JsonIgnore]
	public Color SelectedColor => new Color(selectedColor[0], selectedColor[1], selectedColor[2], selectedColor[3]);

	[JsonIgnore]
	public Color UnselectedColor => new Color(unselectedColor[0], unselectedColor[1], unselectedColor[2], unselectedColor[3]);

	[JsonIgnore]
	public Color PanelBackgroundColor => new Color(panelBackgroundColor[0], panelBackgroundColor[1], panelBackgroundColor[2], panelBackgroundColor[3]);
}
[Serializable]
public class WindowSettings
{
	public float[] windowAnchorMin = new float[2] { 0.1f, 0.1f };

	public float[] windowAnchorMax = new float[2] { 0.9f, 0.9f };

	public int canvasSortingOrder = 100;

	public float[] referenceResolution = new float[2] { 1920f, 1080f };
}
[Serializable]
public class FontSettings
{
	public float fontSizeHeightMultiplier = 0.18f;

	public int minFontSize = 10;

	public int maxFontSize = 22;

	public int dbItemFontSize = 16;

	public int customItemFontSize = 14;
}
[Serializable]
public class ScrollSettings
{
	public float scrollSensitivity = 25f;

	public float scrollbarWidth = 20f;
}
[Serializable]
public class CoordsGUISettings
{
	public string _comment_targetGameObjectName = "MUST BE AT ROOT LEVEL, NO RECURSIVE SEARCH YET (do we even need it?)";

	public string targetGameObjectName = "MainCamera";

	public float updateRate = 10f;

	public int fontSize = 18;

	public bool showRotation = true;

	public bool showVelocity = true;

	public bool showSpeed = true;

	public bool showMaxSpeed = true;

	public float positionToMetersMultiplier = 1.59f;
}
[Serializable]
public class ItemDetectionRule
{
	public string biome = "";

	public string itemType = "";

	public DetectionCondition detection = new DetectionCondition();

	public NameModifier nameModifier = null;

	public bool normalizeName = true;
}
[Serializable]
public class CustomItemDetectionRule : ItemDetectionRule
{
	public bool selected = false;

	public string niceName = null;
}
[Serializable]
public class CampfireRule
{
	public string biome = "";

	public DetectionCondition detection = new DetectionCondition();

	public bool normalizeName = false;
}
[Serializable]
public class DetectionCondition
{
	public string type = "";

	public string value = "";

	public DetectionCondition[] conditions = new DetectionCondition[0];
}
[Serializable]
public class NameModifier
{
	public string type = "";

	public ModifierRule[] rules = new ModifierRule[0];
}
[Serializable]
public class ModifierRule
{
	public string pathContains = "";

	public string suffix = "";
}
public static class ConfigManager
{
	public static ItemsConfig _itemsConfig;

	public static SettingsConfig _settingsConfig;

	private static string ItemsConfigPath => Path.Combine(_settingsConfig?.general?.GetConfigDirectory() ?? Path.Combine(Paths.ConfigPath, "ItemFinder"), "ItemConfig.json");

	private static string SettingsConfigPath => Path.Combine(_settingsConfig?.general?.GetConfigDirectory() ?? Path.Combine(Paths.ConfigPath, "ItemFinder"), "SettingsConfig.json");

	private static void EnsureConfigDirectoryExists()
	{
		string path = _settingsConfig?.general?.GetConfigDirectory() ?? Path.Combine(Paths.ConfigPath, "ItemFinder");
		if (!Directory.Exists(path))
		{
			Directory.CreateDirectory(path);
		}
	}

	public static void LoadConfigs()
	{
		LoadItemsConfig();
		LoadSettingsConfig();
	}

	public static void LoadItemsConfig()
	{
		try
		{
			EnsureConfigDirectoryExists();
			if (File.Exists(ItemsConfigPath))
			{
				ConfigMigration.MigrateItemsConfig(ItemsConfigPath);
				string text = File.ReadAllText(ItemsConfigPath);
				logs.Log("[ConfigManager] Loading items config from " + ItemsConfigPath);
				_itemsConfig = JsonConvert.DeserializeObject<ItemsConfig>(text);
				if (_itemsConfig.customItems == null)
				{
					_itemsConfig.customItems = new CustomItemDetectionRule[0];
				}
				if (_itemsConfig.dbItems == null)
				{
					_itemsConfig.dbItems = CreateDefaultCustomItemRules();
				}
				if (_itemsConfig.campfireRules == null)
				{
					_itemsConfig.campfireRules = CreateDefaultCampfireRules();
				}
			}
			else
			{
				logs.Log("[ConfigManager] ItemsConfig not found, creating default");
				_itemsConfig = CreateDefaultItemsConfig();
				SaveItemsConfig();
			}
		}
		catch (Exception ex)
		{
			logs.Log("[ConfigManager] Error loading ItemsConfig: " + ex.Message);
			_itemsConfig = CreateDefaultItemsConfig();
		}
	}

	public static void LoadSettingsConfig()
	{
		try
		{
			EnsureConfigDirectoryExists();
			if (File.Exists(SettingsConfigPath))
			{
				ConfigMigration.MigrateSettingsConfig(SettingsConfigPath);
				string text = File.ReadAllText(SettingsConfigPath);
				logs.Log("[ConfigManager] Loading settings config from " + SettingsConfigPath);
				_settingsConfig = JsonConvert.DeserializeObject<SettingsConfig>(text);
				if (_settingsConfig.automation == null)
				{
					_settingsConfig.automation = new AutomationSettings();
				}
				if (_settingsConfig.general == null)
				{
					_settingsConfig.general = new GeneralSettings();
				}
				if (_settingsConfig.ui == null)
				{
					_settingsConfig.ui = new UISettings();
				}
				if (_settingsConfig.coordsGUI == null)
				{
					_settingsConfig.coordsGUI = new CoordsGUISettings();
				}
			}
			else
			{
				logs.Log("[ConfigManager] SettingsConfig not found, creating default");
				_settingsConfig = CreateDefaultSettingsConfig();
				SaveSettingsConfig();
			}
		}
		catch (Exception ex)
		{
			logs.Log("[ConfigManager] Error loading SettingsConfig: " + ex.Message);
			_settingsConfig = CreateDefaultSettingsConfig();
		}
	}

	public static void SaveItemsConfig()
	{
		EnsureConfigDirectoryExists();
		CustomItemDetectionRule[] array = _itemsConfig?.dbItems ?? new CustomItemDetectionRule[0];
		ItemDetectionRule[] array2 = new ItemDetectionRule[array.Length];
		for (int i = 0; i < array.Length; i++)
		{
			CustomItemDetectionRule customItemDetectionRule = array[i];
			array2[i] = new ItemDetectionRule
			{
				biome = customItemDetectionRule.biome,
				itemType = customItemDetectionRule.itemType,
				detection = customItemDetectionRule.detection,
				nameModifier = customItemDetectionRule.nameModifier,
				normalizeName = customItemDetectionRule.normalizeName
			};
		}
		var anon = new
		{
			customItems = (_itemsConfig?.customItems ?? new CustomItemDetectionRule[0]),
			dbItems = array2,
			campfireRules = (_itemsConfig?.campfireRules ?? new CampfireRule[0])
		};
		string contents = JsonConvert.SerializeObject((object)anon, (Formatting)1);
		File.WriteAllText(ItemsConfigPath, contents);
	}

	public static void SaveSettingsConfig()
	{
		EnsureConfigDirectoryExists();
		string contents = JsonConvert.SerializeObject((object)_settingsConfig, (Formatting)1);
		File.WriteAllText(SettingsConfigPath, contents);
	}

	public static void SaveConfigs()
	{
		SaveItemsConfig();
		SaveSettingsConfig();
	}

	private static ItemsConfig CreateDefaultItemsConfig()
	{
		ItemsConfig itemsConfig = new ItemsConfig();
		itemsConfig.customItems = CreateDefaultCustomItemRules();
		itemsConfig.dbItems = new CustomItemDetectionRule[0];
		itemsConfig.campfireRules = CreateDefaultCampfireRules();
		return itemsConfig;
	}

	private static SettingsConfig CreateDefaultSettingsConfig()
	{
		return new SettingsConfig
		{
			automation = new AutomationSettings(),
			general = new GeneralSettings(),
			ui = new UISettings(),
			coordsGUI = new CoordsGUISettings()
		};
	}

	public static CustomItemDetectionRule[] CreateDefaultCustomItemRules()
	{
		return new CustomItemDetectionRule[11]
		{
			new CustomItemDetectionRule
			{
				biome = "MESA",
				itemType = "MirageLuggageSmall",
				detection = new DetectionCondition
				{
					type = "pathContains",
					value = "LuggageSpawner_Mirrage/MirageLuggage"
				},
				selected = false,
				niceName = "Mirage Small"
			},
			new CustomItemDetectionRule
			{
				biome = "MESA",
				itemType = "MirageLuggageBig",
				detection = new DetectionCondition
				{
					type = "pathContains",
					value = "LuggageSpawner_Mirrage/MirageLuggageBig"
				},
				selected = false,
				niceName = "Mirage Big"
			},
			new CustomItemDetectionRule
			{
				biome = "MESA",
				itemType = "MirageLuggageEpic",
				detection = new DetectionCondition
				{
					type = "pathContains",
					value = "LuggageSpawner_Mirrage/MirageLuggageEpic"
				},
				selected = false,
				niceName = "Mirage Epic"
			},
			new CustomItemDetectionRule
			{
				biome = "MESA",
				itemType = "MirageLuggageAncient",
				detection = new DetectionCondition
				{
					type = "pathContains",
					value = "LuggageSpawner_Mirrage/MirageLuggageAncient"
				},
				selected = false,
				niceName = "Mirage Ancient"
			},
			new CustomItemDetectionRule
			{
				biome = "ANY",
				itemType = "LuggageSmall",
				detection = new DetectionCondition
				{
					type = "exactName",
					value = "LuggageSmall"
				},
				selected = false,
				niceName = "Small Luggage"
			},
			new CustomItemDetectionRule
			{
				biome = "ANY",
				itemType = "LuggageBig",
				detection = new DetectionCondition
				{
					type = "exactName",
					value = "LuggageBig"
				},
				selected = false,
				niceName = "Big Luggage"
			},
			new CustomItemDetectionRule
			{
				biome = "ANY",
				itemType = "LuggageEpic",
				detection = new DetectionCondition
				{
					type = "exactName",
					value = "LuggageEpic"
				},
				selected = false,
				niceName = "Epic Luggage"
			},
			new CustomItemDetectionRule
			{
				biome = "ANY",
				itemType = "LuggageAncient",
				detection = new DetectionCondition
				{
					type = "exactName",
					value = "LuggageAncient"
				},
				selected = false,
				niceName = "Ancient Luggage"
			},
			new CustomItemDetectionRule
			{
				biome = "MESA",
				itemType = "Antlion",
				detection = new DetectionCondition
				{
					type = "exactName",
					value = "AntLion"
				},
				selected = false,
				niceName = "Antlion"
			},
			new CustomItemDetectionRule
			{
				biome = "ANY",
				itemType = "CapybaraOnsen",
				detection = new DetectionCondition
				{
					type = "pathEndsWith",
					value = "Capybara/Onsen"
				},
				selected = false,
				niceName = "Capybara Hot Spring"
			},
			new CustomItemDetectionRule
			{
				biome = "CALDERA",
				itemType = "Eggs",
				detection = new DetectionCondition
				{
					type = "exactName",
					value = "EggNest"
				},
				selected = false,
				niceName = "null"
			}
		};
	}

	public static CampfireRule[] CreateDefaultCampfireRules()
	{
		return new CampfireRule[5]
		{
			new CampfireRule
			{
				biome = "SHORE",
				detection = new DetectionCondition
				{
					type = "exactPath",
					value = "Map/Biome_1/Beach/Beach_Campfire/Campfire/Campfire"
				}
			},
			new CampfireRule
			{
				biome = "TROPICS",
				detection = new DetectionCondition
				{
					type = "exactPath",
					value = "Map/Biome_2/Jungle/Jungle_Campfire/Campfire/Campfire"
				}
			},
			new CampfireRule
			{
				biome = "ALPINE",
				detection = new DetectionCondition
				{
					type = "exactPath",
					value = "Map/Biome_3/Snow/Snow_Campfire/Campfire/Campfire"
				}
			},
			new CampfireRule
			{
				biome = "MESA",
				detection = new DetectionCondition
				{
					type = "pathContains",
					value = "Map/Biome_3/Desert"
				}
			},
			new CampfireRule
			{
				biome = "CALDERA",
				detection = new DetectionCondition
				{
					type = "pathContains",
					value = "Map/Biome_4/Volcano/Volcano_Campfire"
				}
			}
		};
	}

	public static bool MatchesDetection(GameObject obj, ItemDetectionRule rule)
	{
		if ((Object)(object)obj == (Object)null || rule == null || rule.detection == null)
		{
			return false;
		}
		string text = ((Object)obj).name;
		string text2 = rule.detection.value;
		if (rule.normalizeName)
		{
			text = NormalizeName(text);
			text2 = NormalizeName(text2);
		}
		string fullPath = GetFullPath(obj);
		switch (rule.detection.type)
		{
		case "exactName":
			return text == text2;
		case "pathEndsWith":
			return fullPath.EndsWith(text2);
		case "pathContains":
			return fullPath.Contains(text2);
		case "exactPath":
			return fullPath == text2;
		case "complex":
		{
			if (rule.detection.conditions == null || rule.detection.conditions.Length == 0)
			{
				return false;
			}
			DetectionCondition[] conditions = rule.detection.conditions;
			foreach (DetectionCondition detection in conditions)
			{
				ItemDetectionRule rule2 = new ItemDetectionRule
				{
					detection = detection,
					normalizeName = rule.normalizeName
				};
				if (!MatchesDetection(obj, rule2))
				{
					return false;
				}
			}
			return true;
		}
		default:
			return false;
		}
	}

	public static bool MatchesDetection(GameObject obj, CampfireRule rule)
	{
		if ((Object)(object)obj == (Object)null || rule == null || rule.detection == null)
		{
			return false;
		}
		string text = ((Object)obj).name;
		string text2 = rule.detection.value;
		if (rule.normalizeName)
		{
			text = NormalizeName(text);
			text2 = NormalizeName(text2);
		}
		string fullPath = GetFullPath(obj);
		return rule.detection.type switch
		{
			"exactName" => text == text2, 
			"pathEndsWith" => fullPath.EndsWith(text2), 
			"pathContains" => fullPath.Contains(text2), 
			"exactPath" => fullPath == text2, 
			_ => false, 
		};
	}

	public static string NormalizeName(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return "";
		}
		name = name.Trim();
		int num = name.IndexOf('(');
		if (num >= 0)
		{
			name = name.Substring(0, num);
		}
		return name.Trim();
	}

	private static string GetFullPath(GameObject obj)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return "";
		}
		return ((Object)(object)obj.transform == (Object)null) ? ((Object)obj).name : obj.transform.GetHierarchyPath();
	}
}
public static class TransformExtensions
{
	public static string GetHierarchyPath(this Transform current)
	{
		if ((Object)(object)current.parent == (Object)null)
		{
			return ((Object)current).name;
		}
		return current.parent.GetHierarchyPath() + "/" + ((Object)current).name;
	}
}
public static class ConfigMigration
{
	public static void MigrateSettingsConfig(string path)
	{
		if (!File.Exists(path))
		{
			return;
		}
		try
		{
			string text = File.ReadAllText(path);
			JObject val = JObject.Parse(text);
			SettingsConfig settingsConfig = new SettingsConfig
			{
				automation = new AutomationSettings(),
				general = new GeneralSettings(),
				ui = new UISettings(),
				coordsGUI = new CoordsGUISettings()
			};
			JObject defaults = JObject.FromObject((object)settingsConfig);
			if (DeepMerge(val, defaults))
			{
				File.WriteAllText(path, ((JToken)val).ToString((Formatting)1, Array.Empty<JsonConverter>()));
				logs.Log("[ConfigMigration] SettingsConfig updated with missing fields");
			}
			else
			{
				logs.Log("[ConfigMigration] SettingsConfig is up to date");
			}
		}
		catch (Exception ex)
		{
			logs.Log("[ConfigMigration] Error migrating SettingsConfig: " + ex.Message);
		}
	}

	public static void MigrateItemsConfig(string path)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		if (!File.Exists(path))
		{
			return;
		}
		try
		{
			string text = File.ReadAllText(path);
			JObject val = JObject.Parse(text);
			bool flag = false;
			if (val["customItems"] == null)
			{
				val["customItems"] = (JToken)new JArray();
				logs.Log("[ConfigMigration] Added customItems array");
				flag = true;
			}
			if (val["dbItems"] == null)
			{
				val["dbItems"] = (JToken)new JArray();
				logs.Log("[ConfigMigration] Added dbItems array");
				flag = true;
			}
			if (val["campfireRules"] == null)
			{
				val["campfireRules"] = (JToken)new JArray();
				logs.Log("[ConfigMigration] Added campfireRules array");
				flag = true;
			}
			CustomItemDetectionRule[] array = ConfigManager.CreateDefaultCustomItemRules();
			CampfireRule[] array2 = ConfigManager.CreateDefaultCampfireRules();
			JToken obj = val["customItems"];
			JArray val2 = (JArray)(object)((obj is JArray) ? obj : null);
			if (val2 != null)
			{
				HashSet<string> hashSet = new HashSet<string>();
				foreach (JToken item in val2)
				{
					JToken obj2 = item[(object)"itemType"];
					string text2 = ((obj2 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj2) : null);
					if (!string.IsNullOrEmpty(text2))
					{
						hashSet.Add(text2);
					}
				}
				int num = 0;
				CustomItemDetectionRule[] array3 = array;
				foreach (CustomItemDetectionRule customItemDetectionRule in array3)
				{
					if (!hashSet.Contains(customItemDetectionRule.itemType))
					{
						val2.Add((JToken)(object)JObject.FromObject((object)customItemDetectionRule));
						logs.Log("[ConfigMigration] Added missing item: " + customItemDetectionRule.itemType);
						num++;
						flag = true;
					}
				}
				if (num > 0)
				{
					logs.Log($"[ConfigMigration] Added {num} missing custom items");
				}
			}
			JToken obj3 = val["campfireRules"];
			JArray val3 = (JArray)(object)((obj3 is JArray) ? obj3 : null);
			if (val3 != null)
			{
				HashSet<string> hashSet2 = new HashSet<string>();
				foreach (JToken item2 in val3)
				{
					JToken obj4 = item2[(object)"biome"];
					string text3 = ((obj4 != null) ? Extensions.Value<string>((IEnumerable<JToken>)obj4) : null);
					if (!string.IsNullOrEmpty(text3))
					{
						hashSet2.Add(text3);
					}
				}
				int num2 = 0;
				CampfireRule[] array4 = array2;
				foreach (CampfireRule campfireRule in array4)
				{
					if (!hashSet2.Contains(campfireRule.biome))
					{
						val3.Add((JToken)(object)JObject.FromObject((object)campfireRule));
						logs.Log("[ConfigMigration] Added missing campfire rule for: " + campfireRule.biome);
						num2++;
						flag = true;
					}
				}
				if (num2 > 0)
				{
					logs.Log($"[ConfigMigration] Added {num2} missing campfire rules");
				}
			}
			if (flag)
			{
				File.WriteAllText(path, ((JToken)val).ToString((Formatting)1, Array.Empty<JsonConverter>()));
				logs.Log("[ConfigMigration] ItemsConfig updated with missing fields");
			}
			else
			{
				logs.Log("[ConfigMigration] ItemsConfig is up to date");
			}
		}
		catch (Exception ex)
		{
			logs.Log("[ConfigMigration] Error migrating ItemsConfig: " + ex.Message);
		}
	}

	private static bool DeepMerge(JObject existing, JObject defaults)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Invalid comparison between Unknown and I4
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Invalid comparison between Unknown and I4
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Invalid comparison between Unknown and I4
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Expected O, but got Unknown
		//IL_00ad: Expected O, but got Unknown
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Invalid comparison between Unknown and I4
		bool result = false;
		foreach (JProperty item in defaults.Properties())
		{
			string name = item.Name;
			if (name.StartsWith("_comment"))
			{
				continue;
			}
			JToken val = existing[name];
			JToken value = item.Value;
			if (val == null)
			{
				existing[name] = value.DeepClone();
				logs.Log("[ConfigMigration] Added missing field: " + name);
				result = true;
			}
			else if ((int)val.Type == 1 && (int)value.Type == 1)
			{
				if (DeepMerge((JObject)val, (JObject)value))
				{
					result = true;
				}
			}
			else if ((int)val.Type == 2 && (int)value.Type != 2)
			{
			}
		}
		return result;
	}
}
public static class IconLoader
{
	private static readonly Dictionary<string, Texture2D> _cache = new Dictionary<string, Texture2D>();

	private static bool _initialized = false;

	public static void Initialize()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		if (_initialized)
		{
			return;
		}
		string iconsFolder = GetIconsFolder();
		if (!Directory.Exists(iconsFolder))
		{
			Debug.LogWarning((object)("[IconLoader] Icons folder not found: " + iconsFolder));
			_initialized = true;
			return;
		}
		string[] files = Directory.GetFiles(iconsFolder, "*.png");
		foreach (string text in files)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
			try
			{
				byte[] array = File.ReadAllBytes(text);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)5, false);
				if (ImageConversion.LoadImage(val, array))
				{
					_cache[fileNameWithoutExtension] = val;
				}
				else
				{
					Debug.LogError((object)("[IconLoader] Failed to load image: " + text));
				}
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[IconLoader] Exception loading icon '{fileNameWithoutExtension}': {arg}");
			}
		}
		_initialized = true;
		Debug.Log((object)$"[IconLoader] Loaded {_cache.Count} icons from {iconsFolder}");
	}

	public static Texture2D GetIcon(string iconName)
	{
		if (!_initialized)
		{
			Initialize();
		}
		if (string.IsNullOrEmpty(iconName))
		{
			return null;
		}
		if (_cache.TryGetValue(iconName, out var value))
		{
			return value;
		}
		_cache.TryGetValue("Missing", out value);
		return value;
	}

	private static string GetIconsFolder()
	{
		string path = Path.Combine(Paths.PluginPath, "ItemFinder");
		return Path.Combine(path, "Icons");
	}
}
public class ItemFinder : MonoBehaviour
{
	public struct ItemData
	{
		public string itemType;

		public string biome;

		public Vector3 position;

		public string fullPath;

		public string objectName;

		public Campfire campfireRef;

		public string displayName;
	}

	[CompilerGenerated]
	private sealed class <>c__DisplayClass21_0
	{
		public string originalBiome;

		internal bool <ArrowOnlyCoroutine>b__1()
		{
			return BiomeDetector.CurrentBiome != originalBiome;
		}
	}

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

		private object <>2__current;

		public ItemFinder <>4__this;

		private <>c__DisplayClass21_0 <>8__1;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				logs.ClearLog();
				logs.Log("Arrow-only mode started. Waiting for level to be ready...");
				<>2__current = <>4__this.WaitForLevelReady();
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>2__current = (object)new WaitUntil((Func<bool>)(() => BiomeDetector.CurrentBiome != "Unknown"));
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				<>4__this.CurrentBiome = BiomeDetector.CurrentBiome;
				break;
			case 3:
				<>1__state = -1;
				<>4__this.CurrentBiome = BiomeDetector.CurrentBiome;
				logs.Log("Biome changed to: " + <>4__this.CurrentBiome);
				<>4__this.CurrentBiomeItems.Clear();
				<>4__this.ArrowManager.ClearAll();
				<>8__1 = null;
				break;
			}
			<>8__1 = new <>c__DisplayClass21_0();
			logs.Log("Starting item detection cycle in biome: " + <>4__this.CurrentBiome);
			<>4__this.FindAllItemsForCurrentBiome();
			<>4__this.EnsureArrowManager();
			<>4__this.ArrowManager.SpawnForItems(<>4__this.CurrentBiomeItems);
			logs.Log($"Arrows spawned for {<>4__this.CurrentBiomeItems.Count} items. Waiting for biome change...");
			<>8__1.originalBiome = <>4__this.CurrentBiome;
			<>2__current = (object)new WaitUntil((Func<bool>)(() => BiomeDetector.CurrentBiome != <>8__1.originalBiome));
			<>1__state = 3;
			return true;
		}

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

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

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

		private object <>2__current;

		public ItemFinder <>4__this;

		private SettingsConfig <config>5__1;

		private AutomationSettings <automation>5__2;

		private List<ItemData> <nonCampfireItems>5__3;

		private List<ItemData> <campfireItems>5__4;

		private ItemData <currentBiomeCampfire>5__5;

		private string <originalBiome>5__6;

		private float <timeout>5__7;

		private float <elapsed>5__8;

		private ScreenshotSettings <ssConfig>5__9;

		private Vector3 <offset>5__10;

		private Vector3 <facing>5__11;

		private Character <local>5__12;

		private Vector3 <teleportPos>5__13;

		private Vector3 <targetPos>5__14;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<config>5__1 = null;
			<automation>5__2 = null;
			<nonCampfireItems>5__3 = null;
			<campfireItems>5__4 = null;
			<currentBiomeCampfire>5__5 = default(ItemData);
			<originalBiome>5__6 = null;
			<ssConfig>5__9 = null;
			<local>5__12 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0494: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
			AutomationSettings automationSettings2;
			AutomationSettings automationSettings3;
			AutomationSettings automationSettings4;
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				logs.ClearLog();
				logs.Log("Full automation started. Waiting for level to be ready...");
				<>2__current = <>4__this.WaitForLevelReady();
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>2__current = (object)new WaitUntil((Func<bool>)(() => BiomeDetector.CurrentBiome != "Unknown"));
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				<>4__this.CurrentBiome = BiomeDetector.CurrentBiome;
				<config>5__1 = ConfigManager._settingsConfig;
				<automation>5__2 = <config>5__1?.automation;
				goto IL_062a;
			case 3:
				<>1__state = -1;
				goto IL_0187;
			case 4:
				<>1__state = -1;
				goto IL_02c4;
			case 5:
				<>1__state = -1;
				logs.Log("Triggering campfire...");
				<>2__current = Screenshotter.TriggerCampfireCoroutine(<>4__this, <currentBiomeCampfire>5__5);
				<>1__state = 6;
				return true;
			case 6:
				<>1__state = -1;
				if ((<automation>5__2?.screenshot?.enableBiomeScreenshotTeleport).GetValueOrDefault())
				{
					<ssConfig>5__9 = <automation>5__2.screenshot;
					<offset>5__10 = <ssConfig>5__9.biomeScreenshotOffset;
					<facing>5__11 = <ssConfig>5__9.biomeScreenshotFacing;
					logs.Log($"Teleporting for biome screenshot with offset: {<offset>5__10} and facing: {<facing>5__11}");
					<local>5__12 = Character.localCharacter;
					if ((Object)(object)<local>5__12 != (Object)null && !<local>5__12.data.dead)
					{
						<teleportPos>5__13 = <currentBiomeCampfire>5__5.position + <offset>5__10;
						((MonoBehaviourPun)<local>5__12).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { <teleportPos>5__13, true });
						<targetPos>5__14 = <currentBiomeCampfire>5__5.position + <facing>5__11;
						Screenshotter.FaceTarget(<local>5__12, <targetPos>5__14);
					}
					<ssConfig>5__9 = null;
					<local>5__12 = null;
				}
				<originalBiome>5__6 = <>4__this.CurrentBiome;
				<timeout>5__7 = <config>5__1.general.biomeChangeTimeout;
				<elapsed>5__8 = 0f;
				goto IL_054b;
			case 7:
				{
					<>1__state = -1;
					goto IL_054b;
				}
				IL_02c4:
				<currentBiomeCampfire>5__5 = <campfireItems>5__4.Find((ItemData c) => c.biome == <>4__this.CurrentBiome);
				if ((Object)(object)<currentBiomeCampfire>5__5.campfireRef != (Object)null)
				{
					AutomationSettings automationSettings = <automation>5__2;
					if (automationSettings == null || !automationSettings.skipCampfire)
					{
						logs.Log("Teleporting to campfire...");
						<>2__current = Screenshotter.TeleportToCampfireCoroutine(<>4__this, <currentBiomeCampfire>5__5);
						<>1__state = 5;
						return true;
					}
					logs.Log("Skipping campfire handling due to skip flag.");
					goto IL_05dc;
				}
				logs.Log("No campfire found for current biome: " + <>4__this.CurrentBiome + ". Cannot progress to next biome.");
				logs.Log("Automation completed or stopped.");
				return false;
				IL_05dc:
				<>4__this.CurrentBiomeItems.Clear();
				<>4__this.itemTypeCounter.Clear();
				<>4__this.ArrowManager.ClearAll();
				<nonCampfireItems>5__3 = null;
				<campfireItems>5__4 = null;
				<currentBiomeCampfire>5__5 = default(ItemData);
				goto IL_062a;
				IL_062a:
				logs.Log("Starting full automation cycle in biome: " + <>4__this.CurrentBiome);
				automationSettings2 = <automation>5__2;
				if (automationSettings2 == null || !automationSettings2.skipLuggage)
				{
					if (<config>5__1.general.OpenLuggageAutomatically)
					{
						<>2__current = <>4__this.OpenLuggageAndWaitForItems();
						<>1__state = 3;
						return true;
					}
					logs.Log("Skipping luggage opening due to config.");
				}
				else
				{
					logs.Log("Skipping luggage opening due to skip flag.");
				}
				goto IL_0187;
				IL_0187:
				<>4__this.FindAllItemsForCurrentBiome();
				<>4__this.EnsureArrowManager();
				<>4__this.ArrowManager.SpawnForItems(<>4__this.CurrentBiomeItems);
				logs.Log($"Spawned arrows for {<>4__this.CurrentBiomeItems.Count} items.");
				<nonCampfireItems>5__3 = <>4__this.CurrentBiomeItems.FindAll((ItemData item) => item.itemType != "Campfire");
				<campfireItems>5__4 = <>4__this.CurrentBiomeItems.FindAll((ItemData item) => item.itemType == "Campfire");
				automationSettings3 = <automation>5__2;
				if ((automationSettings3 == null || !automationSettings3.skipScreenshots) && <nonCampfireItems>5__3.Count > 0)
				{
					<>2__current = Screenshotter.ScreenshotItemCoroutine(<>4__this, <>4__this.itemTypeCounter);
					<>1__state = 4;
					return true;
				}
				automationSettings4 = <automation>5__2;
				if (automationSettings4 != null && automationSettings4.skipScreenshots)
				{
					logs.Log("Skipping screenshots due to skip flag.");
				}
				goto IL_02c4;
				IL_054b:
				if (BiomeDetector.CurrentBiome == <originalBiome>5__6 && <elapsed>5__8 < <timeout>5__7)
				{
					<elapsed>5__8 += Time.deltaTime;
					<>2__current = null;
					<>1__state = 7;
					return true;
				}
				<>4__this.CurrentBiome = BiomeDetector.CurrentBiome;
				logs.Log("Biome changed to: " + <>4__this.CurrentBiome);
				<originalBiome>5__6 = null;
				goto IL_05dc;
			}
		}

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

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

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

		private object <>2__current;

		public ItemFinder <>4__this;

		private List<Luggage> <luggageToOpen>5__1;

		private int <itemCountBefore>5__2;

		private float <timeout>5__3;

		private float <elapsed>5__4;

		private int <stableCount>5__5;

		private int <lastItemCount>5__6;

		private List<Luggage>.Enumerator <>s__7;

		private Luggage <lug>5__8;

		private Exception <ex>5__9;

		private int <stillClosed>5__10;

		private int <i>5__11;

		private int <currentItemCount>5__12;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<luggageToOpen>5__1 = null;
			<>s__7 = default(List<Luggage>.Enumerator);
			<lug>5__8 = null;
			<ex>5__9 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Expected O, but got Unknown
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				logs.Log("[ItemFinder] OpenAllLuggageCoroutine started");
				<>4__this.CurrentBiome = BiomeDetector.CurrentBiome;
				logs.Log("[ItemFinder] Current biome: " + <>4__this.CurrentBiome);
				if (!ConfigManager._settingsConfig.general.OpenLuggageAutomatically)
				{
					logs.Log("[ItemFinder] OpenLuggageAutomatically is disabled in config");
					return false;
				}
				<luggageToOpen>5__1 = (from l in Luggage.ALL_LUGGAGE.ToList()
					where (Object)(object)l != (Object)null && ((Component)l).gameObject.activeInHierarchy && l.IsInteractible((Character)null)
					select l).ToList();
				if (<luggageToOpen>5__1.Count == 0)
				{
					logs.Log("[ItemFinder] No interactible luggage found to open");
					return false;
				}
				logs.Log($"[ItemFinder] Found {<luggageToOpen>5__1.Count} luggage items to open");
				<itemCountBefore>5__2 = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0).Length;
				logs.Log($"[ItemFinder] Object count before opening: {<itemCountBefore>5__2}");
				<>s__7 = <luggageToOpen>5__1.GetEnumerator();
				try
				{
					while (<>s__7.MoveNext())
					{
						<lug>5__8 = <>s__7.Current;
						try
						{
							if ((Object)(object)<lug>5__8 != (Object)null && ((Component)<lug>5__8).gameObject.activeInHierarchy)
							{
								((MonoBehaviourPun)<lug>5__8).photonView.RPC("OpenLuggageRPC", (RpcTarget)0, new object[1] { true });
								logs.Log("[ItemFinder] Opened: " + ((Object)((Component)<lug>5__8).gameObject).name);
							}
						}
						catch (Exception ex)
						{
							<ex>5__9 = ex;
							Luggage obj = <lug>5__8;
							object obj2;
							if (obj == null)
							{
								obj2 = null;
							}
							else
							{
								GameObject gameObject = ((Component)obj).gameObject;
								obj2 = ((gameObject != null) ? ((Object)gameObject).name : null);
							}
							if (obj2 == null)
							{
								obj2 = "null";
							}
							logs.Log("[ItemFinder] Failed to open " + (string?)obj2 + ": " + <ex>5__9.Message);
						}
						<lug>5__8 = null;
					}
				}
				finally
				{
					((IDisposable)<>s__7).Dispose();
				}
				<>s__7 = default(List<Luggage>.Enumerator);
				<>2__current = (object)new WaitForSeconds(0.5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<timeout>5__3 = 5f;
				<elapsed>5__4 = 0f;
				goto IL_031b;
			case 2:
				<>1__state = -1;
				goto IL_031b;
			case 3:
				{
					<>1__state = -1;
					<currentItemCount>5__12 = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0).Length;
					if (<currentItemCount>5__12 == <lastItemCount>5__6)
					{
						<stableCount>5__5++;
						if (<stableCount>5__5 >= 20)
						{
							logs.Log($"[ItemFinder] Item spawning stabilized. Objects: {<itemCountBefore>5__2} -> {<currentItemCount>5__12}");
							break;
						}
					}
					else
					{
						<stableCount>5__5 = 0;
						<lastItemCount>5__6 = <currentItemCount>5__12;
					}
					<i>5__11++;
					goto IL_041a;
				}
				IL_041a:
				if (<i>5__11 < 100)
				{
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 3;
					return true;
				}
				break;
				IL_031b:
				if (<elapsed>5__4 < <timeout>5__3)
				{
					<stillClosed>5__10 = (from l in Luggage.ALL_LUGGAGE.ToList()
						where (Object)(object)l != (Object)null && ((Component)l).gameObject.activeInHierarchy && l.IsInteractible((Character)null)
						select l).Count();
					if (<stillClosed>5__10 != 0)
					{
						<elapsed>5__4 += Time.deltaTime;
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					logs.Log("[ItemFinder] All luggage opened successfully");
				}
				logs.Log("[ItemFinder] Waiting for items to spawn...");
				<stableCount>5__5 = 0;
				<lastItemCount>5__6 = <itemCountBefore>5__2;
				<i>5__11 = 0;
				goto IL_041a;
			}
			logs.Log("[ItemFinder] Luggage opening complete.");
			return false;
		}

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

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

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

		private object <>2__current;

		public ItemFinder <>4__this;

		private int <initialItemCount>5__1;

		private List<Luggage> <luggageToOpen>5__2;

		private float <timeout>5__3;

		private float <elapsed>5__4;

		private int <stableCount>5__5;

		private int <lastItemCount>5__6;

		private List<Luggage>.Enumerator <>s__7;

		private Luggage <lug>5__8;

		private Exception <ex>5__9;

		private int <stillClosed>5__10;

		private int <i>5__11;

		private int <currentItemCount>5__12;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<luggageToOpen>5__2 = null;
			<>s__7 = default(List<Luggage>.Enumerator);
			<lug>5__8 = null;
			<ex>5__9 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Expected O, but got Unknown
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (!ConfigManager._settingsConfig.general.OpenLuggageAutomatically)
				{
					logs.Log("Skipping luggage opening due to config.");
					return false;
				}
				logs.Log("Opening all luggage and waiting for item spawn completion...");
				<initialItemCount>5__1 = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0).Length;
				<luggageToOpen>5__2 = (from l in Luggage.ALL_LUGGAGE.ToList()
					where (Object)(object)l != (Object)null && ((Component)l).gameObject.activeInHierarchy && l.IsInteractible((Character)null)
					select l).ToList();
				logs.Log($"Found {<luggageToOpen>5__2.Count} luggage items to open");
				<>s__7 = <luggageToOpen>5__2.GetEnumerator();
				try
				{
					while (<>s__7.MoveNext())
					{
						<lug>5__8 = <>s__7.Current;
						try
						{
							if (((Component)<lug>5__8).gameObject.activeInHierarchy)
							{
								((MonoBehaviourPun)<lug>5__8).photonView.RPC("OpenLuggageRPC", (RpcTarget)0, new object[1] { true });
								logs.Log("Opened luggage: " + ((Object)((Component)<lug>5__8).gameObject).name);
							}
							else
							{
								logs.Log("Skipped inactive luggage: " + ((Object)((Component)<lug>5__8).gameObject).name);
							}
						}
						catch (Exception ex)
						{
							<ex>5__9 = ex;
							logs.Log("Failed to open luggage " + ((Object)((Component)<lug>5__8).gameObject).name + ": " + <ex>5__9.Message);
						}
						<lug>5__8 = null;
					}
				}
				finally
				{
					((IDisposable)<>s__7).Dispose();
				}
				<>s__7 = default(List<Luggage>.Enumerator);
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<timeout>5__3 = 10f;
				<elapsed>5__4 = 0f;
				goto IL_029e;
			case 2:
				<>1__state = -1;
				goto IL_029e;
			case 3:
				{
					<>1__state = -1;
					<currentItemCount>5__12 = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0).Length;
					if (<currentItemCount>5__12 == <lastItemCount>5__6)
					{
						<stableCount>5__5++;
						if (<stableCount>5__5 >= 20)
						{
							logs.Log($"Item spawning stabilized at {<currentItemCount>5__12} objects (was {<initialItemCount>5__1})");
							break;
						}
					}
					else
					{
						<stableCount>5__5 = 0;
						<lastItemCount>5__6 = <currentItemCount>5__12;
					}
					<i>5__11++;
					goto IL_039d;
				}
				IL_039d:
				if (<i>5__11 < 100)
				{
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 3;
					return true;
				}
				break;
				IL_029e:
				if (<elapsed>5__4 < <timeout>5__3)
				{
					<stillClosed>5__10 = (from l in Luggage.ALL_LUGGAGE.ToList()
						where (Object)(object)l != (Object)null && ((Component)l).gameObject.activeInHierarchy && l.IsInteractible((Character)null)
						select l).Count();
					if (<stillClosed>5__10 != 0)
					{
						<elapsed>5__4 += Time.deltaTime;
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
				}
				logs.Log("All accessible luggage opened. Waiting for item spawning to complete...");
				<stableCount>5__5 = 0;
				<lastItemCount>5__6 = <initialItemCount>5__1;
				<i>5__11 = 0;
				goto IL_039d;
			}
			logs.Log("Luggage opening and item spawning complete.");
			return false;
		}

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

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

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

		private object <>2__current;

		public ItemFinder <>4__this;

		private int <activeLuggage>5__1;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				logs.Log("Waiting for level to be fully ready...");
				<>2__current = (object)new WaitUntil((Func<bool>)(() => logs.LevelReady));
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				logs.Log("Basic level ready flag detected.");
				logs.Log("Waiting 2 seconds for GameObjects to settle...");
				<>2__current = (object)new WaitForSeconds(2f);
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				logs.Log("2 second wait complete.");
				<>2__current = (object)new WaitUntil((Func<bool>)(() => Luggage.ALL_LUGGAGE.Count > 0));
				<>1__state = 3;
				return true;
			case 3:
				<>1__state = -1;
				<activeLuggage>5__1 = Luggage.ALL_LUGGAGE.Where((Luggage l) => (Object)(object)l != (Object)null && ((Component)l).gameObject.activeInHierarchy).Count();
				logs.Log($"Level ready - Found {<activeLuggage>5__1} active luggage out of {Luggage.ALL_LUGGAGE.Count} total.");
				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();
		}
	}

	public string OutputDirectory;

	public string SessionTimestamp;

	public List<ItemData> CurrentBiomeItems = new List<ItemData>();

	public string CurrentBiome = "Unknown";

	private Dictionary<string, int> itemTypeCounter = new Dictionary<string, int>();

	private HashSet<string> customItems = new HashSet<string>();

	private HashSet<string> selectedCustomItems = new HashSet<string>();

	private static GameObject[] _cachedObjects;

	private static string _lastScannedBiome;

	private static Dictionary<int, string> _pathCache = new Dictionary<int, string>();

	public ArrowLabelManager ArrowManager { get; private set; }

	private void Awake()
	{
		Debug.Log((object)("[ItemFinder] Awake called on GameObject: " + ((Object)((Component)this).gameObject).name));
		BiomeDetector.Initialize();
		OutputDirectory = ConfigManager._settingsConfig?.general?.GetOutputDirectory();
		SessionTimestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
		ConfigManager.LoadConfigs();
		RefreshCustomItemsFromConfig();
		BiomeDetector.DetectInitialBiome();
		CurrentBiome = BiomeDetector.CurrentBiome;
		logs.Log("[ItemFinder] Initialized with biome: " + CurrentBiome);
		ArrowLabelManager component = ((Component)this).gameObject.GetComponent<ArrowLabelManager>();
		if ((Object)(object)component != (Object)null)
		{
			ArrowManager = component;
		}
	}

	public void EnsureArrowManager()
	{
		if ((Object)(object)ArrowManager == (Object)null)
		{
			ArrowLabelManager arrowLabelManager = ((Component)this).gameObject.GetComponent<ArrowLabelManager>();
			if ((Object)(object)arrowLabelManager == (Object)null)
			{
				arrowLabelManager = ((Component)this).gameObject.AddComponent<ArrowLabelManager>();
				Debug.Log((object)"[ItemFinder] Added ArrowLabelManager component at runtime.");
			}
			ArrowManager = arrowLabelManager;
			Debug.Log((object)$"[ItemFinder] EnsureArrowManager on ItemFinder '{((Object)((Component)this).gameObject).name}' (ItemFinder id {((Object)this).GetInstanceID()}) - existing ALM: {arrowLabelManager}");
		}
	}

	private string GetFullPath(GameObject obj)
	{
		int instanceID = ((Object)obj).GetInstanceID();
		if (_pathCache.TryGetValue(instanceID, out var value))
		{
			return value;
		}
		string text = ((Object)obj).name;
		Transform val = obj.transform;
		while ((Object)(object)val.parent != (Object)null)
		{
			val = val.parent;
			text = ((Object)val).name + "/" + text;
		}
		_pathCache[instanceID] = text;
		return text;
	}

	private string NormalizeName(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return "";
		}
		name = name.Trim();
		int num = name.IndexOf('(');
		if (num >= 0)
		{
			name = name.Substring(0, num);
		}
		return name.Trim();
	}

	private void SaveItemsToFile()
	{
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (string.IsNullOrEmpty(OutputDirectory) || string.IsNullOrEmpty(SessionTimestamp))
			{
				logs.Log("Cannot save items - missing directory or timestamp");
				return;
			}
			string text = "items_" + CurrentBiome + "_" + SessionTimestamp + ".txt";
			string path = Path.Combine(OutputDirectory, text);
			using (StreamWriter streamWriter = new StreamWriter(path))
			{
				streamWriter.WriteLine("Biome: " + CurrentBiome);
				streamWriter.WriteLine("Timestamp: " + SessionTimestamp);
				streamWriter.WriteLine($"Total Items Found: {CurrentBiomeItems.Count}");
				streamWriter.WriteLine("----------------------------------------");
				foreach (ItemData currentBiomeItem in CurrentBiomeItems)
				{
					streamWriter.WriteLine("Item: " + currentBiomeItem.itemType);
					streamWriter.WriteLine($"Position: {currentBiomeItem.position}");
					streamWriter.WriteLine("Object Name: " + currentBiomeItem.objectName);
					streamWriter.WriteLine("Full Path: " + currentBiomeItem.fullPath);
					streamWriter.WriteLine("---");
				}
			}
			logs.Log($"Saved {CurrentBiomeItems.Count} items to {text}");
		}
		catch (Exception ex)
		{
			logs.Log("Error saving items to file: " + ex.Message);
		}
	}

	public void RunArrowOnlyMode()
	{
		((MonoBehaviour)this).StartCoroutine(ArrowOnlyCoroutine());
	}

	[IteratorStateMachine(typeof(<ArrowOnlyCoroutine>d__21))]
	private IEnumerator ArrowOnlyCoroutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ArrowOnlyCoroutine>d__21(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<WaitForLevelReady>d__22))]
	private IEnumerator WaitForLevelReady()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitForLevelReady>d__22(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<OpenLuggageAndWaitForItems>d__23))]
	private IEnumerator OpenLuggageAndWaitForItems()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <OpenLuggageAndWaitForItems>d__23(0)
		{
			<>4__this = this
		};
	}

	[IteratorStateMachine(typeof(<OpenAllLuggageCoroutine>d__24))]
	public IEnumerator OpenAllLuggageCoroutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <OpenAllLuggageCoroutine>d__24(0)
		{
			<>4__this = this
		};
	}

	public void RunFullAutomation()
	{
		((MonoBehaviour)this).StartCoroutine(FullAutomationCoroutine());
	}

	[IteratorStateMachine(typeof(<FullAutomationCoroutine>d__26))]
	private IEnumerator FullAutomationCoroutine()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <FullAutomationCoroutine>d__26(0)
		{
			<>4__this = this
		};
	}

	private void RefreshCustomItemsFromConfig()
	{
		customItems.Clear();
		selectedCustomItems.Clear();
		CustomItemDetectionRule[] array = ConfigManager._itemsConfig?.customItems ?? Array.Empty<CustomItemDetectionRule>();
		foreach (CustomItemDetectionRule customItemDetectionRule in array)
		{
			string item = ConfigManager.NormalizeName(customItemDetectionRule.itemType);
			customItems.Add(item);
			if (customItemDetectionRule.selected)
			{
				selectedCustomItems.Add(item);
			}
		}
		Debug.Log((object)$"[ItemFinder] Refreshed custom items: {customItems.Count} total, {selectedCustomItems.Count} selected");
	}

	private GameObject GetItemObject(GameObject obj)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return null;
		}
		if (obj.transform.childCount > 0)
		{
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)obj.transform.GetChild(i)).gameObject;
				if (ConfigManager.NormalizeName(((Object)obj).name) == ConfigManager.NormalizeName(((Object)gameObject).name))
				{
					return gameObject;
				}
			}
		}
		return obj;
	}

	public void FindAllItemsForCurrentBiome()
	{
		//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_063d: Unknown result type (might be due to invalid IL or missing references)
		//IL_077e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0780: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
		logs.Log("=== DEBUG: Starting FindAllItemsForCurrentBiome ===");
		logs.Log($"ConfigManager._itemsConfig is null: {ConfigManager._itemsConfig == null}");
		if (ConfigManager._itemsConfig != null)
		{
			logs.Log($"dbItems is null: {ConfigManager._itemsConfig.dbItems == null}");
			logs.Log($"customItems is null: {ConfigManager._itemsConfig.customItems == null}");
			logs.Log($"campfireRules is null: {ConfigManager._itemsConfig.campfireRules == null}");
		}
		logs.Log($"ItemNameManager.Instance is null: {ItemNameManager.Instance == null}");
		logs.Log("OutputDirectory: " + OutputDirectory);
		logs.Log("CurrentBiome: " + CurrentBiome);
		if (!Directory.Exists(OutputDirectory))
		{
			logs.Log("Creating output directory...");
			Directory.CreateDirectory(OutputDirectory);
		}
		CurrentBiomeItems.Clear();
		logs.Log("DEBUG: CurrentBiomeItems cleared");
		bool flag = _cachedObjects != null && _cachedObjects.Any((GameObject obj) => (Object)(object)obj == (Object)null);
		if (_lastScannedBiome != CurrentBiome || _cachedObjects == null || flag)
		{
			if (flag)
			{
				logs.Log("DEBUG: Cache contains destroyed objects, rescanning...");
			}
			else
			{
				logs.Log("DEBUG: About to scan for objects...");
			}
			_cachedObjects = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			GameObject[] cachedObjects = _cachedObjects;
			logs.Log($"DEBUG: Found {((cachedObjects != null) ? cachedObjects.Length : 0)} objects");
			_pathCache.Clear();
			_lastScannedBiome = CurrentBiome;
			logs.Log("DEBUG: About to filter luggage...");
			try
			{
				List<GameObject> list = _cachedObjects.Where((GameObject obj) => (Object)(object)obj != (Object)null && ((Object)obj).name != null && ((Object)obj).name.Contains("Luggage")).ToList();
				logs.Log($"Debug: Found {list.Count} active luggage objects in scene");
				foreach (GameObject item in list.Take(10))
				{
					logs.Log("Debug luggage name: '" + (((item != null) ? ((Object)item).name : null) ?? "NULL") + "'");
				}
			}
			catch (Exception arg)
			{
				logs.Log($"DEBUG ERROR in luggage filtering: {arg}");
			}
		}
		logs.Log("DEBUG: About to build campfire biome mapping...");
		Dictionary<Campfire, string> dictionary = new Dictionary<Campfire, string>();
		try
		{
			Campfire[] array = Object.FindObjectsByType<Campfire>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			logs.Log($"DEBUG: Found {((array != null) ? array.Length : 0)} campfires");
			Campfire[] array2 = array;
			foreach (Campfire val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					logs.Log("DEBUG: Null campfire found, skipping");
					continue;
				}
				string value = "UNKNOWN";
				CampfireRule[] array3 = ConfigManager._itemsConfig?.campfireRules ?? Array.Empty<CampfireRule>();
				foreach (CampfireRule campfireRule in array3)
				{
					if (ConfigManager.MatchesDetection(((Component)val).gameObject, campfireRule))
					{
						value = campfireRule.biome;
						break;
					}
				}
				dictionary[val] = value;
			}
			logs.Log($"DEBUG: Built campfire mapping for {dictionary.Count} campfires");
		}
		catch (Exception arg2)
		{
			logs.Log($"DEBUG ERROR in campfire mapping: {arg2}");
		}
		logs.Log("DEBUG: About to start object processing...");
		HashSet<Vector3> hashSet = new HashSet<Vector3>();
		try
		{
			GameObject[] cachedObjects2 = _cachedObjects;
			logs.Log($"DEBUG: Processing {((cachedObjects2 != null) ? cachedObjects2.Length : 0)} cached objects");
			GameObject[] array4 = _cachedObjects ?? Array.Empty<GameObject>();
			foreach (GameObject val2 in array4)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				GameObject itemObject = GetItemObject(val2);
				if ((Object)(object)itemObject == (Object)null)
				{
					continue;
				}
				Transform val3 = null;
				try
				{
					val3 = itemObject.transform.root;
				}
				catch
				{
					continue;
				}
				if ((Object)(object)val3 != (Object)null && ((Object)val3).name == "GAME")
				{
					continue;
				}
				Vector3 position;
				try
				{
					position = itemObject.transform.position;
				}
				catch
				{
					continue;
				}
				if (!((Object)itemObject).name.Contains("Luggage") && hashSet.Contains(position))
				{
					continue;
				}
				bool flag2 = false;
				CustomItemDetectionRule[] array5 = ConfigManager._itemsConfig?.dbItems ?? Array.Empty<CustomItemDetectionRule>();
				foreach (CustomItemDetectionRule customItemDetectionRule in array5)
				{
					if (customItemDetectionRule == null || (customItemDetectionRule.biome != CurrentBiome && customItemDetectionRule.biome != "ANY"))
					{
						continue;
					}
					bool flag3 = false;
					try
					{
						flag3 = ConfigManager.MatchesDetection(itemObject, customItemDetectionRule);
					}
					catch (Exception arg3)
					{
						logs.Log($"DEBUG ERROR in MatchesDetection (db): {arg3}");
					}
					if (flag3)
					{
						string itemType = customItemDetectionRule.itemType;
						string displayName = ((ItemNameManager.Instance != null) ? ItemNameManager.Instance.GetNiceName(((Object)itemObject).name) : ((Object)itemObject).name);
						CurrentBiomeItems.Add(new ItemData
						{
							itemType = itemType,
							biome = CurrentBiome,
							position = position,
							fullPath = GetFullPath(itemObject),
							objectName = ((Object)itemObject).name,
							displayName = displayName
						});
						if (!((Object)itemObject).name.Contains("Luggage"))
						{
							hashSet.Add(position);
						}
						flag2 = true;
						break;
					}
				}
				if (flag2)
				{
					continue;
				}
				CustomItemDetectionRule[] array6 = ConfigManager._itemsConfig?.customItems ?? Array.Empty<CustomItemDetectionRule>();
				foreach (CustomItemDetectionRule customItemDetectionRule2 in array6)
				{
					if (customItemDetectionRule2 == null || (customItemDetectionRule2.biome != CurrentBiome && customItemDetectionRule2.biome != "ANY"))
					{
						continue;
					}
					bool flag4 = false;
					try
					{
						flag4 = ConfigManager.MatchesDetection(itemObject, customItemDetectionRule2);
					}
					catch (Exception arg4)
					{
						logs.Log($"DEBUG ERROR in MatchesDetection (custom): {arg4}");
					}
					if (flag4 && IsCustomItemSelected(customItemDetectionRule2.itemType))
					{
						string itemType2 = customItemDetectionRule2.itemType;
						string displayName2 = ((!string.IsNullOrEmpty(customItemDetectionRule2.niceName)) ? customItemDetectionRule2.niceName : customItemDetectionRule2.itemType);
						CurrentBiomeItems.Add(new ItemData
						{
							itemType = itemType2,
							biome = CurrentBiome,
							position = position,
							fullPath = GetFullPath(itemObject),
							objectName = ((Object)itemObject).name,
							displayName = displayName2
						});
						if (!((Object)itemObject).name.Contains("Luggage"))
						{
							hashSet.Add(position);
						}
						break;
					}
				}
			}
			logs.Log($"DEBUG: Finished processing objects, found {CurrentBiomeItems.Count} items so far");
		}
		catch (Exception arg5)
		{
			logs.Log($"DEBUG ERROR in object processing: {arg5}");
		}
		logs.Log("DEBUG: About to add campfires...");
		try
		{
			foreach (KeyValuePair<Campfire, string> item2 in dictionary)
			{
				if (!(item2.Value != CurrentBiome))
				{
					CurrentBiomeItems.Add(new ItemData
					{
						itemType = "Campfire",
						biome = item2.Value,
						position = ((Component)item2.Key).transform.position,
						fullPath = GetFullPath(((Component)item2.Key).gameObject),
						objectName = ((Object)item2.Key).name,
						campfireRef = item2.Key
					});
				}
			}
			logs.Log($"DEBUG: Added campfires, total items now: {CurrentBiomeItems.Count}");
		}
		catch (Exception arg6)
		{
			logs.Log($"DEBUG ERROR adding campfires: {arg6}");
		}
		logs.Log("DEBUG: About to save items to file...");
		try
		{
			SaveItemsToFile();
			logs.Log("DEBUG: SaveItemsToFile completed successfully");
		}
		catch (Exception arg7)
		{
			logs.Log($"DEBUG ERROR in SaveItemsToFile: {arg7}");
		}
		logs.Log("=== DEBUG: FindAllItemsForCurrentBiome completed ===");
	}

	public void ReloadAndSpawnItems()
	{
		//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0720: Unknown result type (might be due to invalid IL or missing references)
		//IL_0722: Unknown result type (might be due to invalid IL or missing references)
		//IL_0770: Unknown result type (might be due to invalid IL or missing references)
		//IL_0850: Unknown result type (might be due to invalid IL or missing references)
		//IL_0855: Unknown result type (might be due to invalid IL or missing references)
		//IL_044d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_0472: Unknown result type (might be due to invalid IL or missing references)
		logs.Log("[ItemFinder] ReloadAndSpawnItems() called - forcing complete refresh.");
		EnsureArrowManager();
		if ((Object)(object)ArrowManager == (Object)null)
		{
			logs.Log("[ItemFinder] ArrowManager is null after EnsureArrowManager(). Aborting reload to avoid NRE.");
			return;
		}
		try
		{
			ArrowManager.ClearAll();
			logs.Log("[ItemFinder] Cleared all existing arrows.");
		}
		catch (Exception ex)
		{
			logs.Log("[ItemFinder] Error clearing arrows: " + ex.Message);
		}
		logs.Log($"[ItemFinder] CurrentBiomeItems count before clear: {CurrentBiomeItems.Count}");
		CurrentBiomeItems.Clear();
		logs.Log($"[ItemFinder] CurrentBiomeItems count after clear: {CurrentBiomeItems.Count}");
		logs.Log("=== DEBUG: Starting FindAllItemsForCurrentBiome ===");
		if (!Directory.Exists(OutputDirectory))
		{
			logs.Log("Creating output directory...");
			Directory.CreateDirectory(OutputDirectory);
		}
		bool flag = _cachedObjects != null && _cachedObjects.Any((GameObject obj) => (Object)(object)obj == (Object)null);
		if (_cachedObjects == null || flag)
		{
			_cachedObjects = Object.FindObjectsByType<GameObject>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			GameObject[] cachedObjects = _cachedObjects;
			logs.Lo