Decompiled source of ItemFinder v1.0.0

plugins/ItemFinder.dll

Decompiled 18 hours 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 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_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		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));
		}
	}

	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 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("Started BiomeDetector - Scene: " + name);
		Application.logMessageReceived += new LogCallback(OnLogMessageReceived);
	}

	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>((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("Initial biome detected: " + CurrentBiome + " (found crashed plane)");
					break;
				}
			}
		}
	}

	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)
			{
				CurrentBiome = text;
				logs.Log("Biome detected: " + 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();
}
[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 UnityCoordinatesFontSize = 18;

	public float coordinatesUpdateRate = 10f;

	public int? AscentToLoad = null;

	public int? LevelToLoad = null;

	public int? Levelindex = null;

	public string[] validBiomes = new string[7] { "SHORE", "TROPICS", "MESA", "ALPINE", "CALDERA", "KILN", "THE KILN" };

	public KeyboardSettings keyboard = new KeyboardSettings();

	public bool OpenLuggageAutomatically = false;

	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 bool requireShiftModifier = false;

	public string itemSelectorToggleKey = "I";

	public string fullAutomationKey = "F4";

	public string arrowModeKey = "F3";

	public string toggleArrowsKey = "F1";

	public string toggleLabelsKey = "F2";

	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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_0015: Unknown result type (might be due to invalid IL or missing references)
		if (Enum.TryParse<KeyCode>(keyString, out KeyCode result))
		{
			return result;
		}
		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 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))
			{
				string text = File.ReadAllText(ItemsConfigPath);
				logs.Log("[DEBUG] 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 = CreateDefaultItemRules();
				}
				if (_itemsConfig.campfireRules == null)
				{
					_itemsConfig.campfireRules = CreateDefaultCampfireRules();
				}
			}
			else
			{
				_itemsConfig = CreateDefaultItemsConfig();
				SaveItemsConfig();
			}
		}
		catch
		{
			_itemsConfig = CreateDefaultItemsConfig();
		}
	}

	public static void LoadSettingsConfig()
	{
		try
		{
			EnsureConfigDirectoryExists();
			if (File.Exists(SettingsConfigPath))
			{
				string text = File.ReadAllText(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();
				}
			}
			else
			{
				_settingsConfig = CreateDefaultSettingsConfig();
				SaveSettingsConfig();
			}
		}
		catch
		{
			_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 = CreateDefaultItemRules();
		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()
		};
	}

	private static CustomItemDetectionRule[] CreateDefaultItemRules()
	{
		return new CustomItemDetectionRule[7]
		{
			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 = "ALPINE",
				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"
			}
		};
	}

	private 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 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>.Enumerator <>s__1;

		private Luggage <lug>5__2;

		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()
		{
			<>s__1 = default(List<Luggage>.Enumerator);
			<lug>5__2 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (ConfigManager._settingsConfig.general.OpenLuggageAutomatically)
				{
					<>s__1 = Luggage.ALL_LUGGAGE.ToList().GetEnumerator();
					try
					{
						while (<>s__1.MoveNext())
						{
							<lug>5__2 = <>s__1.Current;
							if (<lug>5__2.IsInteractible((Character)null))
							{
								((MonoBehaviourPun)<lug>5__2).photonView.RPC("OpenLuggageRPC", (RpcTarget)0, new object[1] { true });
							}
							<lug>5__2 = null;
						}
					}
					finally
					{
						((IDisposable)<>s__1).Dispose();
					}
					<>s__1 = default(List<Luggage>.Enumerator);
					<>2__current = (object)new WaitUntil((Func<bool>)(() => Luggage.ALL_LUGGAGE.All((Luggage l) => !l.IsInteractible((Character)null))));
					<>1__state = 1;
					return true;
				}
				logs.Log("Skipping OpenAllLuggageCoroutine due to config.");
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			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));
		OutputDirectory = ConfigManager._settingsConfig?.general?.GetOutputDirectory();
		SessionTimestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
		ConfigManager.LoadConfigs();
		RefreshCustomItemsFromConfig();
		BiomeDetector.DetectInitialBiome();
		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;
		}
	}

	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");
	}

	public void FindAllItemsForCurrentBiome()
	{
		//IL_07b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: 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_047b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_056c: Unknown result type (might be due to invalid IL or missing references)
		//IL_056e: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a9: 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)
				{
					logs.Log("DEBUG: Null object in cached objects, skipping");
					continue;
				}
				Vector3 position = val2.transform.position;
				if (!((Object)val2).name.Contains("Luggage") && hashSet.Contains(position))
				{
					continue;
				}
				if (!((Object)val2).name.Contains("Luggage"))
				{
					hashSet.Add(position);
				}
				bool flag2 = false;
				CustomItemDetectionRule[] array5 = ConfigManager._itemsConfig?.dbItems ?? Array.Empty<CustomItemDetectionRule>();
				foreach (CustomItemDetectionRule customItemDetectionRule in array5)
				{
					if ((!(customItemDetectionRule.biome != CurrentBiome) || !(customItemDetectionRule.biome != "ANY")) && ConfigManager.MatchesDetection(val2, customItemDetectionRule))
					{
						string itemType = customItemDetectionRule.itemType;
						string niceName = ItemNameManager.Instance.GetNiceName(((Object)val2).name);
						CurrentBiomeItems.Add(new ItemData
						{
							itemType = itemType,
							biome = CurrentBiome,
							position = position,
							fullPath = GetFullPath(val2),
							objectName = ((Object)val2).name,
							displayName = niceName
						});
						flag2 = true;
						break;
					}
				}
				if (flag2)
				{
					continue;
				}
				CustomItemDetectionRule[] array6 = ConfigManager._itemsConfig?.customItems ?? Array.Empty<CustomItemDetectionRule>();
				foreach (CustomItemDetectionRule customItemDetectionRule2 in array6)
				{
					if ((!(customItemDetectionRule2.biome != CurrentBiome) || !(customItemDetectionRule2.biome != "ANY")) && ConfigManager.MatchesDetection(val2, customItemDetectionRule2) && IsCustomItemSelected(customItemDetectionRule2.itemType))
					{
						string itemType2 = customItemDetectionRule2.itemType;
						string displayName = ((!string.IsNullOrEmpty(customItemDetectionRule2.niceName)) ? customItemDetectionRule2.niceName : customItemDetectionRule2.itemType);
						CurrentBiomeItems.Add(new ItemData
						{
							itemType = itemType2,
							biome = CurrentBiome,
							position = position,
							fullPath = GetFullPath(val2),
							objectName = ((Object)val2).name,
							displayName = displayName
						});
						break;
					}
				}
			}
			logs.Log($"DEBUG: Finished processing objects, found {CurrentBiomeItems.Count} items so far");
		}
		catch (Exception arg3)
		{
			logs.Log($"DEBUG ERROR in object processing: {arg3}");
		}
		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 arg4)
		{
			logs.Log($"DEBUG ERROR adding campfires: {arg4}");
		}
		logs.Log("DEBUG: About to save items to file...");
		try
		{
			SaveItemsToFile();
			logs.Log("DEBUG: SaveItemsToFile completed successfully");
		}
		catch (Exception arg5)
		{
			logs.Log($"DEBUG ERROR in SaveItemsToFile: {arg5}");
		}
		logs.Log("=== DEBUG: FindAllItemsForCurrentBiome completed ===");
	}

	public void ReloadAndSpawnItems()
	{
		Debug.Log((object)"[ItemFinder] ReloadAndSpawnItems() called.");
		_lastScannedBiome = null;
		_cachedObjects = null;
		EnsureArrowManager();
		FindAllItemsForCurrentBiome();
		if ((Object)(object)ArrowManager != (Object)null)
		{
			ArrowManager.SpawnForItems(CurrentBiomeItems);
		}
		Debug.Log((object)"[ItemFinder] ReloadAndSpawnItems() completed.");
	}

	public bool IsCustomItem(string itemName)
	{
		return customItems.Contains(ConfigManager.NormalizeName(itemName));
	}

	public bool IsCustomItemSelected(string itemName)
	{
		string item = ConfigManager.NormalizeName(itemName);
		return selectedCustomItems.Contains(item);
	}

	public void SetCustomItemSelected(string itemName, bool selected)
	{
		string text = ConfigManager.NormalizeName(itemName);
		if (!customItems.Contains(text))
		{
			return;
		}
		if (selected)
		{
			selectedCustomItems.Add(text);
		}
		else
		{
			selectedCustomItems.Remove(text);
		}
		ItemDetectionRule[] array = ConfigManager._itemsConfig?.itemDetectionRules ?? Array.Empty<ItemDetectionRule>();
		foreach (ItemDetectionRule itemDetectionRule in array)
		{
			if (itemDetectionRule is CustomItemDetectionRule customItemDetectionRule && ConfigManager.NormalizeName(customItemDetectionRule.itemType) == text)
			{
				customItemDetectionRule.selected = selected;
				break;
			}
		}
	}
}
public class ItemNameManager
{
	[Serializable]
	private class SerializableDictionary
	{
		public List<string> RawName = new List<string>();

