Decompiled source of PeakFinder v3.2.1

PEAK Finder.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using Peak;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public class BeaconRenderer : MonoBehaviour
{
	public List<Vector3> targets = new List<Vector3>();

	public Color color = new Color(0f, 1f, 0f, 1f);

	public float height = 150f;

	private Material _mat;

	private void OnDestroy()
	{
		if ((Object)(object)_mat != (Object)null)
		{
			Object.Destroy((Object)(object)_mat);
			_mat = null;
		}
	}

	private void EnsureMat()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		if (!((Object)(object)_mat != (Object)null))
		{
			Shader val = Shader.Find("Hidden/Internal-Colored");
			if (!((Object)(object)val == (Object)null))
			{
				_mat = new Material(val);
				((Object)_mat).hideFlags = (HideFlags)61;
				_mat.SetInt("_ZWrite", 0);
				_mat.SetInt("_SrcBlend", 5);
				_mat.SetInt("_DstBlend", 10);
				_mat.renderQueue = 5000;
			}
		}
	}

	private void OnRenderObject()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		if (targets == null || targets.Count == 0)
		{
			return;
		}
		EnsureMat();
		if ((Object)(object)_mat == (Object)null)
		{
			return;
		}
		_mat.SetPass(0);
		GL.PushMatrix();
		GL.Begin(1);
		GL.Color(color);
		float num = height;
		foreach (Vector3 target in targets)
		{
			Vector3 val = target + new Vector3(0f, num, 0f);
			GL.Vertex(target);
			GL.Vertex(val);
			GL.Vertex(val + new Vector3(-3f, 0f, 0f));
			GL.Vertex(val + new Vector3(3f, 0f, 0f));
			GL.Vertex(val + new Vector3(0f, 0f, -3f));
			GL.Vertex(val + new Vector3(0f, 0f, 3f));
		}
		GL.End();
		GL.PopMatrix();
	}
}
[BepInPlugin("com.mandrake.bugfinder", "PEAK Finder", "3.2.1")]
public class Plugin : BaseUnityPlugin
{
	private class Category
	{
		public int Index;

		public string ConfigName;

		public string DisplayName;

		public string WorldLabel;

		public ConfigEntry<bool> Show;

		public ConfigEntry<KeyboardShortcut> ToggleKeyEntry;

		public BeaconRenderer Live;

		public readonly List<Vector3> LivePos = new List<Vector3>();

		public readonly List<string> LiveNames = new List<string>();

		public List<string> Keywords;

		public Type MarkerType;

		public bool ItemScan;
	}

	private class LuggageHit
	{
		public Vector3 Pos;

		public int SegIdx = -1;

		public string SegLabel = "";

		public bool Open;
	}

	private class TodaySeg
	{
		public int Index = -1;

		public string Canon = "";

		public int Biome = -1;

		public string VariantEn = "";

		public string VariantCn = "";

		public bool Done;
	}

	private List<string> _capyExcludeKeys = new List<string>();

	private Type _mirageType;

	private FieldInfo _mirageHideField;

	private MapHandler _capyLogMap;

	private int _mirageLogged = -1;

	private readonly List<Transform> _mirageHidden = new List<Transform>();

	private readonly List<Transform> _mirageComps = new List<Transform>();

	private ConfigEntry<float> _scanInterval;

	private ConfigEntry<bool> _autoScan;

	private ConfigEntry<KeyboardShortcut> _toggleKey;

	private ConfigEntry<KeyboardShortcut> _rescanKey;

	private ConfigEntry<KeyboardShortcut> _panelKey;

	private ConfigEntry<float> _beaconHeight;

	private ConfigEntry<bool> _swampOnly;

	private ConfigEntry<bool> _gloomOnly;

	private ConfigEntry<bool> _includeJesterBells;

	private ConfigEntry<float> _clusterRadius;

	private bool _showPanel;

	private float _nextScanTime;

	private string _status = "";

	private string _mapName = "";

	private readonly List<Category> _categories = new List<Category>();

	private Category _mandrake;

	private Category _bug;

	private Category _beehive;

	private Category _capybara;

	private Category _belltower;

	private Category _luggage;

	private MapHandler _cachedMap;

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

	private readonly List<Transform> _tmpTransforms = new List<Transform>();

	private readonly List<Transform> _excludeChars = new List<Transform>();

	private GameObject _root;

	private MapHandler _bellScanMap;

	private bool _bellCacheValid;

	private bool _bellNoGloomLogged;

	private readonly List<Vector3> _bellCachePos = new List<Vector3>();

	private readonly List<string> _bellCacheNames = new List<string>();

	private ConfigEntry<bool> _luggageExport;

	private readonly List<LuggageHit> _clownHits = new List<LuggageHit>();

	private string _luggageSummary = "";

	private int _luggageOpenedCount;

	private string _luggageSig = "";

	private string _luggageLogSig = "";

	private string _mapSortingCn = "";

	private string _mapSortingEn = "";

	private int _mapSegCount;

	private MountainProgressHandler _mph;

	private MapHandler _mphMap;

	private readonly List<string> _climbNames = new List<string>();

	private bool _climbLoaded;

	private bool _climbOrderAligned;

	private bool _climbAlignWarned;

	private readonly List<TodaySeg> _today = new List<TodaySeg>();

	private bool _todayAligned;

	private string _todayMapSig = "";

	private string _todayDetailCn = "";

	private string _todayExportSig = "";

	private ConfigEntry<bool> _todayExport;

	private bool _manualRescan;

	private static readonly HashSet<string> MesaKnownVariants = new HashSet<string> { "ScorpionsHell", "CactusHell", "CactusForest", "DynamiteHell", "TornadoHell", "TumblerHell" };

	private static readonly HashSet<string> RootsKnownVariants = new HashSet<string> { "CaveMania", "DeepWater", "BombBeetle", "DeepWoods", "Clearcut" };

	private static readonly HashSet<string> RootsStructuralNames = new HashSet<string> { "Redwoods", "Redwood", "Variant" };

	private static readonly Dictionary<int, Dictionary<string, string>> VariantCnMap = new Dictionary<int, Dictionary<string, string>>
	{
		[0] = new Dictionary<string, string>
		{
			["Default"] = "默认",
			["SnakeBeach"] = "蛇岩",
			["RedBeach"] = "赤沙",
			["BlueBeach"] = "蓝沙",
			["JellyHell"] = "水母地狱",
			["BlackSand"] = "黑沙"
		},
		[1] = new Dictionary<string, string>
		{
			["Default"] = "默认",
			["Lava"] = "熔岩管",
			["Pillars"] = "巨柱",
			["Thorny"] = "巨棘藤",
			["Bombs"] = "爆菇",
			["Ivy"] = "紫毒藤",
			["SkyJungle"] = "浮岛"
		},
		[2] = new Dictionary<string, string>
		{
			["Default"] = "默认",
			["Lava"] = "熔岩管",
			["Spiky"] = "冰刺",
			["GeyserHell"] = "间歇泉地狱"
		},
		[6] = new Dictionary<string, string>
		{
			["Default"] = "默认",
			["ScorpionsHell"] = "毒蝎地狱",
			["CactusHell"] = "峭壁仙人掌地狱",
			["CactusForest"] = "高原仙人掌林",
			["DynamiteHell"] = "炸药地狱",
			["TornadoHell"] = "龙卷风地狱",
			["TumblerHell"] = "风滚草地狱"
		},
		[7] = new Dictionary<string, string>
		{
			["Default"] = "默认",
			["CaveMania"] = "洞窟丛生",
			["DeepWater"] = "赤水孢泽",
			["BombBeetle"] = "爆菇甲虫",
			["DeepWoods"] = "幽深密林",
			["Clearcut"] = "皆伐菌原"
		}
	};

	internal string _mapSortingDetailCn => _todayDetailCn;

	internal void BindCapybaraConfig()
	{
		_capyExcludeKeys = SplitList(((BaseUnityPlugin)this).Config.Bind<string>("Scan", "CapybaraExcludeFilter", "mirage", "卡皮巴拉地标排除关键词(方山的假绿洲带 Mirage),逗号分隔").Value);
		try
		{
			_mirageType = Type.GetType("Mirage, Assembly-CSharp");
		}
		catch
		{
			_mirageType = null;
		}
		try
		{
			_mirageHideField = ((_mirageType != null) ? _mirageType.GetField("objectsToHide") : null);
		}
		catch
		{
			_mirageHideField = null;
		}
	}