		public List<string> DisplayName = new List<string>();

		public Dictionary<string, string> ObjToNice
		{
			get
			{
				Dictionary<string, string> dictionary = new Dictionary<string, string>();
				for (int i = 0; i < Math.Min(RawName.Count, DisplayName.Count); i++)
				{
					dictionary[RawName[i]] = DisplayName[i];
				}
				return dictionary;
			}
		}

		public SerializableDictionary(Dictionary<string, string> objToNice)
		{
			foreach (KeyValuePair<string, string> item in objToNice)
			{
				RawName.Add(item.Key);
				DisplayName.Add(item.Value);
			}
		}

		public SerializableDictionary()
		{
		}
	}

	private static ItemNameManager _instance;

	private Dictionary<string, string> objToNice = new Dictionary<string, string>();

	private string cachePath = Path.Combine(Paths.ConfigPath, "ItemFinder", "ItemNameCache.json");

	public static ItemNameManager Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ItemNameManager();
			}
			return _instance;
		}
	}

	private ItemNameManager()
	{
		EnsureCacheDirectoryExists();
		PopulateFromDatabase();
	}

	private void EnsureCacheDirectoryExists()
	{
		string directoryName = Path.GetDirectoryName(cachePath);
		if (!Directory.Exists(directoryName))
		{
			Directory.CreateDirectory(directoryName);
		}
	}

	public string GetNiceName(string objName)
	{
		if (objToNice.TryGetValue(objName, out var value))
		{
			return value;
		}
		return objName;
	}

	public void SetName(string objName, string niceName)
	{
		objToNice[objName] = niceName;
	}

	public void SaveToDisk()
	{
		try
		{
			SerializableDictionary serializableDictionary = new SerializableDictionary(objToNice);
			string contents = JsonUtility.ToJson((object)serializableDictionary, true);
			File.WriteAllText(cachePath, contents);
			Debug.Log((object)("[ItemNameManager] Cache saved to '" + cachePath + "'"));
		}
		catch
		{
			Debug.LogWarning((object)"[ItemNameManager] Failed to save cache.");
		}
	}

	public void PopulateFromDatabase()
	{
		if ((Object)(object)SingletonAsset<ItemDatabase>.Instance == (Object)null || ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects == null)
		{
			return;
		}
		objToNice.Clear();
		Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
		foreach (Item @object in ((DatabaseAsset<ItemDatabase, Item>)(object)SingletonAsset<ItemDatabase>.Instance).Objects)
		{
			if (!((Object)(object)@object == (Object)null) && @object.UIData != null)
			{
				string name = ((Object)((Component)@object).gameObject).name;
				string key = @object.UIData.itemName ?? name;
				if (!dictionary.TryGetValue(key, out var value))
				{
					value = (dictionary[key] = new List<string>());
				}
				value.Add(name);
			}
		}
		foreach (KeyValuePair<string, List<string>> item in dictionary)
		{
			string key2 = item.Key;
			List<string> value2 = item.Value;
			if (value2.Count == 1)
			{
				SetName(value2[0], key2);
				continue;
			}
			foreach (string item2 in value2)
			{
				string niceName = key2 + " (" + item2 + ")";
				SetName(item2, niceName);
			}
		}
		SaveToDisk();
		Debug.Log((object)"[ItemNameManager] Cache overwritten from ItemDatabase with duplicate resolution.");
	}
}
[BepInPlugin("ItemFinder.plugin", "ItemFinder", "1.0.0")]
public class Keyboard : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <ManualTriggerCampfireCoroutine>d__8 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Keyboard <>4__this;

		private List<ItemFinder.ItemData> <campfireItems>5__1;

		private ItemFinder.ItemData <currentBiomeCampfire>5__2;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<campfireItems>5__1 = null;
			<currentBiomeCampfire>5__2 = default(ItemFinder.ItemData);
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.finder.FindAllItemsForCurrentBiome();
				<campfireItems>5__1 = <>4__this.finder.CurrentBiomeItems.FindAll((ItemFinder.ItemData item) => item.itemType == "Campfire");
				<currentBiomeCampfire>5__2 = <campfireItems>5__1.Find((ItemFinder.ItemData c) => c.biome == BiomeDetector.CurrentBiome);
				if ((Object)(object)<currentBiomeCampfire>5__2.campfireRef != (Object)null)
				{
					logs.Log("Triggering campfire in " + <currentBiomeCampfire>5__2.biome + "...");
					<>2__current = Screenshotter.TriggerCampfireCoroutine(<>4__this.finder, <currentBiomeCampfire>5__2);
					<>1__state = 1;
					return true;
				}
				logs.Log("No campfire found for current biome: " + BiomeDetector.CurrentBiome);
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			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 <SetupUIDelayed>d__7 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Keyboard <>4__this;

		private GameObject <guiObj>5__1;

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

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

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

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

		private bool MoveNext()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (ConfigManager._itemsConfig == null || ConfigManager._settingsConfig == null)
				{
					logs.Log("[Keyboard] Config is null, loading config...");
					ConfigManager.LoadConfigs();
				}
				goto IL_0070;
			case 1:
				<>1__state = -1;
				goto IL_0070;
			case 2:
				{
					<>1__state = -1;
					logs.Log($"[Keyboard] About to initialize window. ItemsConfig null: {ConfigManager._itemsConfig == null}, SettingsConfig null: {ConfigManager._settingsConfig == null}");
					<>4__this.window.Initialize();
					logs.Log("[Keyboard] Window initialization complete");
					return false;
				}
				IL_0070:
				if ((Object)(object)SingletonAsset<ItemDatabase>.Instance == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				if ((Object)(object)<>4__this.window == (Object)null)
				{
					<>4__this.window = Object.FindObjectOfType<ItemSelectorWindow>();
					if ((Object)(object)<>4__this.window == (Object)null)
					{
						<guiObj>5__1 = new GameObject("ItemSelectorWindow");
						<>4__this.window = <guiObj>5__1.AddComponent<ItemSelectorWindow>();
						<guiObj>5__1 = null;
					}
				}
				<>4__this.window.SetupUI();
				<>2__current = null;
				<>1__state = 2;
				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();
		}
	}

	private ItemSelectorWindow window;

	private ItemFinder finder;

	private bool automationQueued = false;

	private bool arrowModeQueued = false;

	private void Awake()
	{
		logs.Log("[Keyboard] Loading config...");
		ConfigManager.LoadConfigs();
		logs.Log($"[Keyboard] Config loaded. Config is null: {ConfigManager._itemsConfig == null && ConfigManager._settingsConfig == null}");
		SceneManager.sceneLoaded += OnSceneLoaded;
		logs.Log("[Keyboard] Peak Automation Plugin loaded!");
	}

	private void EnsureFinderExists()
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		if ((Object)(object)finder == (Object)null)
		{
			finder = Object.FindObjectOfType<ItemFinder>();
			if ((Object)(object)finder == (Object)null)
			{
				logs.Log("[Keyboard] Creating new ItemFinder GameObject.");
				GameObject val = new GameObject("ItemFinder");
				finder = val.AddComponent<ItemFinder>();
			}
			else
			{
				logs.Log("[Keyboard] Found existing ItemFinder: " + ((Object)((Component)finder).gameObject).name);
			}
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		((MonoBehaviour)this).StartCoroutine(SetupUIDelayed());
		if (automationQueued)
		{
			EnsureFinderExists();
			finder?.RunFullAutomation();
			automationQueued = false;
		}
		if (arrowModeQueued)
		{
			EnsureFinderExists();
			finder?.RunArrowOnlyMode();
			arrowModeQueued = false;
		}
	}

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

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

	private void Update()
	{
		//IL_0029: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_024f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
		KeyboardSettings keyboardSettings = ConfigManager._settingsConfig?.general?.keyboard ?? new KeyboardSettings();
		if (Input.GetKeyDown(keyboardSettings.GetItemSelectorToggleKey()))
		{
			window?.Toggle();
		}
		if (Input.GetKeyDown(keyboardSettings.GetFullAutomationKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			AirportCheckInKiosk val = Object.FindObjectOfType<AirportCheckInKiosk>();
			if ((Object)(object)val != (Object)null)
			{
				try
				{
					int valueOrDefault = (ConfigManager._settingsConfig?.general?.AscentToLoad).GetValueOrDefault(-1);
					val.LoadIslandMaster(valueOrDefault);
					automationQueued = true;
				}
				catch (Exception arg)
				{
					logs.Log($"[Keyboard] Full automation key pressed - kiosk.LoadIslandMaster threw an exception: {arg}");
				}
			}
			else
			{
				logs.Log("[Keyboard] Full automation key pressed - AirportCheckInKiosk not found");
			}
		}
		if (Input.GetKeyDown(keyboardSettings.GetArrowModeKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			AirportCheckInKiosk val2 = Object.FindObjectOfType<AirportCheckInKiosk>();
			if ((Object)(object)val2 != (Object)null)
			{
				try
				{
					int valueOrDefault2 = (ConfigManager._settingsConfig?.general?.AscentToLoad).GetValueOrDefault(-1);
					val2.LoadIslandMaster(valueOrDefault2);
					arrowModeQueued = true;
				}
				catch (Exception arg2)
				{
					logs.Log($"[Keyboard] Arrow mode key pressed - kiosk.LoadIslandMaster threw an exception: {arg2}");
				}
			}
			else
			{
				logs.Log("[Keyboard] Arrow mode key pressed - AirportCheckInKiosk not found");
			}
		}
		if (Input.GetKeyDown(keyboardSettings.GetArrowsNoLoadKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			AirportCheckInKiosk val3 = Object.FindObjectOfType<AirportCheckInKiosk>();
			if ((Object)(object)val3 != (Object)null)
			{
				arrowModeQueued = true;
				logs.Log("[Keyboard] Arrow mode queued without game load - waiting for level ready");
			}
			else
			{
				logs.Log("[Keyboard] Arrow mode queue attempted - AirportCheckInKiosk not found");
			}
		}
		if (Input.GetKeyDown(keyboardSettings.GetToggleArrowsKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			EnsureFinderExists();
			finder?.EnsureArrowManager();
			finder?.ArrowManager?.ToggleArrows();
		}
		if (Input.GetKeyDown(keyboardSettings.GetToggleLabelsKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			EnsureFinderExists();
			finder?.EnsureArrowManager();
			finder?.ArrowManager?.ToggleLabels();
		}
		if (Input.GetKeyDown(keyboardSettings.GetHotReloadKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			EnsureFinderExists();
			if ((Object)(object)finder?.ArrowManager != (Object)null)
			{
				finder.ArrowManager.ClearAll();
				finder.ReloadAndSpawnItems();
				logs.Log("[Keyboard] Hot reload (F5) completed via ReloadAndSpawnItems().");
			}
		}
		if (Input.GetKeyDown(keyboardSettings.GetSpawnItemsKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			EnsureFinderExists();
			finder?.EnsureArrowManager();
			finder?.ReloadAndSpawnItems();
		}
		if (Input.GetKeyDown(keyboardSettings.GetOpenLuggageKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			EnsureFinderExists();
			if ((Object)(object)finder != (Object)null)
			{
				logs.Log("F7 pressed - Opening all luggage...");
				((MonoBehaviour)finder).StartCoroutine(finder.OpenAllLuggageCoroutine());
			}
		}
		if (Input.GetKeyDown(keyboardSettings.GetTriggerCampfireKey()) && keyboardSettings.IsShiftRequirementMet())
		{
			EnsureFinderExists();
			if ((Object)(object)finder != (Object)null)
			{
				logs.Log("Manual campfire trigger requested...");
				((MonoBehaviour)finder).StartCoroutine(ManualTriggerCampfireCoroutine());
			}
		}
	}
}
public static class logs
{
	private const float FADE_COMPLETE_THRESHOLD = 0.999f;

	private const int STABILITY_THRESHOLD = 20;

	private const int LOG_BATCH_SIZE = 50;

	private const int LOG_FLUSH_INTERVAL_MS = 1000;

	private static bool fadeOutComplete;

	private static int runStartedCount;

	private static float lastFadeValue;

	private static bool suppressCallbackOutput;

	private static readonly ConcurrentQueue<string> logQueue;

	private static CancellationTokenSource cancellationTokenSource;

	private static Task loggingTask;

	private static readonly object lockObject;

	private static bool isInitialized;

	private static string logFolder
	{
		get
		{
			string text = ConfigManager._settingsConfig?.general?.outputPath ?? "";
			if (string.IsNullOrEmpty(text))
			{
				return Path.Combine(Paths.ConfigPath, "Itemfinder");
			}
			if (Path.IsPathRooted(text))
			{
				return text;
			}
			return Path.Combine(Paths.ConfigPath, "ItemFinder", text);
		}
	}

	private static string logFilePath => Path.Combine(logFolder, "PeakAutomationLog.txt");

	public static bool LevelReady { get; private set; }

	public static bool RunStarted { get; private set; }

	static logs()
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		LevelReady = false;
		RunStarted = false;
		fadeOutComplete = false;
		runStartedCount = 0;
		lastFadeValue = 0f;
		suppressCallbackOutput = false;
		logQueue = new ConcurrentQueue<string>();
		lockObject = new object();
		isInitialized = false;
		EnsureLogDirectoryExists();
		InitializeAsyncLogging();
		Application.logMessageReceived += new LogCallback(OnLogMessageReceived);
		ResetLevelState();
	}

	private static void InitializeAsyncLogging()
	{
		lock (lockObject)
		{
			if (!isInitialized)
			{
				cancellationTokenSource = new CancellationTokenSource();
				loggingTask = Task.Run(() => ProcessLogQueueAsync(cancellationTokenSource.Token));
				isInitialized = true;
			}
		}
	}

	private static void EnsureLogDirectoryExists()
	{
		try
		{
			if (!Directory.Exists(logFolder))
			{
				Directory.CreateDirectory(logFolder);
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[logs] Failed to create log directory: " + ex.Message));
		}
	}

	public static void Log(string message)
	{
		Debug.Log((object)message);
	}

	public static void LogAsync(string message)
	{
		if (!isInitialized)
		{
			InitializeAsyncLogging();
		}
		string item = $"[{DateTime.Now:HH:mm:ss}] {message}";
		logQueue.Enqueue(item);
	}

	private static async Task ProcessLogQueueAsync(CancellationToken cancellationToken)
	{
		List<string> logBatch = new List<string>(50);
		while (!cancellationToken.IsCancellationRequested)
		{
			try
			{
				string logMessage;
				while (logQueue.TryDequeue(out logMessage) && logBatch.Count < 50)
				{
					logBatch.Add(logMessage);
				}
				if (logBatch.Count > 0)
				{
					await WriteBatchToFileAsync(logBatch);
					logBatch.Clear();
				}
				await Task.Delay(1000, cancellationToken);
			}
			catch (OperationCanceledException)
			{
				break;
			}
			catch (Exception ex2)
			{
				Debug.LogError((object)("[logs] Error in async logging: " + ex2.Message));
				await Task.Delay(5000, cancellationToken);
			}
		}
		if (logBatch.Count > 0)
		{
			try
			{
				await WriteBatchToFileAsync(logBatch);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[logs] Error flushing final logs: " + ex.Message));
			}
		}
	}

	private static async Task WriteBatchToFileAsync(List<string> messages)
	{
		EnsureLogDirectoryExists();
		try
		{
			using StreamWriter writer = new StreamWriter(logFilePath, append: true);
			foreach (string message in messages)
			{
				await writer.WriteLineAsync(message);
			}
			await writer.FlushAsync();
		}
		catch (Exception ex2)
		{
			Exception ex = ex2;
			Debug.LogError((object)("[logs] Failed to write batch to file: " + ex.Message));
		}
	}

	private static void WriteToFileImmediate(string message)
	{
		try
		{
			EnsureLogDirectoryExists();
			string text = $"[{DateTime.Now:HH:mm:ss}] {message}";
			File.AppendAllText(logFilePath, text + Environment.NewLine);
		}
		catch (Exception ex)
		{
			if (!suppressCallbackOutput)
			{
				suppressCallbackOutput = true;
				Debug.Log((object)("[logs] failed to write to file: " + ex.Message));
				suppressCallbackOutput = false;
			}
		}
	}

	public static void ClearLog()
	{
		try
		{
			EnsureLogDirectoryExists();
			if (File.Exists(logFilePath))
			{
				File.WriteAllText(logFilePath, "");
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[logs] Failed to clear log: " + ex.Message));
		}
		ResetLevelState();
		Debug.Log((object)"[logs] Cleared log and reset level state.");
	}

	public static void ResetLevelState()
	{
		LevelReady = false;
		RunStarted = false;
		fadeOutComplete = false;
		runStartedCount = 0;
		lastFadeValue = 0f;
		LogAsync("Level state reset for new detection cycle");
	}

	public static void LogLevelState()
	{
		string text = $"Level State - Ready: {LevelReady}, RunStarted: {RunStarted}, " + $"FadeOut: {fadeOutComplete}, RunCount: {runStartedCount}, LastFade: {lastFadeValue}";
		Debug.Log((object)text);
	}

	private static void OnLogMessageReceived(string logString, string stackTrace, LogType type)
	{
		if (string.IsNullOrEmpty(logString))
		{
			return;
		}
		if (logString.StartsWith("[") || logString.Contains("BiomeDetector") || logString.Contains("ItemFinder") || logString.Contains("Keyboard") || logString.Contains("Set hero title:") || logString.Contains("SETTING FADE OUT:") || logString.Contains("RUN STARTED"))
		{
			LogAsync(logString);
		}
		else if ((ConfigManager._settingsConfig?.general?.LogUnityDebug).GetValueOrDefault())
		{
			LogAsync("[Unity] " + logString);
		}
		if (logString.Contains("Set hero title: "))
		{
			string text = logString.Replace("Set hero title: ", "").Trim();
			LogAsync("[BiomeDetector] Raw hero title message: '" + text + "'");
			if (IsValidBiomeTitle(text))
			{
				LogAsync("[BiomeDetector] Detected hero title: '" + text + "'");
			}
			else
			{
				LogAsync("[BiomeDetector] Hero title '" + text + "' not recognized as biome");
			}
		}
		if (logString.Contains("SETTING FADE OUT:"))
		{
			string[] array = logString.Split(new string[1] { "SETTING FADE OUT:" }, StringSplitOptions.None);
			if (array.Length > 1 && float.TryParse(array[1].Trim(), out var result))
			{
				lastFadeValue = result;
				LogAsync($"[Fade] parsed fade value = {result}");
				if (!fadeOutComplete && result >= 0.999f)
				{
					fadeOutComplete = true;
					LogAsync("[Fade] fadeOutComplete = true (fade reached ~1)");
					CheckLevelReady();
				}
			}
		}
		if (logString.Contains("RUN STARTED"))
		{
			runStartedCount++;
			LogAsync($"[Run] RUN STARTED message received (count={runStartedCount})");
			if (fadeOutComplete)
			{
				RunStarted = true;
				LogAsync("[Run] RunStarted = true (RUN STARTED happened after fade complete)");
				CheckLevelReady();
			}
			else
			{
				LogAsync("[Run] RUN STARTED seen before fade complete; waiting for fade completion to mark in-level run");
			}
		}
	}

	private static void CheckLevelReady()
	{
		if (fadeOutComplete && RunStarted && !LevelReady)
		{
			LevelReady = true;
			WriteToFileImmediate("=== LEVEL READY: Both fade-out complete AND RUN STARTED (in-level) detected ===");
		}
	}

	private static bool IsValidBiomeTitle(string s)
	{
		string[] array = new string[7] { "SHORE", "TROPICS", "MESA", "ALPINE", "CALDERA", "KILN", "THE KILN" };
		string[] array2 = array;
		foreach (string text in array2)
		{
			if (text == s)
			{
				return true;
			}
		}
		return false;
	}

	public static async Task FlushAsync()
	{
		if (isInitialized)
		{
			int maxWaitMs = 5000;
			int waitedMs = 0;
			while (!logQueue.IsEmpty && waitedMs < maxWaitMs)
			{
				await Task.Delay(100);
				waitedMs += 100;
			}
		}
	}

	public static void Shutdown()
	{
		if (!isInitialized)
		{
			return;
		}
		try
		{
			cancellationTokenSource?.Cancel();
			if (loggingTask != null && !loggingTask.IsCompleted)
			{
				loggingTask.Wait(TimeSpan.FromSeconds(5.0));
			}
			string result;
			while (logQueue.TryDequeue(out result))
			{
				try
				{
					File.AppendAllText(logFilePath, result + Environment.NewLine);
				}
				catch
				{
					break;
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("[logs] Error during shutdown: " + ex.Message));
		}
		finally
		{
			cancellationTokenSource?.Dispose();
			isInitialized = false;
		}
	}
}
public static class Screenshotter
{
	[CompilerGenerated]
	private sealed class <>c__DisplayClass1_0
	{
		public KeyCode triggerKey;

		internal bool <ScreenshotItemCoroutine>b__0()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Input.GetKeyDown(triggerKey);
		}

		internal bool <ScreenshotItemCoroutine>b__1()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Input.GetKeyDown(triggerKey);
		}
	}

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

		private object <>2__current;

		public ItemFinder finder;

		public Dictionary<string, int> counters;

		private List<ItemFinder.ItemData> <items>5__1;

		private SettingsConfig <config>5__2;

		private ScreenshotSettings <screenshotSettings>5__3;

		private GeneralSettings <general>5__4;

		private int <i>5__5;

		private <>c__DisplayClass1_0 <>8__6;

		private ItemFinder.ItemData <item>5__7;

		private Character <local>5__8;

		private Vector3 <teleportPos>5__9;

		private int <count>5__10;

		private string <filename>5__11;

		private string <fullPath>5__12;

		private RaycastHit <hit>5__13;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<items>5__1 = null;
			<config>5__2 = null;
			<screenshotSettings>5__3 = null;
			<general>5__4 = null;
			<>8__6 = null;
			<item>5__7 = default(ItemFinder.ItemData);
			<local>5__8 = null;
			<filename>5__11 = null;
			<fullPath>5__12 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<items>5__1 = finder.CurrentBiomeItems;
				<config>5__2 = ConfigManager._settingsConfig;
				if (<config>5__2 == null)
				{
					logs.Log("Config is null, cannot proceed with screenshot automation!");
					return false;
				}
				<screenshotSettings>5__3 = <config>5__2.automation.screenshot;
				<general>5__4 = <config>5__2.general;
				<i>5__5 = 0;
				break;
			case 1:
				<>1__state