	private void ScanCapybara(Category cat, MapHandler map)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected I4, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0435: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>();
		List<string> list2 = new List<string>();
		List<Transform> list3 = new List<Transform>();
		List<Tuple<Transform, Vector3, string>> list4 = new List<Tuple<Transform, Vector3, string>>();
		List<GameObject> list5 = new List<GameObject>();
		if (map.segments != null)
		{
			MapSegment[] segments = map.segments;
			foreach (MapSegment val in segments)
			{
				if (val != null && !((Object)(object)val.segmentParent == (Object)null))
				{
					bool flag = false;
					try
					{
						int num = (int)val.biome;
						flag = num == 2 || num == 6;
					}
					catch
					{
					}
					if (flag)
					{
						list5.Add(val.segmentParent);
					}
				}
			}
		}
		CollectMirageData();
		int num2 = 0;
		try
		{
			Object[] array = Resources.FindObjectsOfTypeAll(typeof(Capybara));
			if (array != null)
			{
				Object[] array2 = array;
				foreach (Object obj2 in array2)
				{
					Component val2 = (Component)(object)((obj2 is Component) ? obj2 : null);
					if ((Object)(object)val2 == (Object)null || (Object)(object)val2.gameObject == (Object)null)
					{
						continue;
					}
					Scene scene = val2.gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						if (!val2.gameObject.activeInHierarchy)
						{
							num2++;
						}
						else if (!IsExcluded(val2.transform) && !IsMirageFake(val2.transform))
						{
							list.Add(val2.transform.position);
							list2.Add("Capybara (" + ((Object)val2.gameObject).name + ")");
							list3.Add(val2.transform);
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] 卡皮巴拉组件扫描失败: " + ex.Message));
		}
		List<string> list6 = new List<string>();
		foreach (GameObject item in list5)
		{
			if ((Object)(object)item == (Object)null)
			{
				continue;
			}
			_tmpTransforms.Clear();
			item.GetComponentsInChildren<Transform>(true, _tmpTransforms);
			foreach (Transform tmpTransform in _tmpTransforms)
			{
				if ((Object)(object)tmpTransform == (Object)null || (Object)(object)((Component)tmpTransform).gameObject == (Object)null || ((Object)(object)_root != (Object)null && (Object)(object)tmpTransform.root == (Object)(object)_root.transform))
				{
					continue;
				}
				string text = ((Object)tmpTransform).name.ToLowerInvariant();
				if (!MatchKeys(text, cat.Keywords))
				{
					continue;
				}
				string text2 = null;
				if (text.Contains("capybara"))
				{
					text2 = "capybara锚点";
				}
				else if (text.Contains("spawner") || text.Contains("spawn"))
				{
					text2 = "生成锚点";
				}
				else if (text.Contains("autolod") || text.Contains("_lod"))
				{
					text2 = "LOD代理";
				}
				else if (!((Component)tmpTransform).gameObject.activeInHierarchy)
				{
					text2 = "禁用";
				}
				if (text2 == null && IsMirageFake(tmpTransform))
				{
					text2 = "Mirage幻影";
				}
				if (text2 != null)
				{
					if (list6.Count < 12)
					{
						list6.Add(((Object)tmpTransform).name + "(" + text2 + ")");
					}
				}
				else
				{
					list4.Add(Tuple.Create<Transform, Vector3, string>(tmpTransform, tmpTransform.position, "地标 (" + ((Object)tmpTransform).name + ")"));
				}
			}
		}
		int num3 = 0;
		if (list4.Count > 0)
		{
			HashSet<GameObject> hashSet = new HashSet<GameObject>();
			if (list3.Count > 0)
			{
				foreach (Transform item2 in list3)
				{
					GameObject val3 = FindSegmentRoot(item2, list5);
					if ((Object)(object)val3 != (Object)null)
					{
						hashSet.Add(val3);
					}
				}
			}
			foreach (Tuple<Transform, Vector3, string> item3 in list4)
			{
				GameObject val4 = FindSegmentRoot(item3.Item1, list5);
				if ((Object)(object)val4 != (Object)null && hashSet.Contains(val4))
				{
					num3++;
					continue;
				}
				list.Add(item3.Item2);
				list2.Add(item3.Item3);
			}
		}
		Cluster(list, list2, cat.LivePos, cat.LiveNames, _clusterRadius.Value);
		if ((Object)(object)_capyLogMap != (Object)(object)map)
		{
			_capyLogMap = map;
			_mirageLogged = -1;
		}
		if (_mirageLogged != _mirageComps.Count)
		{
			_mirageLogged = _mirageComps.Count;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] 卡皮巴拉:Alpine/Mesa 段根 " + list5.Count + " 个,Mirage " + _mirageComps.Count + " 个(引用假道具 " + _mirageHidden.Count + " 个),跳过禁用组件实例 " + num2 + ((num3 > 0) ? (";地标压制 " + num3 + " 个(段内有真卡皮巴拉)") : "") + ((list6.Count > 0) ? (";地标排除: " + string.Join(", ", list6.ToArray())) : ";无地标排除")));
		}
	}

	private void CollectMirageData()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		_mirageHidden.Clear();
		_mirageComps.Clear();
		if (_mirageType == null)
		{
			return;
		}
		try
		{
			Object[] array = Resources.FindObjectsOfTypeAll(_mirageType);
			foreach (Object obj in array)
			{
				Component val = (Component)(object)((obj is Component) ? obj : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val.gameObject == (Object)null)
				{
					continue;
				}
				Scene scene = val.gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					continue;
				}
				_mirageComps.Add(val.transform);
				if (_mirageHideField == null || !(_mirageHideField.GetValue(val) is GameObject[] array2))
				{
					continue;
				}
				GameObject[] array3 = array2;
				foreach (GameObject val2 in array3)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						_mirageHidden.Add(val2.transform);
					}
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] Mirage 收集失败: " + ex.Message));
		}
	}

	private bool IsMirageFake(Transform t)
	{
		Transform val = t;
		int num = 0;
		while ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && num < 20)
		{
			if (MatchKeys(((Object)val).name.ToLowerInvariant(), _capyExcludeKeys))
			{
				return true;
			}
			if (_mirageType != null && HasComp(((Component)val).gameObject, _mirageType))
			{
				return true;
			}
			val = val.parent;
			num++;
		}
		if (_mirageType == null)
		{
			return false;
		}
		if ((Object)(object)t != (Object)null && (Object)(object)((Component)t).gameObject != (Object)null && HasCompInChildren(((Component)t).gameObject, _mirageType))
		{
			return true;
		}
		foreach (Transform item in _mirageHidden)
		{
			if (!((Object)(object)item == (Object)null) && ((Object)(object)t == (Object)(object)item || IsDescendant(t, item) || IsDescendant(item, t)))
			{
				return true;
			}
		}
		return false;
	}

	private static bool HasComp(GameObject go, Type type)
	{
		try
		{
			return (Object)(object)go.GetComponent(type) != (Object)null;
		}
		catch
		{
			return false;
		}
	}

	private static GameObject FindSegmentRoot(Transform t, List<GameObject> roots)
	{
		if ((Object)(object)t == (Object)null || roots == null)
		{
			return null;
		}
		Transform val = t;
		while ((Object)(object)val != (Object)null)
		{
			foreach (GameObject root in roots)
			{
				if ((Object)(object)root != (Object)null && (Object)(object)val == (Object)(object)root.transform)
				{
					return root;
				}
			}
			val = val.parent;
		}
		return null;
	}

	private static bool HasCompInChildren(GameObject go, Type type)
	{
		try
		{
			Component[] componentsInChildren = go.GetComponentsInChildren(type, true);
			return componentsInChildren != null && componentsInChildren.Length != 0;
		}
		catch
		{
			return false;
		}
	}

	private void Awake()
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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)
		//IL_01ab: Expected O, but got Unknown
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Unknown result type (might be due to invalid IL or missing references)
		_scanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ScanInterval", 5f, "扫描间隔(秒)");
		_autoScan = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoScan", true, "是否自动定时扫描(关掉后只用手动重扫)");
		_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "开关全部光柱");
		_rescanKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "RescanKey", new KeyboardShortcut((KeyCode)282, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "立即重新扫描");
		_panelKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "PanelKey", new KeyboardShortcut((KeyCode)282, Array.Empty<KeyCode>()), "开关左上角信息面板(关闭后停止自动扫描,再次打开立即扫描)");
		_beaconHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "BeaconHeight", 150f, "实刷光柱高度");
		_swampOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Scan", "SwampOnly", false, "道具类层级兜底只扫描雾沼(Swamp)段(生物群系 8)");
		_gloomOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Scan", "GloomOnly", true, "钟塔只扫描雾沼(Gloom/Swamp)段(找不到雾沼段时回退全图)");
		_includeJesterBells = ((BaseUnityPlugin)this).Config.Bind<bool>("Scan", "IncludeJesterBells", true, "把雾沼段里的 JesterBells 也算作钟");
		_clusterRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Scan", "ClusterRadius", 50f, "同一目标的归类半径");
		BindLuggageConfig();
		BindCapybaraConfig();
		BindTodayConfig();
		_root = new GameObject("PEAKFinderBeacons");
		Object.DontDestroyOnLoad((Object)(object)_root);
		_mandrake = AddCategory(1, "Mandrake", "曼德拉草", "曼德拉", showDefault: true, "#00FF00FF", new Color(0f, 1f, 0f), "MandrakeNameFilter", "mandrake", typeof(Mandrake), itemScan: true);
		_bug = AddCategory(2, "Bug", "雾沼虫", "雾沼虫", showDefault: true, "#00A0FFFF", new Color(0f, 0.63f, 1f), "BugNameFilter", "earlyworm,worm", typeof(EarlyWorm), itemScan: true);
		_beehive = AddCategory(3, "Beehive", "蜂巢·蜂蜜", "蜂巢", showDefault: true, "#B026FFFF", new Color(0.69f, 0.15f, 1f), "BeehiveNameFilter", "beehive,honey,honeycomb", typeof(Beehive), itemScan: true);
		_capybara = AddCategory(4, "Capybara", "卡皮巴拉", "卡皮巴拉", showDefault: true, "#FF8C00FF", new Color(1f, 0.55f, 0f), "CapybaraNameFilter", "oasis,hotspring,spring", typeof(Capybara), itemScan: false);
		_belltower = AddCategory(5, "Belltower", "钟塔", "钟塔", showDefault: true, "#FFCC00FF", new Color(1f, 0.8f, 0f), "BelltowerNameFilter", "bell,tower,belfry", null, itemScan: false);
		_luggage = AddCategory(6, "Luggage", "小丑行李", "小丑行李", showDefault: true, "#FF0033FF", new Color(1f, 0f, 0.2f), "LuggageNameFilter", "clown", null, itemScan: false);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] v3.2.1 loaded. " + KeyText(_toggleKey) + "=全开/关, " + KeyText(_rescanKey) + "=重扫, " + KeyText(_panelKey) + "=面板, 面板开启时数字 5-0 切分类(5曼德拉 6雾沼虫 7蜂巢 8卡皮巴拉 9钟塔 0小丑行李)"));
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if ((int)mode != 0)
		{
			return;
		}
		foreach (Category category in _categories)
		{
			category.LivePos.Clear();
			category.LiveNames.Clear();
		}
		ClearRenderers();
	}

	private Category AddCategory(int index, string configName, string display, string worldLabel, bool showDefault, string colorHexDefault, Color fallbackColor, string filterKey, string filterDefault, Type markerType, bool itemScan)
	{
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		Category category = new Category
		{
			Index = index,
			ConfigName = configName,
			DisplayName = display,
			WorldLabel = worldLabel,
			MarkerType = markerType,
			ItemScan = itemScan
		};
		category.Show = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "Show" + configName + "Beacons", showDefault, "是否显示" + display + "光柱");
		ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", configName + "ColorHex", colorHexDefault, display + "光柱颜色(HEX RRGGBBAA)");
		category.Keywords = SplitList(((BaseUnityPlugin)this).Config.Bind<string>("Scan", filterKey, filterDefault, "按名字匹配" + display + "的关键词,逗号分隔").Value);
		category.ToggleKeyEntry = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "CategoryKey" + index, new KeyboardShortcut(DefaultCategoryKey(index), Array.Empty<KeyCode>()), "面板开启时:切换" + display + "显示");
		category.Live = _root.AddComponent<BeaconRenderer>();
		category.Live.color = ParseHexColor(val.Value, fallbackColor);
		category.Live.height = Mathf.Max(10f, _beaconHeight.Value);
		((Behaviour)category.Live).enabled = category.Show.Value;
		_categories.Add(category);
		return category;
	}

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			KeyboardShortcut value = _toggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				ToggleAllCategories();
			}
			value = _rescanKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_manualRescan = true;
				ScanNow();
			}
			value = _panelKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				_showPanel = !_showPanel;
				if (_showPanel)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[PEAKFinder] 面板开启,开始扫描");
					ScanNow();
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"[PEAKFinder] 面板关闭,停止自动扫描");
				}
			}
			if (_showPanel)
			{
				foreach (Category category in _categories)
				{
					value = category.ToggleKeyEntry.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						SetCategoryShow(category, !category.Show.Value);
					}
				}
			}
			if (_showPanel && _autoScan.Value && Time.time >= _nextScanTime)
			{
				_nextScanTime = Time.time + Mathf.Max(0.5f, _scanInterval.Value);
				ScanNow();
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[PEAKFinder] Update error: " + ex));
		}
	}

	private void SetCategoryShow(Category cat, bool on)
	{
		cat.Show.Value = on;
		if ((Object)(object)cat.Live != (Object)null)
		{
			((Behaviour)cat.Live).enabled = on;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] " + cat.DisplayName + ":" + (on ? "开" : "关")));
	}

	private void ToggleAllCategories()
	{
		bool flag = _categories.Any((Category c) => c.Show.Value);
		foreach (Category category in _categories)
		{
			SetCategoryShow(category, !flag);
		}
	}

	private void ScanNow()
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			MapHandler val = Object.FindObjectOfType<MapHandler>();
			if ((Object)(object)val == (Object)null || !MapHandler.Exists || !MapHandler.ExistsAndInitialized)
			{
				_status = "未进入地图(请先进入每日远征)";
				_mapName = "";
				ResetLuggageSession();
				RefreshTodayDetail(null, forceExport: false);
				_manualRescan = false;
				foreach (Category category in _categories)
				{
					category.LivePos.Clear();
					category.LiveNames.Clear();
				}
				ClearRenderers();
				return;
			}
			Scene scene = ((Component)val).gameObject.scene;
			_mapName = ((Scene)(ref scene)).name;
			RefreshMapSorting(val);
			EnsureRoots(val);
			BuildExcludeChars();
			RefreshTodayDetail(val, _manualRescan);
			_manualRescan = false;
			foreach (Category category2 in _categories)
			{
				category2.LivePos.Clear();
				category2.LiveNames.Clear();
				if (category2 == _luggage)
				{
					ScanLuggage(category2, val);
				}
				else if (category2.Show.Value)
				{
					if (category2 == _belltower)
					{
						ScanBelltower(category2, val);
					}
					else if (category2 == _capybara)
					{
						ScanCapybara(category2, val);
					}
					else
					{
						ScanItemCategory(category2);
					}
				}
			}
			AssignRenderers();
			UpdateStatus();
			LogMatches();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[PEAKFinder] Scan error: " + ex));
		}
	}

	private void EnsureRoots(MapHandler map)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Invalid comparison between Unknown and I4
		if ((Object)(object)_cachedMap == (Object)(object)map && _roots.Count > 0)
		{
			return;
		}
		_cachedMap = map;
		_roots.Clear();
		if (map.segments == null)
		{
			return;
		}
		MapSegment[] segments = map.segments;
		foreach (MapSegment val in segments)
		{
			if (val != null && (!_swampOnly.Value || (int)val.biome == 8) && (Object)(object)val.segmentParent != (Object)null && !_roots.Contains(val.segmentParent))
			{
				_roots.Add(val.segmentParent);
			}
		}
	}

	private void BuildExcludeChars()
	{
		_excludeChars.Clear();
		Character[] array = Resources.FindObjectsOfTypeAll<Character>();
		if (array == null)
		{
			return;
		}
		Character[] array2 = array;
		foreach (Character val in array2)
		{
			if ((Object)(object)val != (Object)null)
			{
				_excludeChars.Add(((Component)val).transform);
			}
		}
	}

	private void ScanItemCategory(Category cat)
	{
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>();
		List<string> list2 = new List<string>();
		if (cat.MarkerType != null)
		{
			AddComponentTargets(cat, list, list2);
		}
		if (cat.ItemScan)
		{
			AddItemTargets(cat, list, list2);
		}
		foreach (GameObject root in _roots)
		{
			if ((Object)(object)root == (Object)null)
			{
				continue;
			}
			_tmpTransforms.Clear();
			root.GetComponentsInChildren<Transform>(true, _tmpTransforms);
			foreach (Transform tmpTransform in _tmpTransforms)
			{
				if (!((Object)(object)tmpTransform == (Object)null) && (!((Object)(object)_root != (Object)null) || !((Object)(object)tmpTransform.root == (Object)(object)_root.transform)))
				{
					string text = ((Object)tmpTransform).name.ToLowerInvariant();
					if (MatchKeys(text, cat.Keywords) && !text.Contains("spawner") && !text.Contains("spawn"))
					{
						list.Add(tmpTransform.position);
						list2.Add(((Object)tmpTransform).name);
					}
				}
			}
		}
		Cluster(list, list2, cat.LivePos, cat.LiveNames, _clusterRadius.Value);
	}

	private void ScanBelltower(Category cat, MapHandler map)
	{
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: 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_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0394: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_bellScanMap != (Object)(object)map)
		{
			_bellScanMap = map;
			_bellCacheValid = false;
			_bellNoGloomLogged = false;
			_bellCachePos.Clear();
			_bellCacheNames.Clear();
		}
		GameObject val = FindGloomSegmentRoot(map);
		if ((Object)(object)val == (Object)null && _gloomOnly.Value)
		{
			if (!_bellNoGloomLogged)
			{
				_bellNoGloomLogged = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[PEAKFinder] 钟塔:本图无雾沼段,跳过扫描(数量应为 0)");
			}
			cat.LivePos.Clear();
			cat.LiveNames.Clear();
			return;
		}
		Scene scene;
		if (_bellCacheValid)
		{
			cat.LivePos.Clear();
			cat.LiveNames.Clear();
			cat.LivePos.AddRange(_bellCachePos);
			cat.LiveNames.AddRange(_bellCacheNames);
		}
		else
		{
			List<Vector3> list = new List<Vector3>();
			List<string> list2 = new List<string>();
			if ((Object)(object)val != (Object)null && _gloomOnly.Value)
			{
				_tmpTransforms.Clear();
				val.GetComponentsInChildren<Transform>(true, _tmpTransforms);
				foreach (Transform tmpTransform in _tmpTransforms)
				{
					if (!((Object)(object)tmpTransform == (Object)null) && MatchKeys(((Object)tmpTransform).name.ToLowerInvariant(), cat.Keywords))
					{
						list.Add(tmpTransform.position);
						list2.Add(((Object)tmpTransform).name);
					}
				}
			}
			else if (!_gloomOnly.Value)
			{
				Transform[] array = Object.FindObjectsOfType<Transform>();
				foreach (Transform val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						scene = ((Component)val2).gameObject.scene;
						if (((Scene)(ref scene)).IsValid() && (!((Object)(object)_root != (Object)null) || !((Object)(object)val2.root == (Object)(object)_root.transform)) && MatchKeys(((Object)val2).name.ToLowerInvariant(), cat.Keywords))
						{
							list.Add(val2.position);
							list2.Add(((Object)val2).name);
						}
					}
				}
			}
			Cluster(list, list2, cat.LivePos, cat.LiveNames, _clusterRadius.Value);
			if (cat.LivePos.Count > 0)
			{
				_bellCachePos.Clear();
				_bellCachePos.AddRange(cat.LivePos);
				_bellCacheNames.Clear();
				_bellCacheNames.AddRange(cat.LiveNames);
				_bellCacheValid = true;
			}
		}
		if (!_includeJesterBells.Value)
		{
			return;
		}
		JesterBells[] array2 = Resources.FindObjectsOfTypeAll<JesterBells>();
		foreach (JesterBells val3 in array2)
		{
			if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null)
			{
				continue;
			}
			GameObject gameObject = ((Component)val3).gameObject;
			scene = gameObject.scene;
			if (!((Scene)(ref scene)).IsValid() || !gameObject.activeInHierarchy || ((Object)(object)val != (Object)null && !IsDescendant(gameObject.transform, val.transform)))
			{
				continue;
			}
			bool flag = false;
			foreach (Vector3 livePo in cat.LivePos)
			{
				if (Vector3.Distance(livePo, gameObject.transform.position) <= _clusterRadius.Value)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				cat.LivePos.Add(gameObject.transform.position);
				cat.LiveNames.Add("JesterBells");
			}
		}
	}

	private GameObject FindGloomSegmentRoot(MapHandler map)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		if (map.segments == null)
		{
			return null;
		}
		MapSegment[] segments = map.segments;
		foreach (MapSegment val in segments)
		{
			if (val != null && (int)val.biome == 8)
			{
				return val.segmentParent;
			}
		}
		return null;
	}

	private void AssignRenderers()
	{
		foreach (Category category in _categories)
		{
			if ((Object)(object)category.Live != (Object)null)
			{
				category.Live.targets.Clear();
				if (category.Show.Value)
				{
					category.Live.targets.AddRange(category.LivePos);
				}
				((Behaviour)category.Live).enabled = category.Show.Value;
			}
		}
	}

	private void ClearRenderers()
	{
		foreach (Category category in _categories)
		{
			if ((Object)(object)category.Live != (Object)null)
			{
				category.Live.targets.Clear();
			}
		}
	}

	private void UpdateStatus()
	{
		bool flag = _categories.Any((Category c) => c.LivePos.Count > 0);
		_status = (flag ? "已扫描" : "没扫到目标:看日志或调 NameFilter 关键词");
	}

	private void LogMatches()
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		foreach (Category category in _categories)
		{
			if (category != _luggage)
			{
				for (int i = 0; i < category.LivePos.Count; i++)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] " + category.DisplayName + " #" + (i + 1) + " '" + category.LiveNames[i] + "' " + FmtVec(category.LivePos[i])));
				}
			}
		}
	}

	private void OnGUI()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		if (!_showPanel)
		{
			return;
		}
		try
		{
			GUILayout.BeginArea(new Rect(10f, 10f, 440f, 280f));
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			GUILayout.Label("<b>PEAK Finder</b>", Array.Empty<GUILayoutOption>());
			GUILayout.Label("地图: " + (string.IsNullOrEmpty(_mapName) ? "-" : _mapName) + "   " + _status, Array.Empty<GUILayoutOption>());
			string text = ((_mapSortingDetailCn.Length > 0) ? _mapSortingDetailCn : _mapSortingCn);
			if (text.Length > 0)
			{
				GUILayout.Label("今日: " + text + "(" + _mapSegCount + "段)", Array.Empty<GUILayoutOption>());
			}
			foreach (Category category in _categories)
			{
				string text2 = (category.Show.Value ? "<color=#7CFC00>开</color>" : "<color=#A0A0A0>关</color>");
				string text3 = "共 " + category.LivePos.Count;
				if (category == _luggage && category.LivePos.Count > 0)
				{
					text3 = text3 + ":" + _luggageSummary;
					if (_luggageOpenedCount > 0)
					{
						text3 = text3 + ",已开" + _luggageOpenedCount;
					}
				}
				GUILayout.Label("[" + KeyShortLabel(category.ToggleKeyEntry.Value) + "] " + category.DisplayName + "   " + text2 + "   " + text3, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(4f);
			GUILayout.Label(KeyText(_toggleKey) + " 全开/关 | " + KeyText(_rescanKey) + " 重扫 | " + KeyText(_panelKey) + " 面板", Array.Empty<GUILayoutOption>());
			GUILayout.Label("面板开启时: 数字 5-0 切分类", Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
			GUILayout.EndArea();
			Camera main = Camera.main;
			foreach (Category category2 in _categories)
			{
				if (category2.Show.Value && !((Object)(object)category2.Live == (Object)null))
				{
					for (int i = 0; i < category2.LivePos.Count; i++)
					{
						DrawWorldLabel(main, category2.LivePos[i], category2.WorldLabel, category2.Live.color);
					}
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[PEAKFinder] OnGUI error: " + ex));
		}
	}

	private static void DrawWorldLabel(Camera cam, Vector3 worldPos, string text, Color col)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)cam == (Object)null))
		{
			Vector3 val = cam.WorldToScreenPoint(worldPos);
			if (!(val.z <= 0f))
			{
				Rect val2 = new Rect(val.x - 30f, (float)Screen.height - val.y - 12f, 90f, 20f);
				GUI.color = col;
				GUI.Label(val2, text);
				GUI.color = Color.white;
			}
		}
	}

	private void AddComponentTargets(Category cat, List<Vector3> pos, List<string> names)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		Object[] array = Resources.FindObjectsOfTypeAll(cat.MarkerType);
		if (array == null)
		{
			return;
		}
		Object[] array2 = array;
		foreach (Object obj in array2)
		{
			Component val = (Component)(object)((obj is Component) ? obj : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.gameObject == (Object)null))
			{
				GameObject gameObject = val.gameObject;
				Scene scene = gameObject.scene;
				if (((Scene)(ref scene)).IsValid() && !IsExcluded(gameObject.transform))
				{
					pos.Add(gameObject.transform.position);
					names.Add(cat.ConfigName + " (" + ((Object)gameObject).name + ")");
				}
			}
		}
	}

	private void AddItemTargets(Category cat, List<Vector3> pos, List<string> names)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		Item[] array = Resources.FindObjectsOfTypeAll<Item>();
		foreach (Item val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
			{
				GameObject gameObject = ((Component)val).gameObject;
				Scene scene = gameObject.scene;
				if (((Scene)(ref scene)).IsValid() && !IsExcluded(gameObject.transform) && MatchKeys(((Object)gameObject).name.ToLowerInvariant(), cat.Keywords))
				{
					pos.Add(gameObject.transform.position);
					names.Add("Item (" + ((Object)gameObject).name + ")");
				}
			}
		}
	}

	private bool IsExcluded(Transform t)
	{
		if ((Object)(object)t == (Object)null)
		{
			return true;
		}
		if ((Object)(object)_root != (Object)null && (Object)(object)t.root == (Object)(object)_root.transform)
		{
			return true;
		}
		foreach (Transform excludeChar in _excludeChars)
		{
			if ((Object)(object)excludeChar != (Object)null && IsDescendant(t, excludeChar))
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsDescendant(Transform t, Transform root)
	{
		Transform val = t;
		while ((Object)(object)val != (Object)null)
		{
			if ((Object)(object)val == (Object)(object)root)
			{
				return true;
			}
			val = val.parent;
		}
		return false;
	}

	private static bool MatchKeys(string lowerName, List<string> keys)
	{
		foreach (string key in keys)
		{
			if (key.Length > 0 && lowerName.Contains(key))
			{
				return true;
			}
		}
		return false;
	}

	private static void Cluster(List<Vector3> srcPos, List<string> srcNames, List<Vector3> outPos, List<string> outNames, float radius)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: 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_0059: Unknown result type (might be due to invalid IL or missing references)
		outPos.Clear();
		outNames.Clear();
		if (srcPos.Count == 0)
		{
			return;
		}
		List<int> list = new List<int>(8);
		for (int i = 0; i < srcPos.Count; i++)
		{
			Vector3 val = srcPos[i];
			bool flag = false;
			for (int j = 0; j < outPos.Count; j++)
			{
				if (Vector3.Distance(outPos[j], val) <= radius)
				{
					if (val.y > outPos[j].y)
					{
						outPos[j] = val;
						list[j] = i;
					}
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				outPos.Add(val);
				list.Add(i);
			}
		}
		foreach (int item in list)
		{
			outNames.Add(srcNames[item]);
		}
	}

	private static List<string> SplitList(string s)
	{
		List<string> list = new List<string>();
		if (string.IsNullOrEmpty(s))
		{
			return list;
		}
		string[] array = s.Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim().ToLowerInvariant();
			if (text.Length > 0)
			{
				list.Add(text);
			}
		}
		return list;
	}

	private static string FmtVec(Vector3 v)
	{
		return "(" + v.x.ToString("F0") + ", " + v.y.ToString("F0") + ", " + v.z.ToString("F0") + ")";
	}

	private unsafe static string KeyText(ConfigEntry<KeyboardShortcut> entry)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = entry.Value;
		KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
		if ((int)mainKey != 0)
		{
			return ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString();
		}
		return "(无)";
	}

	private unsafe static string KeyShortLabel(KeyboardShortcut ks)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_001f: 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_0010: Invalid comparison between Unknown and I4
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected I4, but got Unknown
		KeyCode mainKey = ((KeyboardShortcut)(ref ks)).MainKey;
		if ((int)mainKey >= 48 && (int)mainKey <= 57)
		{
			return (mainKey - 48).ToString();
		}
		if ((int)mainKey != 0)
		{
			return ((object)(*(KeyCode*)(&mainKey))/*cast due to .constrained prefix*/).ToString();
		}
		return "-";
	}

	private static Color ParseHexColor(string hex, Color fallback)
	{
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(hex))
		{
			return fallback;
		}
		string text = hex.TrimStart('#');
		if (text.Length < 6)
		{
			return fallback;
		}
		try
		{
			float num = (float)Convert.ToInt32(text.Substring(0, 2), 16) / 255f;
			float num2 = (float)Convert.ToInt32(text.Substring(2, 2), 16) / 255f;
			float num3 = (float)Convert.ToInt32(text.Substring(4, 2), 16) / 255f;
			float num4 = ((text.Length >= 8) ? ((float)Convert.ToInt32(text.Substring(6, 2), 16) / 255f) : 1f);
			return new Color(num, num2, num3, num4);
		}
		catch
		{
			return fallback;
		}
	}

	private void EnsureClimb(MapHandler map)
	{
		if (_climbLoaded && (Object)(object)_mphMap == (Object)(object)map)
		{
			return;
		}
		_mphMap = map;
		if ((Object)(object)map == (Object)null)
		{
			_climbLoaded = false;
			_climbNames.Clear();
			return;
		}
		try
		{
			_climbNames.Clear();
			_mph = Object.FindObjectOfType<MountainProgressHandler>();
			if ((Object)(object)_mph == (Object)null)
			{
				return;
			}
			ProgressPoint[] progressPoints = _mph.progressPoints;
			if (progressPoints == null || progressPoints.Length == 0)
			{
				return;
			}
			ProgressPoint[] array = progressPoints;
			foreach (ProgressPoint val in array)
			{
				if (val == null)
				{
					continue;
				}
				string text = "";
				try
				{
					text = val.title ?? "";
				}
				catch
				{
				}
				if (text.Length == 0)
				{
					try
					{
						text = val.localizedTitle ?? "";
					}
					catch
					{
					}
				}
				string text2 = BiomeEn(text);
				if (text2.Length != 0)
				{
					_climbNames.Add(text2);
				}
			}
			_climbLoaded = _climbNames.Count > 0;
		}
		catch (Exception ex)
		{
			_climbLoaded = false;
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] 读取今日爬升序列失败(下次扫描重试): " + ex.Message));
		}
	}

	private static bool IsKnownCanon(string canon)
	{
		switch (NormalizeKey(canon))
		{
		case "shore":
		case "beach":
		case "roots":
		case "gloom":
		case "swamp":
		case "ocean":
		case "nadir":
		case "tropics":
		case "citadel":
		case "caldera":
		case "volcano":
		case "thekiln":
		case "thepeak":
		case "jungle":
		case "forest":
		case "alpine":
		case "desert":
		case "temple":
		case "heaven":
		case "snow":
		case "mesa":
		case "kiln":
		case "peak":
		case "hell":
		case "mars":
		case "void":
		case "grasslands":
		case "thecitadel":
		case "skyblock":
		case "wisconsin":
			return true;
		default:
			return false;
		}
	}

	private static string CanonicalOfSegment(MapSegment seg)
	{
		try
		{
			GameObject segmentParent = seg.segmentParent;
			if ((Object)(object)segmentParent != (Object)null)
			{
				string text = CleanRootName(((Object)segmentParent).name);
				if (text.Length > 0 && IsKnownCanon(text))
				{
					return BiomeEn(text);
				}
			}
		}
		catch
		{
		}
		string text2 = BiomeName(seg);
		if (text2.Length == 0)
		{
			return "";
		}
		string text3 = BiomeEn(text2);
		if (!IsKnownCanon(text3))
		{
			return "";
		}
		return text3;
	}

	private string SegmentCnAt(List<MapSegment> order, int i)
	{
		if (_climbOrderAligned && i < _climbNames.Count)
		{
			return BiomeCn(_climbNames[i]);
		}
		string text = CanonicalOfSegment(order[i]);
		if (text.Length > 0)
		{
			return BiomeCn(text);
		}
		return BiomeCn(BiomeName(order[i]));
	}

	private static string SegDebugInfo(MapSegment seg)
	{
		if (seg == null)
		{
			return "?";
		}
		try
		{
			GameObject segmentParent = seg.segmentParent;
			return "容器:" + (((Object)(object)segmentParent != (Object)null) ? ((Object)segmentParent).name : "(无)") + ", biome:" + BiomeName(seg);
		}
		catch
		{
			return "?";
		}
	}

	private static KeyCode DefaultCategoryKey(int index)
	{
		return (KeyCode)(index switch
		{
			1 => 53, 
			2 => 54, 
			3 => 55, 
			4 => 56, 
			5 => 57, 
			6 => 48, 
			_ => 290, 
		});
	}

	private void BindLuggageConfig()
	{
		_luggageExport = ((BaseUnityPlugin)this).Config.Bind<bool>("Export", "ExportEnabled", true, "小丑行李结果变化时自动导出每日报告(txt/json/latest.json → plugins/ClownLuggageFinder/reports,无坐标)");
	}

	private void ResetLuggageSession()
	{
		RefreshMapSorting(null);
		_luggageSig = "";
		_luggageLogSig = "";
		_luggageSummary = "";
		_luggageOpenedCount = 0;
		_clownHits.Clear();
		_climbOrderAligned = false;
		_climbAlignWarned = false;
	}

	private void RefreshMapSorting(MapHandler map)
	{
		_mapSortingCn = "";
		_mapSortingEn = "";
		_mapSegCount = 0;
		if ((Object)(object)map == (Object)null)
		{
			return;
		}
		EnsureClimb(map);
		if (_climbNames.Count >= 2)
		{
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			foreach (string climbName in _climbNames)
			{
				string value = BiomeCn(climbName);
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(",");
				}
				stringBuilder.Append(value);
				if (stringBuilder2.Length > 0)
				{
					stringBuilder2.Append(">");
				}
				stringBuilder2.Append(climbName);
				_mapSegCount++;
			}
			_mapSortingCn = stringBuilder.ToString();
			_mapSortingEn = stringBuilder2.ToString();
		}
		else
		{
			if (map.segments == null)
			{
				return;
			}
			StringBuilder stringBuilder3 = new StringBuilder();
			StringBuilder stringBuilder4 = new StringBuilder();
			MapSegment[] segments = map.segments;
			foreach (MapSegment val in segments)
			{
				if (val == null)
				{
					continue;
				}
				string text = BiomeName(val);
				if (text.Length != 0)
				{
					string value2 = BiomeCn(text);
					string value3 = BiomeEn(text);
					if (stringBuilder3.Length > 0)
					{
						stringBuilder3.Append(",");
					}
					stringBuilder3.Append(value2);
					if (stringBuilder4.Length > 0)
					{
						stringBuilder4.Append(">");
					}
					stringBuilder4.Append(value3);
					_mapSegCount++;
				}
			}
			_mapSortingCn = stringBuilder3.ToString();
			_mapSortingEn = stringBuilder4.ToString();
		}
	}

	private void ScanLuggage(Category cat, MapHandler map)
	{
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_047a: Unknown result type (might be due to invalid IL or missing references)
		cat.LivePos.Clear();
		cat.LiveNames.Clear();
		_clownHits.Clear();
		_luggageSummary = "";
		_luggageOpenedCount = 0;
		if ((Object)(object)map == (Object)null)
		{
			return;
		}
		EnsureClimb(map);
		List<MapSegment> list = OrderedSegments(map);
		if (list.Count == 0)
		{
			return;
		}
		_climbOrderAligned = _climbNames.Count == list.Count;
		if (!_climbOrderAligned && !_climbAlignWarned && _climbNames.Count > 0)
		{
			_climbAlignWarned = true;
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] 爬升点数(" + _climbNames.Count + ")与段数(" + list.Count + ")不一致,行李段名回退 biome 解析(变体段可能标错)"));
		}
		Luggage[] array = null;
		try
		{
			array = Resources.FindObjectsOfTypeAll<Luggage>();
		}
		catch
		{
		}
		if (array == null || array.Length == 0)
		{
			try
			{
				array = Object.FindObjectsOfType<Luggage>();
			}
			catch
			{
			}
		}
		if (array == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[PEAKFinder] 小丑行李扫描失败:Luggage 查询抛出异常");
			return;
		}
		int num = 0;
		Luggage[] array2 = array;
		foreach (Luggage val in array2)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			try
			{
				if ((Object)(object)((Component)val).gameObject == (Object)null)
				{
					continue;
				}
				Scene scene = ((Component)val).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					continue;
				}
				string text = "";
				try
				{
					text += val.displayName;
				}
				catch
				{
				}
				try
				{
					text = text + " " + ((Object)((Component)val).gameObject).name;
				}
				catch
				{
				}
				try
				{
					text = text + " " + val.GetName();
				}
				catch
				{
				}
				if (!text.ToLowerInvariant().Contains("clown"))
				{
					continue;
				}
				LuggageHit luggageHit = new LuggageHit();
				try
				{
					Transform transform = val.GetTransform();
					luggageHit.Pos = (((Object)(object)transform != (Object)null) ? transform.position : ((Component)val).gameObject.transform.position);
				}
				catch
				{
					num++;
					goto end_IL_013f;
				}
				try
				{
					luggageHit.Open = val.IsOpen;
				}
				catch
				{
				}
				bool active = false;
				try
				{
					active = ((Component)val).gameObject.activeInHierarchy;
				}
				catch
				{
				}
				int num2 = LocateSegmentIndex(list, val, active);
				if (num2 < 0)
				{
					continue;
				}
				luggageHit.SegIdx = num2;
				int num3 = num2;
				if (!_climbOrderAligned)
				{
					string text2 = CanonicalOfSegment(list[num2]);
					int num4 = ((text2.Length > 0) ? _climbNames.IndexOf(text2) : (-1));
					if (num4 >= 0)
					{
						num3 = num4;
					}
				}
				luggageHit.SegLabel = "第" + (num3 + 1) + "段·" + SegmentCnAt(list, num2) + TodayVariantSuffix(num2);
				_clownHits.Add(luggageHit);
				end_IL_013f:;
			}
			catch
			{
				num++;
			}
		}
		if (num > 0)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] 小丑行李扫描有 " + num + " 个对象处理异常(已跳过)"));
		}
		_clownHits.Sort(CompareBySeg);
		StringBuilder stringBuilder = new StringBuilder();
		int num5 = 0;
		for (int j = 0; j < _clownHits.Count; j++)
		{
			LuggageHit luggageHit2 = _clownHits[j];
			if (luggageHit2.Open)
			{
				num5++;
			}
			int num6 = 1;
			for (; j + 1 < _clownHits.Count && _clownHits[j + 1].SegIdx == luggageHit2.SegIdx; j++)
			{
				if (_clownHits[j + 1].Open)
				{
					num5++;
				}
				num6++;
			}
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Append("、");
			}
			stringBuilder.Append(luggageHit2.SegLabel);
			if (num6 > 1)
			{
				stringBuilder.Append("×" + num6);
			}
		}
		_luggageSummary = stringBuilder.ToString();
		_luggageOpenedCount = num5;
		foreach (LuggageHit clownHit in _clownHits)
		{
			cat.LivePos.Add(clownHit.Pos);
			cat.LiveNames.Add(clownHit.SegLabel + (clownHit.Open ? "(已开)" : "(未开)"));
		}
		string text3 = "";
		foreach (LuggageHit clownHit2 in _clownHits)
		{
			text3 = text3 + clownHit2.SegIdx + ":" + (clownHit2.Open ? "1" : "0") + ";";
		}
		if (text3 != _luggageSig)
		{
			_luggageSig = text3;
			if (_luggageExport.Value)
			{
				TryExportLuggageReport(map, list);
			}
		}
		if (!(text3 != _luggageLogSig))
		{
			return;
		}
		_luggageLogSig = text3;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] 小丑行李 " + ((_clownHits.Count > 0) ? ("共 " + _clownHits.Count + ":" + _luggageSummary) : "本图未发现")));
		if (_clownHits.Count <= 0)
		{
			return;
		}
		StringBuilder stringBuilder2 = new StringBuilder();
		foreach (LuggageHit clownHit3 in _clownHits)
		{
			MapSegment seg = ((clownHit3.SegIdx >= 0 && clownHit3.SegIdx < list.Count) ? list[clownHit3.SegIdx] : null);
			if (stringBuilder2.Length > 0)
			{
				stringBuilder2.Append(" | ");
			}
			stringBuilder2.Append(clownHit3.SegLabel).Append(" <- ").Append(SegDebugInfo(seg));
		}
		stringBuilder2.Append(";爬升序列 ").Append(_climbNames.Count).Append(" 项 / 段列表 ")
			.Append(list.Count)
			.Append(" 项")
			.Append(_climbOrderAligned ? "(对齐)" : "(未对齐)");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] 段位解析: " + stringBuilder2.ToString()));
	}

	private static int CompareBySeg(LuggageHit a, LuggageHit b)
	{
		return a.SegIdx.CompareTo(b.SegIdx);
	}

	private static List<MapSegment> OrderedSegments(MapHandler map)
	{
		List<MapSegment> list = new List<MapSegment>();
		if ((Object)(object)map == (Object)null || map.segments == null)
		{
			return list;
		}
		MapSegment[] segments = map.segments;
		foreach (MapSegment val in segments)
		{
			if (val != null && BiomeName(val).Length != 0)
			{
				list.Add(val);
			}
		}
		return list;
	}

	private static int LocateSegmentIndex(List<MapSegment> order, Luggage l, bool active)
	{
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Transform transform = l.GetTransform();
			if ((Object)(object)transform == (Object)null)
			{
				transform = ((Component)l).gameObject.transform;
			}
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					for (int i = 0; i < order.Count; i++)
					{
						if (GameObjectEquals(order[i].segmentParent, ((Component)val).gameObject) || GameObjectEquals(order[i].segmentCampfire, ((Component)val).gameObject))
						{
							return i;
						}
					}
				}
				val = val.parent;
			}
		}
		catch
		{
		}
		try
		{
			Transform transform2 = l.GetTransform();
			if ((Object)(object)transform2 == (Object)null)
			{
				transform2 = ((Component)l).gameObject.transform;
			}
			Transform val2 = transform2;
			while ((Object)(object)val2 != (Object)null)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null))
				{
					string text = CleanRootName(((Object)((Component)val2).gameObject).name);
					if (text.Length != 0)
					{
						int result = -1;
						int num = 0;
						for (int j = 0; j < order.Count; j++)
						{
							if (NormalizeKey(text) == NormalizeKey(BiomeName(order[j])))
							{
								num++;
								result = j;
							}
						}
						if (num == 1)
						{
							return result;
						}
					}
				}
				val2 = val2.parent;
			}
		}
		catch
		{
		}
		if (active)
		{
			try
			{
				MapSegment currentMapSegment = MapHandler.CurrentMapSegment;
				if (currentMapSegment != null)
				{
					for (int k = 0; k < order.Count; k++)
					{
						if (GameObjectEquals(order[k].segmentParent, currentMapSegment.segmentParent) || GameObjectEquals(order[k].segmentCampfire, currentMapSegment.segmentCampfire))
						{
							return k;
						}
					}
				}
			}
			catch
			{
			}
		}
		try
		{
			Transform transform3 = l.GetTransform();
			if ((Object)(object)transform3 == (Object)null)
			{
				transform3 = ((Component)l).gameObject.transform;
			}
			if ((Object)(object)transform3 != (Object)null)
			{
				int result2 = -1;
				float num2 = float.MaxValue;
				for (int m = 0; m < order.Count; m++)
				{
					GameObject segmentParent = order[m].segmentParent;
					if (!((Object)(object)segmentParent == (Object)null))
					{
						Vector3 val3 = segmentParent.transform.position - transform3.position;
						float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
						if (sqrMagnitude < num2)
						{
							num2 = sqrMagnitude;
							result2 = m;
						}
					}
				}
				return result2;
			}
		}
		catch
		{
		}
		return -1;
	}

	private static bool GameObjectEquals(GameObject a, GameObject b)
	{
		if ((Object)(object)a != (Object)null && (Object)(object)b != (Object)null)
		{
			return (Object)(object)a == (Object)(object)b;
		}
		return false;
	}

	private void TryExportLuggageReport(MapHandler map, List<MapSegment> order)
	{
		try
		{
			if (!_luggageExport.Value || (Object)(object)map == (Object)null || !MapHandler.Exists || !MapHandler.ExistsAndInitialized)
			{
				return;
			}
			if (_clownHits.Count == 0)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[PEAKFinder] 小丑行李报告:当前地图未发现,跳过导出");
				return;
			}
			string text = Path.Combine(Paths.PluginPath, "ClownLuggageFinder", "reports");
			try
			{
				Directory.CreateDirectory(text);
			}
			catch
			{
			}
			string text2 = DateTime.Now.ToString("yyyy-MM-dd");
			string text3 = Path.Combine(text, "clown_luggage_" + text2);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("=== PEAK 小丑行李每日报告(不含坐标) ===");
			stringBuilder.AppendLine("日期: " + text2);
			stringBuilder.AppendLine("生成时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
			stringBuilder.AppendLine("山峰排序(中文): " + _mapSortingCn);
			if (_mapSortingDetailCn.Length > 0)
			{
				stringBuilder.AppendLine("山峰排序(含变体): " + _mapSortingDetailCn);
			}
			stringBuilder.AppendLine("山峰排序(英文): " + _mapSortingEn);
			stringBuilder.AppendLine("小丑行李数量: " + _clownHits.Count);
			stringBuilder.AppendLine("");
			int num = 1;
			foreach (LuggageHit clownHit in _clownHits)
			{
				stringBuilder.AppendLine("小丑行李 #" + num + ":");
				stringBuilder.AppendLine("  位置: " + clownHit.SegLabel);
				stringBuilder.AppendLine("  状态: " + (clownHit.Open ? "已打开" : "未打开"));
				stringBuilder.AppendLine("");
				num++;
			}
			File.WriteAllText(text3 + ".txt", stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: true));
			StringBuilder stringBuilder2 = new StringBuilder();
			stringBuilder2.Append("{\"date\":\"" + DateTime.Now.ToString("M月d日") + "\",");
			stringBuilder2.Append("\"map\":\"" + JsonEsc(_mapSortingEn) + "\",");
			stringBuilder2.Append("\"MapSorting\":\"" + JsonEsc(_mapSortingCn) + "\",");
			if (_mapSortingDetailCn.Length > 0)
			{
				stringBuilder2.Append("\"MapSortingDetail\":\"" + JsonEsc(_mapSortingDetailCn) + "\",");
			}
			stringBuilder2.Append("\"num\":" + _clownHits.Count + ",");
			StringBuilder stringBuilder3 = new StringBuilder();
			bool flag = true;
			for (int i = 0; i < order.Count; i++)
			{
				int num2 = 0;
				foreach (LuggageHit clownHit2 in _clownHits)
				{
					if (clownHit2.SegIdx == i)
					{
						num2++;
					}
				}
				if (num2 != 0)
				{
					if (!flag)
					{
						stringBuilder3.Append(",");
					}
					flag = false;
					stringBuilder3.Append("\"" + JsonEsc(SegmentCnAt(order, i) + TodayVariantSuffix(i)) + "\":" + num2);
				}
			}
			stringBuilder2.Append("\"segments\":{" + stringBuilder3.ToString() + "},");
			stringBuilder2.Append("\"location\":[");
			bool flag2 = true;
			foreach (LuggageHit clownHit3 in _clownHits)
			{
				if (!flag2)
				{
					stringBuilder2.Append(",");
				}
				flag2 = false;
				stringBuilder2.Append("{\"segment\":\"" + JsonEsc(clownHit3.SegLabel) + "\",\"open\":" + (clownHit3.Open ? "true" : "false") + "}");
			}
			stringBuilder2.Append("],");
			stringBuilder2.Append("\"totalnum\":" + _clownHits.Count);
			stringBuilder2.Append("}");
			string contents = stringBuilder2.ToString();
			File.WriteAllText(text3 + ".json", contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			File.WriteAllText(Path.Combine(text, "latest.json"), contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] 小丑行李报告已导出: " + text3 + ".txt"));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[PEAKFinder] 小丑行李报告导出失败: " + ex));
		}
	}

	private static string BiomeName(MapSegment seg)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			string text = ((object)seg.biome/*cast due to .constrained prefix*/).ToString();
			if (!string.IsNullOrEmpty(text) && text != "0")
			{
				return text;
			}
		}
		catch
		{
		}
		try
		{
			GameObject segmentParent = seg.segmentParent;
			if ((Object)(object)segmentParent != (Object)null)
			{
				string text2 = CleanRootName(((Object)segmentParent).name);
				if (text2.Length > 0)
				{
					return text2;
				}
			}
		}
		catch
		{
		}
		return "";
	}

	private static string BiomeCn(string en)
	{
		switch (NormalizeKey(en))
		{
		case "shore":
		case "beach":
			return "海岸";
		case "tropics":
		case "jungle":
			return "雨林";
		case "roots":
		case "forest":
			return "森林";
		case "alpine":
		case "snow":
			return "雪山";
		case "desert":
		case "mesa":
			return "方山";
		case "gloom":
		case "swamp":
			return "雾沼";
		case "citadel":
		case "temple":
		case "thecitadel":
			return "城塞";
		case "caldera":
		case "volcano":
			return "火山";
		case "thekiln":
		case "kiln":
			return "熔炉";
		case "thepeak":
		case "peak":
			return "顶峰";
		case "grasslands":
			return "草原";
		case "ocean":
			return "海洋";
		case "skyblock":
			return "浮岛";
		case "hell":
			return "地狱";
		case "heaven":
			return "天堂";
		case "mars":
			return "火星";
		case "wisconsin":
			return "威斯康星";
		case "void":
			return "虚空";
		case "nadir":
			return "深渊";
		default:
			if (en != null)
			{
				return en.Trim();
			}
			return "";
		}
	}

	private static string BiomeEn(string en)
	{
		switch (NormalizeKey(en))
		{
		case "shore":
		case "beach":
			return "Shore";
		case "tropics":
		case "jungle":
			return "Tropics";
		case "roots":
		case "forest":
			return "Roots";
		case "alpine":
		case "snow":
			return "Alpine";
		case "desert":
		case "mesa":
			return "Mesa";
		case "gloom":
		case "swamp":
			return "Gloom";
		case "citadel":
		case "temple":
		case "thecitadel":
			return "The Citadel";
		case "caldera":
		case "volcano":
			return "Caldera";
		case "thekiln":
		case "kiln":
			return "The Kiln";
		case "thepeak":
		case "peak":
			return "The Peak";
		case "grasslands":
			return "Grasslands";
		case "ocean":
			return "Ocean";
		case "skyblock":
			return "Skyblock";
		case "hell":
			return "Hell";
		case "heaven":
			return "Heaven";
		case "mars":
			return "Mars";
		case "wisconsin":
			return "Wisconsin";
		case "void":
			return "Void";
		case "nadir":
			return "Nadir";
		default:
			if (en != null)
			{
				return en.Trim();
			}
			return "";
		}
	}

	private static string NormalizeKey(string en)
	{
		if (en == null)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		string text = en.ToLowerInvariant();
		foreach (char c in text)
		{
			if (c != '_' && c != '-' && c != ' ' && c != '.')
			{
				stringBuilder.Append(c);
			}
		}
		return stringBuilder.ToString();
	}

	private static string CleanRootName(string n)
	{
		if (n == null)
		{
			return "";
		}
		return n.Replace("_Segment", "").Replace("Segment", "").Replace("_Campfire", "")
			.Replace("Campfire", "")
			.Trim()
			.Trim('_', '-', ' ', '.');
	}

	private static string JsonEsc(string s)
	{
		if (s == null)
		{
			return "";
		}
		return s.Replace("\\", "\\\\").Replace("\"", "\\\"");
	}

	internal void BindTodayConfig()
	{
		_todayExport = ((BaseUnityPlugin)this).Config.Bind<bool>("Export", "ExportTodayMapDetail", true, "今日地图详情变化时自动导出 json(plugins/ClownLuggageFinder/reports/today_map_*.json,无坐标);Ctrl+F1 重扫也会导出");
	}

	internal static bool BiomeHasVariant(int biome)
	{
		if (biome != 0 && biome != 1 && biome != 2 && biome != 6)
		{
			return biome == 7;
		}
		return true;
	}

	private void RebuildToday(MapHandler map)
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Expected I4, but got Unknown
		_today.Clear();
		_todayDetailCn = "";
		if ((Object)(object)map == (Object)null)
		{
			return;
		}
		List<MapSegment> list = OrderedSegments(map);
		if (_climbNames.Count == 0 || list.Count == 0)
		{
			return;
		}
		bool flag = _climbNames.Count == list.Count;
		int num = (flag ? _climbNames.Count : list.Count);
		for (int i = 0; i < num; i++)
		{
			TodaySeg todaySeg = new TodaySeg
			{
				Index = i
			};
			todaySeg.Canon = (flag ? _climbNames[i] : BiomeEn(BiomeName(list[i])));
			try
			{
				todaySeg.Biome = (int)list[i].biome;
			}
			catch
			{
				todaySeg.Biome = -1;
			}
			_today.Add(todaySeg);
		}
		_todayAligned = flag;
	}

	private void RefreshTodayDetail(MapHandler map, bool forceExport)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)map == (Object)null)
			{
				_todayMapSig = "";
				_todayExportSig = "";
				_today.Clear();
				_todayDetailCn = "";
				return;
			}
			Scene scene = ((Component)map).gameObject.scene;
			string text = ((Scene)(ref scene)).name + "|" + string.Join(">", _climbNames.ToArray());
			if (text != _todayMapSig || _today.Count == 0)
			{
				_todayMapSig = text;
				RebuildToday(map);
			}
			if (_today.Count == 0)
			{
				return;
			}
			List<MapSegment> order = OrderedSegments(map);
			bool flag = false;
			for (int i = 0; i < _today.Count; i++)
			{
				TodaySeg todaySeg = _today[i];
				if (todaySeg.Done || !BiomeHasVariant(todaySeg.Biome))
				{
					continue;
				}
				bool parentActive;
				string text2 = ResolveSegmentVariant(order, i, todaySeg.Biome, out parentActive);
				if (text2 != null)
				{
					todaySeg.Done = text2.Length > 0 || parentActive;
					if (text2.Length > 0 && text2 != todaySeg.VariantEn)
					{
						todaySeg.VariantEn = text2;
						todaySeg.VariantCn = LocalizeVariant(todaySeg.Biome, text2);
						flag = true;
						((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] 今日变体: 段" + (i + 1) + "·" + todaySeg.Canon + " = " + text2 + ((todaySeg.VariantCn.Length > 0) ? ("(" + todaySeg.VariantCn + ")") : "")));
					}
				}
			}
			if (flag)
			{
				RefreshDetailString();
			}
			if (forceExport || flag)
			{
				string text3 = _todayMapSig + "|" + BuildDetailCanons();
				if (forceExport || text3 != _todayExportSig)
				{
					_todayExportSig = text3;
					TryExportTodayDetail(map);
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] 今日变体解析失败: " + ex.Message));
		}
	}

	private string ResolveSegmentVariant(List<MapSegment> order, int i, int biome, out bool parentActive)
	{
		parentActive = false;
		try
		{
			if (i >= order.Count)
			{
				return null;
			}
			GameObject segmentParent = order[i].segmentParent;
			if ((Object)(object)segmentParent == (Object)null)
			{
				return null;
			}
			parentActive = segmentParent.activeInHierarchy;
			string text = CollectChosenVariantName(segmentParent, biome, parentActive);
			if (text != null)
			{
				return text;
			}
			Transform parent = segmentParent.transform.parent;
			if ((Object)(object)parent != (Object)null && (Object)(object)((Component)parent).gameObject != (Object)null && (Object)(object)((Component)parent).gameObject != (Object)(object)segmentParent)
			{
				string text2 = CollectChosenVariantName(((Component)parent).gameObject, biome, ((Component)parent).gameObject.activeInHierarchy);
				if (text2 != null)
				{
					parentActive = true;
					return text2;
				}
			}
			return parentActive ? "" : null;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[PEAKFinder] 段变体读取异常: " + ex.Message));
			return parentActive ? "" : null;
		}
	}

	private string CollectChosenVariantName(GameObject root, int biome, bool rootActive)
	{
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		if (biome == 6 || biome == 7)
		{
			List<string> list = new List<string>();
			VariantObject[] componentsInChildren = root.GetComponentsInChildren<VariantObject>(true);
			if (componentsInChildren == null)
			{
				return null;
			}
			VariantObject[] array = componentsInChildren;
			foreach (VariantObject val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
				{
					GameObject gameObject = ((Component)val).gameObject;
					if (rootActive ? gameObject.activeInHierarchy : gameObject.activeSelf)
					{
						list.Add(((Object)gameObject).name);
					}
				}
			}
			HashSet<string> hashSet = ((biome == 6) ? MesaKnownVariants : RootsKnownVariants);
			foreach (string item in list)
			{
				if (hashSet.Contains(item))
				{
					return CleanVariant(biome, item);
				}
			}
			foreach (string item2 in list)
			{
				if (item2.Equals("Default", StringComparison.Ordinal))
				{
					return CleanVariant(biome, item2);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			return CleanVariant(biome, list[0]);
		}
		List<string> list2 = new List<string>();
		BiomeVariant[] componentsInChildren2 = root.GetComponentsInChildren<BiomeVariant>(true);
		if (componentsInChildren2 == null)
		{
			return null;
		}
		BiomeVariant[] array2 = componentsInChildren2;
		foreach (BiomeVariant val2 in array2)
		{
			if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)null)
			{
				continue;
			}
			GameObject gameObject2 = ((Component)val2).gameObject;
			if (rootActive ? gameObject2.activeInHierarchy : gameObject2.activeSelf)
			{
				string name = ((Object)gameObject2).name;
				if (!string.IsNullOrWhiteSpace(name) && !list2.Contains(name))
				{
					list2.Add(name.Trim());
				}
			}
		}
		if (list2.Count == 0)
		{
			return null;
		}
		return CleanVariant(biome, list2[0]);
	}

	private static string CleanVariant(int biome, string variant)
	{
		switch (biome)
		{
		case 6:
			if (variant.Equals("NoVariant", StringComparison.Ordinal))
			{
				return "Default";
			}
			if (variant.Equals("CacusHell", StringComparison.Ordinal))
			{
				return "CactusHell";
			}
			return variant;
		default:
			return variant;
		case 7:
		{
			string[] array = variant.Split(' ', '-');
			if (array.Length <= 1)
			{
				return variant;
			}
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				if (text.Length > 0)
				{
					text = char.ToUpperInvariant(text[0]) + text.Substring(1).ToLowerInvariant();
				}
				if (RootsStructuralNames.Contains(text))
				{
					text = "";
				}
				array[i] = text;
			}
			return string.Join("", array);
		}
		}
	}

	private static string LocalizeVariant(int biome, string variant)
	{
		if (VariantCnMap.TryGetValue(biome, out var value) && value.TryGetValue(variant, out var value2))
		{
			return value2;
		}
		return variant;
	}

	private void RefreshDetailString()
	{
		_todayDetailCn = "";
		if (!_todayAligned || _today.Count == 0)
		{
			return;
		}
		StringBuilder stringBuilder = new StringBuilder();
		foreach (TodaySeg item in _today)
		{
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Append(",");
			}
			stringBuilder.Append(BiomeCn(item.Canon));
			if (item.VariantCn.Length > 0)
			{
				stringBuilder.Append('(').Append(item.VariantCn).Append(')');
			}
		}
		_todayDetailCn = stringBuilder.ToString();
	}

	private string BuildDetailCanons()
	{
		StringBuilder stringBuilder = new StringBuilder();
		foreach (TodaySeg item in _today)
		{
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Append('>');
			}
			stringBuilder.Append(item.Canon);
			if (item.VariantEn.Length > 0)
			{
				stringBuilder.Append('(').Append(item.VariantEn).Append(')');
			}
		}
		return stringBuilder.ToString();
	}

	private string TodayVariantSuffix(int segIdx)
	{
		if (!_todayAligned || segIdx < 0 || segIdx >= _today.Count)
		{
			return "";
		}
		TodaySeg todaySeg = _today[segIdx];
		if (todaySeg.VariantCn.Length <= 0)
		{
			return "";
		}
		return "(" + todaySeg.VariantCn + ")";
	}

	private static string SafeFileName(string n)
	{
		if (string.IsNullOrEmpty(n))
		{
			return "level";
		}
		char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
		StringBuilder stringBuilder = new StringBuilder();
		foreach (char c in n)
		{
			bool flag = false;
			char[] array = invalidFileNameChars;
			foreach (char c2 in array)
			{
				if (c == c2)
				{
					flag = true;
					break;
				}
			}
			stringBuilder.Append(flag ? '_' : c);
		}
		return stringBuilder.ToString();
	}

	private void TryExportTodayDetail(MapHandler map)
	{
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!_todayExport.Value || (Object)(object)map == (Object)null || _today.Count == 0 || !MapHandler.Exists || !MapHandler.ExistsAndInitialized)
			{
				return;
			}
			string text = Path.Combine(Paths.PluginPath, "ClownLuggageFinder", "reports");
			try
			{
				Directory.CreateDirectory(text);
			}
			catch
			{
			}
			string text2 = DateTime.Now.ToString("yyyy-MM-dd");
			string text3 = Path.Combine(text, "today_map_" + text2);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("{\"date\":\"" + DateTime.Now.ToString("M月d日") + "\",");
			Scene scene = ((Component)map).gameObject.scene;
			stringBuilder.Append("\"level\":\"" + JsonEsc(SafeFileName(((Scene)(ref scene)).name)) + "\",");
			stringBuilder.Append("\"map\":\"" + JsonEsc(BuildDetailCanons()) + "\",");
			stringBuilder.Append("\"MapSorting\":\"" + JsonEsc((_mapSortingDetailCn.Length > 0) ? _mapSortingDetailCn : _mapSortingCn) + "\",");
			stringBuilder.Append("\"num\":" + _today.Count + ",");
			stringBuilder.Append("\"segments\":[");
			bool flag = true;
			foreach (TodaySeg item in _today)
			{
				if (!flag)
				{
					stringBuilder.Append(",");
				}
				flag = false;
				string text4 = BiomeCn(item.Canon);
				stringBuilder.Append("{\"index\":" + item.Index + ",");
				stringBuilder.Append("\"label\":\"" + JsonEsc("第" + (item.Index + 1) + "段·" + text4 + TodayVariantSuffix(item.Index)) + "\",");
				stringBuilder.Append("\"biome\":\"" + JsonEsc(item.Canon) + "\",");
				stringBuilder.Append("\"biome_cn\":\"" + JsonEsc(text4) + "\",");
				stringBuilder.Append("\"variant\":\"" + JsonEsc(item.VariantEn) + "\",");
				stringBuilder.Append("\"variant_cn\":\"" + JsonEsc(item.VariantCn) + "\"}");
			}
			stringBuilder.Append("]}");
			string contents = stringBuilder.ToString();
			File.WriteAllText(text3 + ".json", contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			File.WriteAllText(Path.Combine(text, "today_map_latest.json"), contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[PEAKFinder] 今日地图详情已导出: " + text3 + ".json" + ((_mapSortingDetailCn.Length > 0) ? ("(" + _mapSortingDetailCn + ")") : "")));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[PEAKFinder] 今日地图详情导出失败: " + ex));
		}
	}
}