Decompiled source of Hard Item Randomizer v1.11.18

BepInEx/plugins/AssetChainFixer.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;

[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.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[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;
		}
	}
}
namespace AssetChainFixer
{
	[BepInPlugin("com.assetchain.fixer", "AssetChainFixer", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static bool ManualPlayEnabled = true;

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AssetChainFixer] 已加载。");
		}

		private void Update()
		{
			if (Input_GetKeyDown_F5())
			{
				ChainFixer.RunDemoSpawn();
			}
			if (Input_GetKeyDown_F6())
			{
				ManualPlayEnabled = !ManualPlayEnabled;
			}
		}

		private static bool Input_GetKeyDown_F5()
		{
			return Input.GetKeyDown((KeyCode)286);
		}

		private static bool Input_GetKeyDown_F6()
		{
			return Input.GetKeyDown((KeyCode)287);
		}
	}
	public static class ChainFixer
	{
		public enum BundleType
		{
			Unknown,
			Normal,
			StreamedScene
		}

		private static readonly Regex BundleSuffixRegex = new Regex("_[0-9a-fA-F]{32}\\.bundle+$", RegexOptions.Compiled);

		private static Dictionary<string, string> _bundleKeys;

		private static Dictionary<string, GameObject> _prefabCache = new Dictionary<string, GameObject>(StringComparer.Ordinal);

		private static tk2dSpriteCollectionData _cachedCoinRocksCollection;

		private static bool _coinRocksLoadAttempted;

		private static Dictionary<string, Sprite> _spriteCache;

		public static void EnsureBundleKeyMap()
		{
			if (_bundleKeys != null)
			{
				return;
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			try
			{
				foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
				{
					foreach (object key2 in resourceLocator.Keys)
					{
						if (key2 is string text)
						{
							Match match = BundleSuffixRegex.Match(text);
							if (match.Success)
							{
								string key = BundleSuffixRegex.Replace(text, "");
								dictionary[key] = text;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[ChainFixer] 构建 bundle key 映射异常: " + ex.Message));
				}
			}
			_bundleKeys = ((dictionary.Count > 0) ? dictionary : null);
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"[ChainFixer] bundle key 映射: {dictionary.Count} 个");
			}
		}

		public static string ToBundleKey(string name)
		{
			EnsureBundleKeyMap();
			if (_bundleKeys == null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[ChainFixer] bundle key 映射未就绪(Addressables 未加载 catalog)");
				}
				return name;
			}
			if (BundleSuffixRegex.IsMatch(name))
			{
				name = BundleSuffixRegex.Replace(name, "");
			}
			else if (name.EndsWith(".bundle", StringComparison.OrdinalIgnoreCase))
			{
				name = name.Substring(0, name.Length - 7);
			}
			if (_bundleKeys.TryGetValue(name, out var value))
			{
				return value;
			}
			throw new Exception("Bundle " + name + " not found in lookup.");
		}

		public static List<string> FindKeysContaining(string fragment, string logTag = "ChainFixer")
		{
			List<string> list = new List<string>();
			try
			{
				foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
				{
					foreach (object key in resourceLocator.Keys)
					{
						if (key is string text && text.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0)
						{
							list.Add(text);
							ManualLogSource log = Plugin.Log;
							if (log != null)
							{
								log.LogInfo((object)("[" + logTag + "] key 匹配 '" + fragment + "': " + text));
							}
						}
					}
				}
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[{logTag}] 匹配 '{fragment}' 共 {list.Count} 个");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("[" + logTag + "] 遍历 key 异常: " + ex.Message));
				}
			}
			return list;
		}

		public static T LoadNativeDataSet<T>(string keyFragment, string assetPath, string logTag = "ChainFixer") where T : Object
		{
			//IL_0073: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			List<string> list = FindKeysContaining(keyFragment, logTag);
			if (list.Count == 0)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[" + logTag + "] 未找到含 '" + keyFragment + "' 的数据集 key"));
				}
				return default(T);
			}
			string text = list[0];
			AssetBundle val = null;
			try
			{
				AsyncOperationHandle<IAssetBundleResource> val2 = default(AsyncOperationHandle<IAssetBundleResource>);
				val2 = Addressables.LoadAssetAsync<IAssetBundleResource>((object)text);
				val2.WaitForCompletion();
				if ((int)val2.Status != 1 || val2.Result == null)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)$"[{logTag}] 数据集加载失败: {text} → {val2.OperationException}");
					}
					return default(T);
				}
				val = val2.Result.GetAssetBundle();
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("[" + logTag + "] 数据集加载异常 " + text + ": " + ex.Message));
				}
				return default(T);
			}
			if ((Object)(object)val == (Object)null)
			{
				return default(T);
			}
			T val3 = val.LoadAsset<T>(assetPath);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.LoadAllAssets<T>().FirstOrDefault();
			}
			if ((Object)(object)val3 != (Object)null)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)("[" + logTag + "] 数据集命中: key=" + text + " asset=" + assetPath + " → " + ((Object)val3).name));
				}
			}
			else
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[" + logTag + "] 数据集未命中: key=" + text + " asset=" + assetPath));
				}
			}
			return val3;
		}

		public static SavedItem LoadDataSavedItem(string keyFragment, string assetName, string logTag = "ChainFixer")
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			List<string> list = FindKeysContaining(keyFragment, logTag);
			if (list.Count == 0)
			{
				return null;
			}
			string text = list[0];
			try
			{
				AsyncOperationHandle<IAssetBundleResource> val = default(AsyncOperationHandle<IAssetBundleResource>);
				val = Addressables.LoadAssetAsync<IAssetBundleResource>((object)text);
				val.WaitForCompletion();
				if ((int)val.Status != 1 || val.Result == null)
				{
					return null;
				}
				AssetBundle assetBundle = val.Result.GetAssetBundle();
				if ((Object)(object)assetBundle == (Object)null)
				{
					return null;
				}
				SavedItem val2 = assetBundle.LoadAsset<SavedItem>(assetName);
				if ((Object)(object)val2 != (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[" + logTag + "] 数据集命中 SavedItem '" + assetName + "' @ " + text));
					}
					return val2;
				}
				GameObject val3 = assetBundle.LoadAsset<GameObject>(assetName);
				if ((Object)(object)val3 != (Object)null)
				{
					SavedItem component = val3.GetComponent<SavedItem>();
					if ((Object)(object)component != (Object)null)
					{
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogInfo((object)("[" + logTag + "] 数据集命中 GameObject→SavedItem '" + assetName + "' @ " + text));
						}
						return component;
					}
					PrefabCollectable component2 = val3.GetComponent<PrefabCollectable>();
					if ((Object)(object)component2 != (Object)null)
					{
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogInfo((object)("[" + logTag + "] 数据集命中 GameObject→PrefabCollectable '" + assetName + "' @ " + text));
						}
						return (SavedItem)(object)component2;
					}
				}
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("[" + logTag + "] 数据集未找到 '" + assetName + "' @ " + text));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[" + logTag + "] 数据集加载异常 " + text + ": " + ex.Message));
				}
			}
			return null;
		}

		public static AssetBundle LoadBundleWithDeps(string bundleName, string logTag = "ChainFixer")
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Invalid comparison between Unknown and I4
			string text;
			try
			{
				text = ToBundleKey(bundleName);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[" + logTag + "] bundle key 映射未命中 " + bundleName + ",尝试直接 key 加载: " + ex.Message));
				}
				text = bundleName;
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[" + logTag + "] Addressables 加载 " + bundleName + " → key=" + text));
			}
			AsyncOperationHandle<IAssetBundleResource> val = default(AsyncOperationHandle<IAssetBundleResource>);
			try
			{
				val = Addressables.LoadAssetAsync<IAssetBundleResource>((object)text);
				val.WaitForCompletion();
				if ((int)val.Status != 1 || val.Result == null)
				{
					ManualLogSource log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)$"[{logTag}] Addressables 加载失败: {val.OperationException}");
					}
					return null;
				}
				AssetBundle assetBundle = val.Result.GetAssetBundle();
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)("[" + logTag + "] bundle 依赖链加载成功: " + ((Object)assetBundle).name));
				}
				return assetBundle;
			}
			catch (Exception ex2)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[" + logTag + "] Addressables 加载异常 " + bundleName + ": " + ex2.Message));
				}
				return null;
			}
		}

		public static List<RuntimeAnimatorController> WarmupBundle(AssetBundle bundle, string logTag = "ChainFixer")
		{
			List<RuntimeAnimatorController> list = new List<RuntimeAnimatorController>();
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			try
			{
				Object[] array = bundle.LoadAllAssets();
				foreach (Object val in array)
				{
					if (val == (Object)null)
					{
						continue;
					}
					num3++;
					if (val is Sprite)
					{
						num++;
						continue;
					}
					RuntimeAnimatorController val2 = (RuntimeAnimatorController)(object)((val is RuntimeAnimatorController) ? val : null);
					if (val2 != null)
					{
						list.Add(val2);
					}
					else if (val is AnimationClip)
					{
						num2++;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[" + logTag + "] 预热异常: " + ex.Message));
				}
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"[{logTag}] 预热(全量): total={num3} sprites={num} controllers={list.Count} clips={num2}");
			}
			return list;
		}

		public static int FixAnimatorControllers(GameObject root, List<RuntimeAnimatorController> loadedCtrls, string logTag = "ChainFixer")
		{
			if (loadedCtrls == null || loadedCtrls.Count == 0)
			{
				return 0;
			}
			Dictionary<string, RuntimeAnimatorController> dictionary = new Dictionary<string, RuntimeAnimatorController>(StringComparer.OrdinalIgnoreCase);
			foreach (RuntimeAnimatorController loadedCtrl in loadedCtrls)
			{
				if (!dictionary.ContainsKey(((Object)loadedCtrl).name))
				{
					dictionary[((Object)loadedCtrl).name] = loadedCtrl;
				}
			}
			int num = 0;
			Animator[] componentsInChildren = root.GetComponentsInChildren<Animator>(true);
			foreach (Animator val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || val.layerCount > 0)
				{
					continue;
				}
				string text = (((Object)(object)val.runtimeAnimatorController != (Object)null) ? ((Object)val.runtimeAnimatorController).name : ((Object)((Component)val).gameObject).name);
				if (!string.IsNullOrEmpty(text) && dictionary.TryGetValue(text, out var value))
				{
					val.runtimeAnimatorController = value;
					num++;
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"[{logTag}] 回填 Controller: {text} → {((Object)((Component)val).gameObject).name}, Layers={val.layerCount}");
					}
				}
			}
			return num;
		}

		public static GameObject SpawnWithFullChain(string bundleName, string prefabPath, Transform parent, string logTag = "ChainFixer")
		{
			AssetBundle val = LoadBundleWithDeps(bundleName, logTag);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			List<RuntimeAnimatorController> loadedCtrls = WarmupBundle(val, logTag);
			GameObject val2 = val.LoadAsset<GameObject>(prefabPath);
			if ((Object)(object)val2 == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[" + logTag + "] prefab 加载失败: " + prefabPath));
				}
				return null;
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[" + logTag + "] prefab 加载成功: " + ((Object)val2).name));
			}
			GameObject val3 = Object.Instantiate<GameObject>(val2);
			if ((Object)(object)parent != (Object)null)
			{
				val3.transform.SetParent(parent, false);
			}
			val3.SetActive(false);
			FixAnimatorControllers(val3, loadedCtrls, logTag);
			return val3;
		}

		public static void DumpSceneExtractDiagnostics(string sceneAddress, string sceneBundleKey, Func<GameObject, bool> matcher, string logTag = "ChainFixer")
		{
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Invalid comparison between Unknown and I4
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[" + logTag + "] ===== F4 场景提取诊断开始 ====="));
				}
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[" + logTag + "] 目标场景 address: '" + sceneAddress + "',目标 bundle key: '" + sceneBundleKey + "'"));
				}
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("[" + logTag + "] --- 1. 遍历全部 locator keys ---"));
				}
				int num = 0;
				List<string> list = new List<string>();
				List<string> list2 = new List<string>();
				foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
				{
					foreach (object key in resourceLocator.Keys)
					{
						if (key is string text)
						{
							num++;
							if (text.IndexOf("aspid", StringComparison.OrdinalIgnoreCase) >= 0)
							{
								list.Add(text);
							}
							if (text.StartsWith("Scenes/", StringComparison.OrdinalIgnoreCase))
							{
								list2.Add(text);
							}
						}
					}
				}
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)$"[{logTag}] locator 总 key 数: {num}");
				}
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogInfo((object)string.Format("[{0}] 含 'aspid' 的 key ({1}): {2}", logTag, list.Count, string.Join(" | ", list)));
				}
				ManualLogSource log6 = Plugin.Log;
				if (log6 != null)
				{
					log6.LogInfo((object)string.Format("[{0}] 以 'Scenes/' 开头的 key ({1}): {2}", logTag, list2.Count, string.Join(" | ", list2.Take(50))));
				}
				ManualLogSource log7 = Plugin.Log;
				if (log7 != null)
				{
					log7.LogInfo((object)("[" + logTag + "] --- 2. LoadResourceLocations 定位场景 " + sceneAddress + " ---"));
				}
				try
				{
					AsyncOperationHandle<IList<IResourceLocation>> val = Addressables.LoadResourceLocationsAsync((object)sceneAddress, typeof(Scene));
					val.WaitForCompletion();
					ManualLogSource log8 = Plugin.Log;
					if (log8 != null)
					{
						log8.LogInfo((object)string.Format("[{0}] LoadResourceLocations(Scene) Status={1} Result={2} loc", logTag, val.Status, (val.Result == null) ? "null" : val.Result.Count.ToString()));
					}
					if (val.Result != null)
					{
						foreach (IResourceLocation item in val.Result)
						{
							ManualLogSource log9 = Plugin.Log;
							if (log9 != null)
							{
								log9.LogInfo((object)$"[{logTag}]   Scene location: InternalId='{item.InternalId}' PrimaryKey='{item.PrimaryKey}' ResourceType={item.ResourceType} Data={item.Data}");
							}
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log10 = Plugin.Log;
					if (log10 != null)
					{
						log10.LogWarning((object)("[" + logTag + "] LoadResourceLocations(Scene) 异常: " + ex.Message));
					}
				}
				ManualLogSource log11 = Plugin.Log;
				if (log11 != null)
				{
					log11.LogInfo((object)("[" + logTag + "] --- 3. 尝试用场景 address 加载 bundle (IAssetBundleResource) ---"));
				}
				try
				{
					AsyncOperationHandle<IAssetBundleResource> val2 = Addressables.LoadAssetAsync<IAssetBundleResource>((object)sceneAddress);
					val2.WaitForCompletion();
					ManualLogSource log12 = Plugin.Log;
					if (log12 != null)
					{
						object[] obj = new object[4] { logTag, sceneAddress, val2.Status, null };
						object obj2;
						if (val2.Result != null)
						{
							AssetBundle assetBundle = val2.Result.GetAssetBundle();
							obj2 = ((assetBundle != null) ? ((Object)assetBundle).name : null);
						}
						else
						{
							obj2 = "Result=null";
						}
						obj[3] = obj2;
						log12.LogInfo((object)string.Format("[{0}] LoadAssetAsync<IAssetBundleResource>('{1}') Status={2} {3}", obj));
					}
					if ((int)val2.Status == 1 && val2.Result != null)
					{
						AssetBundle assetBundle2 = val2.Result.GetAssetBundle();
						if ((Object)(object)assetBundle2 != (Object)null)
						{
							ManualLogSource log13 = Plugin.Log;
							if (log13 != null)
							{
								log13.LogInfo((object)("[" + logTag + "]   bundle 名: '" + ((Object)assetBundle2).name + "'"));
							}
							DumpBundleAssets(assetBundle2, matcher, logTag);
						}
					}
				}
				catch (Exception ex2)
				{
					ManualLogSource log14 = Plugin.Log;
					if (log14 != null)
					{
						log14.LogWarning((object)("[" + logTag + "] 场景 address 加载 bundle 异常: " + ex2.Message));
					}
				}
				ManualLogSource log15 = Plugin.Log;
				if (log15 != null)
				{
					log15.LogInfo((object)("[" + logTag + "] --- 4. 尝试直接 LoadBundleWithDeps ---"));
				}
				AssetBundle val3 = LoadBundleWithDeps(sceneBundleKey, logTag);
				if ((Object)(object)val3 != (Object)null)
				{
					ManualLogSource log16 = Plugin.Log;
					if (log16 != null)
					{
						log16.LogInfo((object)("[" + logTag + "]   LoadBundleWithDeps 成功: '" + ((Object)val3).name + "'"));
					}
					DumpBundleAssets(val3, matcher, logTag);
				}
				else
				{
					ManualLogSource log17 = Plugin.Log;
					if (log17 != null)
					{
						log17.LogWarning((object)("[" + logTag + "]   LoadBundleWithDeps 失败 (返回 null)"));
					}
				}
				ManualLogSource log18 = Plugin.Log;
				if (log18 != null)
				{
					log18.LogInfo((object)("[" + logTag + "] --- 5. 尝试 AssetBundle.LoadFromFile 直接读磁盘 ---"));
				}
				try
				{
					string text2 = Application.streamingAssetsPath + "/aa/StandaloneWindows64";
					string[] array = new string[3]
					{
						text2 + "/scenes_scenes_scenes/aspid_01.bundle",
						text2 + "/" + sceneBundleKey,
						text2 + "/aspid_01.bundle"
					};
					string[] array2 = array;
					foreach (string text3 in array2)
					{
						ManualLogSource log19 = Plugin.Log;
						if (log19 != null)
						{
							log19.LogInfo((object)$"[{logTag}]   检查磁盘路径: {text3} exists={File.Exists(text3)}");
						}
						if (File.Exists(text3))
						{
							AssetBundle val4 = AssetBundle.LoadFromFile(text3);
							ManualLogSource log20 = Plugin.Log;
							if (log20 != null)
							{
								log20.LogInfo((object)("[" + logTag + "]   LoadFromFile 结果: " + (((Object)(object)val4 == (Object)null) ? "null" : ((Object)val4).name)));
							}
							if ((Object)(object)val4 != (Object)null)
							{
								DumpBundleAssets(val4, matcher, logTag);
								val4.Unload(false);
							}
						}
					}
				}
				catch (Exception ex3)
				{
					ManualLogSource log21 = Plugin.Log;
					if (log21 != null)
					{
						log21.LogWarning((object)("[" + logTag + "] LoadFromFile 异常: " + ex3.Message));
					}
				}
				ManualLogSource log22 = Plugin.Log;
				if (log22 != null)
				{
					log22.LogInfo((object)("[" + logTag + "] ===== F4 场景提取诊断结束 ====="));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log23 = Plugin.Log;
				if (log23 != null)
				{
					log23.LogError((object)$"[{logTag}] DumpSceneExtractDiagnostics 异常: {arg}");
				}
			}
		}

		private static void DumpBundleAssets(AssetBundle bundle, Func<GameObject, bool> matcher, string logTag)
		{
			try
			{
				Object[] array = bundle.LoadAllAssets();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[{logTag}]   bundle '{((Object)bundle).name}' LoadAllAssets 总数: {array.Length}");
				}
				int num = 0;
				int num2 = 0;
				List<GameObject> list = new List<GameObject>();
				Object[] array2 = array;
				foreach (Object val in array2)
				{
					if (!(val == (Object)null))
					{
						GameObject val2 = (GameObject)(object)((val is GameObject) ? val : null);
						if (val2 != null)
						{
							num++;
							list.Add(val2);
						}
						else
						{
							num2++;
						}
					}
				}
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[{logTag}]   GameObject 资产: {num} 个,其他资产: {num2} 个");
				}
				foreach (GameObject item in list.Take(80))
				{
					bool flag = false;
					try
					{
						flag = matcher(item);
					}
					catch
					{
					}
					if (flag)
					{
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogInfo((object)("[" + logTag + "]   ★命中★ GameObject: '" + ((Object)item).name + "' components=" + string.Join(",", Array.ConvertAll(item.GetComponents<Component>(), (Component c) => ((object)c).GetType().Name))));
						}
					}
					else
					{
						ManualLogSource log4 = Plugin.Log;
						if (log4 != null)
						{
							log4.LogInfo((object)$"[{logTag}]   GameObject: '{((Object)item).name}' hit={flag}");
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("[" + logTag + "] DumpBundleAssets 异常: " + ex.Message));
				}
			}
		}

		public static GameObject ExtractSceneObjectAsTemplate(string bundleName, Func<GameObject, bool> matcher, string logTag = "ChainFixer")
		{
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Invalid comparison between Unknown and I4
			try
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[" + logTag + "] 从 bundle " + bundleName + " 提取模板"));
				}
				AssetBundle val = null;
				string text = bundleName;
				int num = text.LastIndexOf('/');
				if (num >= 0)
				{
					text = text.Substring(num + 1);
				}
				string text2 = Regex.Replace(text, "_[0-9a-fA-F]{32}\\.bundle$", ".bundle");
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[" + logTag + "] 遍历已加载 bundle,匹配名: '" + text2 + "' (来源 '" + bundleName + "')"));
				}
				foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
				{
					if (!((Object)(object)allLoadedAssetBundle == (Object)null))
					{
						bool flag = ((Object)allLoadedAssetBundle).name == text2 || ((Object)allLoadedAssetBundle).name.EndsWith("/" + text2, StringComparison.OrdinalIgnoreCase) || ((Object)allLoadedAssetBundle).name.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0;
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogInfo((object)$"[{logTag}]   已加载 bundle: '{((Object)allLoadedAssetBundle).name}' nameMatch={flag}");
						}
						if (flag)
						{
							val = allLoadedAssetBundle;
							break;
						}
					}
				}
				if ((Object)(object)val == (Object)null && (bundleName.IndexOf("/", StringComparison.Ordinal) >= 0 || bundleName.StartsWith("Scenes", StringComparison.OrdinalIgnoreCase)))
				{
					ManualLogSource log4 = Plugin.Log;
					if (log4 != null)
					{
						log4.LogInfo((object)("[" + logTag + "] 参数为场景 address,尝试 LoadAssetAsync<IAssetBundleResource> 直接取场景 bundle"));
					}
					try
					{
						AsyncOperationHandle<IAssetBundleResource> val2 = Addressables.LoadAssetAsync<IAssetBundleResource>((object)bundleName);
						val2.WaitForCompletion();
						ManualLogSource log5 = Plugin.Log;
						if (log5 != null)
						{
							log5.LogInfo((object)$"[{logTag}] LoadAssetAsync<IAssetBundleResource> Status={val2.Status}");
						}
						if ((int)val2.Status == 1 && val2.Result != null)
						{
							val = val2.Result.GetAssetBundle();
						}
					}
					catch (Exception ex)
					{
						ManualLogSource log6 = Plugin.Log;
						if (log6 != null)
						{
							log6.LogWarning((object)("[" + logTag + "] 场景 address 加载 bundle 异常: " + ex.Message));
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log7 = Plugin.Log;
					if (log7 != null)
					{
						log7.LogInfo((object)("[" + logTag + "] 尝试 LoadBundleWithDeps 加载"));
					}
					val = LoadBundleWithDeps(bundleName, logTag);
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log8 = Plugin.Log;
					if (log8 != null)
					{
						log8.LogInfo((object)("[" + logTag + "] 尝试 AssetBundle.LoadFromFile 磁盘直读"));
					}
					try
					{
						string text3 = Application.streamingAssetsPath + "/aa/StandaloneWindows64";
						string text4 = text2.Replace(".bundle", "_3f5daa59bb73e1ff0f6bb2d9a0e72e54.bundle");
						string[] array = new string[3]
						{
							text3 + "/scenes_scenes_scenes/" + text2,
							text3 + "/scenes_scenes_scenes/" + text4,
							text3 + "/" + text2
						};
						string[] array2 = array;
						foreach (string text5 in array2)
						{
							if (File.Exists(text5))
							{
								ManualLogSource log9 = Plugin.Log;
								if (log9 != null)
								{
									log9.LogInfo((object)("[" + logTag + "]   LoadFromFile: " + text5));
								}
								AssetBundle val3 = AssetBundle.LoadFromFile(text5);
								if ((Object)(object)val3 != (Object)null)
								{
									val = val3;
									break;
								}
							}
						}
					}
					catch (Exception ex2)
					{
						ManualLogSource log10 = Plugin.Log;
						if (log10 != null)
						{
							log10.LogWarning((object)("[" + logTag + "] LoadFromFile 异常: " + ex2.Message));
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log11 = Plugin.Log;
					if (log11 != null)
					{
						log11.LogWarning((object)("[" + logTag + "] bundle 加载失败: " + bundleName));
					}
					return null;
				}
				GameObject val4 = null;
				GameObject[] array3 = val.LoadAllAssets<GameObject>();
				ManualLogSource log12 = Plugin.Log;
				if (log12 != null)
				{
					log12.LogInfo((object)$"[{logTag}] bundle 内 GameObject 资产数: {array3.Length}");
				}
				GameObject[] array4 = array3;
				foreach (GameObject val5 in array4)
				{
					if (!((Object)(object)val5 == (Object)null) && matcher(val5))
					{
						val4 = val5;
						break;
					}
				}
				if ((Object)(object)val4 == (Object)null)
				{
					ManualLogSource log13 = Plugin.Log;
					if (log13 != null)
					{
						log13.LogWarning((object)$"[{logTag}] bundle {bundleName} 中未找到匹配对象 (GameObject资产={array3.Length})");
					}
					return null;
				}
				GameObject val6 = Object.Instantiate<GameObject>(val4);
				((Object)val6).name = ((Object)val4).name + " [Template]";
				Object.DontDestroyOnLoad((Object)(object)val6);
				ManualLogSource log14 = Plugin.Log;
				if (log14 != null)
				{
					log14.LogInfo((object)("[" + logTag + "] 模板提取成功: " + ((Object)val6).name + "(源自 bundle " + bundleName + ",未加载场景)"));
				}
				return val6;
			}
			catch (Exception arg)
			{
				ManualLogSource log15 = Plugin.Log;
				if (log15 != null)
				{
					log15.LogError((object)$"[{logTag}] ExtractSceneObjectAsTemplate 异常: {arg}");
				}
				return null;
			}
		}

		public static GameObject LoadPrefabFixed(string bundleName, string prefabPath, string logTag = "ChainFixer")
		{
			string key = bundleName + "|" + prefabPath;
			if (_prefabCache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[" + logTag + "] prefab 缓存命中: " + prefabPath));
				}
				return value;
			}
			AssetBundle val = LoadBundleWithDeps(bundleName, logTag);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			List<RuntimeAnimatorController> loadedCtrls = WarmupBundle(val, logTag);
			GameObject val2 = val.LoadAsset<GameObject>(prefabPath);
			if ((Object)(object)val2 == (Object)null)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[" + logTag + "] prefab 加载失败: " + prefabPath));
				}
				return null;
			}
			ManualLogSource log3 = Plugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)("[" + logTag + "] prefab 加载成功: " + ((Object)val2).name));
			}
			FixAnimatorControllers(val2, loadedCtrls, logTag);
			_prefabCache[key] = val2;
			return val2;
		}

		public static string ReportSpriteState(GameObject root)
		{
			StringBuilder stringBuilder = new StringBuilder();
			SpriteRenderer[] componentsInChildren = root.GetComponentsInChildren<SpriteRenderer>(true);
			foreach (SpriteRenderer val in componentsInChildren)
			{
				string text = (((Object)(object)val.sprite != (Object)null) ? ((Object)val.sprite).name : "null");
				string text2 = "";
				if ((Object)(object)val.sprite != (Object)null)
				{
					text2 = (((Object)(object)val.sprite.texture != (Object)null) ? ((Object)val.sprite.texture).name : "noTex");
					text2 += (((Object)(object)val.sprite.texture != (Object)null) ? $"({((Texture)val.sprite.texture).width}x{((Texture)val.sprite.texture).height})" : "");
				}
				stringBuilder.AppendLine("  SpriteRenderer '" + ((Object)((Component)val).gameObject).name + "': sprite=" + text + " texture=" + text2);
			}
			return stringBuilder.ToString();
		}

		public static tk2dSpriteCollectionData FindSpriteCollection(string collectionName, string logTag = "ChainFixer")
		{
			tk2dSpriteCollectionData[] array = Resources.FindObjectsOfTypeAll<tk2dSpriteCollectionData>();
			foreach (tk2dSpriteCollectionData val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == collectionName)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)$"[{logTag}] 找到 sprite collection: '{collectionName}' sprites={val.Count}");
					}
					return val;
				}
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogWarning((object)("[" + logTag + "] 未找到 sprite collection: '" + collectionName + "'"));
			}
			return null;
		}

		public static BundleType DetectBundleType(AssetBundle bundle, string logTag = "ChainFixer")
		{
			if ((Object)(object)bundle == (Object)null)
			{
				return BundleType.Unknown;
			}
			try
			{
				Object[] array = bundle.LoadAllAssets();
				int num = array.Length;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[{logTag}] bundle '{((Object)bundle).name}' 是普通 bundle,LoadAllAssets={num} 个资产");
				}
				return BundleType.Normal;
			}
			catch (InvalidOperationException)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[" + logTag + "] bundle '" + ((Object)bundle).name + "' 是 streamed scene bundle(LoadAllAssets 抛异常)"));
				}
				return BundleType.StreamedScene;
			}
			catch (Exception ex2)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("[" + logTag + "] bundle '" + ((Object)bundle).name + "' 类型检测异常: " + ex2.Message));
				}
				return BundleType.Unknown;
			}
		}

		public static GameObject ExtractFromSceneBundle(string bundleName, Func<GameObject, bool> matcher, string logTag = "ChainFixer")
		{
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Invalid comparison between Unknown and I4
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_047f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[" + logTag + "] 从 streamed scene bundle 提取对象: " + bundleName));
			}
			string text = ExtractSceneNameFromBundle(bundleName);
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[" + logTag + "] 推断场景名: '" + text + "'"));
			}
			List<string> list = new List<string>();
			foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators)
			{
				foreach (object key in resourceLocator.Keys)
				{
					if (key is string text2 && text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						list.Add(text2);
					}
				}
			}
			ManualLogSource log3 = Plugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)string.Format("[{0}] locator 中匹配的 key ({1}): {2}", logTag, list.Count, string.Join(" | ", list.Take(20))));
			}
			foreach (string item in list)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)("[" + logTag + "] 尝试 LoadResourceLocations: '" + item + "'"));
				}
				try
				{
					AsyncOperationHandle<IList<IResourceLocation>> val = Addressables.LoadResourceLocationsAsync((object)item, typeof(SceneInstance));
					val.WaitForCompletion();
					if (val.Result != null && val.Result.Count > 0)
					{
						ManualLogSource log5 = Plugin.Log;
						if (log5 != null)
						{
							log5.LogInfo((object)$"[{logTag}] LoadResourceLocations 命中 {val.Result.Count} 个");
						}
						foreach (IResourceLocation item2 in val.Result)
						{
							ManualLogSource log6 = Plugin.Log;
							if (log6 != null)
							{
								log6.LogInfo((object)("[" + logTag + "]   location: InternalId='" + item2.InternalId + "' PrimaryKey='" + item2.PrimaryKey + "'"));
							}
						}
						AsyncOperationHandle<SceneInstance> val2 = Addressables.LoadSceneAsync((object)item, (LoadSceneMode)1, true, 100, (SceneReleaseMode)0);
						try
						{
							val2.WaitForCompletion();
						}
						catch (Exception ex)
						{
							ManualLogSource log7 = Plugin.Log;
							if (log7 != null)
							{
								log7.LogWarning((object)("[" + logTag + "] WaitForCompletion 异常: " + ex.Message));
							}
						}
						if ((int)val2.Status == 1)
						{
							SceneInstance result = val2.Result;
							Scene scene = ((SceneInstance)(ref result)).Scene;
							ManualLogSource log8 = Plugin.Log;
							if (log8 != null)
							{
								log8.LogInfo((object)$"[{logTag}] 场景加载成功: '{((Scene)(ref scene)).name}' rootObjects={((Scene)(ref scene)).rootCount}");
							}
							GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
							int num = 0;
							GameObject val3 = null;
							GameObject[] array = rootGameObjects;
							foreach (GameObject val4 in array)
							{
								Transform[] componentsInChildren = val4.GetComponentsInChildren<Transform>(true);
								foreach (Transform val5 in componentsInChildren)
								{
									num++;
									if (((Component)val5).gameObject.activeSelf || ((Component)val5).gameObject.activeInHierarchy)
									{
										bool flag = false;
										try
										{
											flag = matcher(((Component)val5).gameObject);
										}
										catch
										{
										}
										if (flag)
										{
											val3 = ((Component)val5).gameObject;
											break;
										}
									}
								}
								if ((Object)(object)val3 != (Object)null)
								{
									break;
								}
							}
							ManualLogSource log9 = Plugin.Log;
							if (log9 != null)
							{
								log9.LogInfo((object)$"[{logTag}] 场景内扫描: {num} 个活跃对象, 命中={(Object)(object)val3 != (Object)null}");
							}
							if ((Object)(object)val3 != (Object)null)
							{
								GameObject val6 = Object.Instantiate<GameObject>(val3);
								((Object)val6).name = ((Object)val3).name + " [Extracted]";
								Object.DontDestroyOnLoad((Object)(object)val6);
								ManualLogSource log10 = Plugin.Log;
								if (log10 != null)
								{
									log10.LogInfo((object)("[" + logTag + "] ★ 模板提取成功: " + ((Object)val6).name));
								}
								try
								{
									Addressables.UnloadSceneAsync(val2, true);
									ManualLogSource log11 = Plugin.Log;
									if (log11 != null)
									{
										log11.LogInfo((object)("[" + logTag + "] 场景已卸载"));
									}
								}
								catch (Exception ex2)
								{
									Plugin.Log.LogWarning((object)("[" + logTag + "] 场景卸载异常: " + ex2.Message));
								}
								return val6;
							}
							ManualLogSource log12 = Plugin.Log;
							if (log12 != null)
							{
								log12.LogInfo((object)("[" + logTag + "] 未命中,打印场景对象:"));
							}
							GameObject[] array2 = rootGameObjects;
							foreach (GameObject val7 in array2)
							{
								Component[] componentsInChildren2 = val7.GetComponentsInChildren<Component>(true);
								foreach (Component val8 in componentsInChildren2)
								{
									if (!(val8 is Transform) && !(val8 is MeshFilter))
									{
										ManualLogSource log13 = Plugin.Log;
										if (log13 != null)
										{
											log13.LogInfo((object)("[" + logTag + "]   '" + ((Object)val8.gameObject).name + "' → " + ((object)val8).GetType().Name));
										}
									}
								}
							}
							try
							{
								Addressables.UnloadSceneAsync(val2, true);
							}
							catch
							{
							}
							continue;
						}
						ManualLogSource log14 = Plugin.Log;
						if (log14 != null)
						{
							log14.LogWarning((object)$"[{logTag}] 场景加载失败: Status={val2.Status}");
						}
						try
						{
							if (val2.IsValid())
							{
								Addressables.Release<SceneInstance>(val2);
							}
						}
						catch
						{
						}
					}
					else
					{
						ManualLogSource log15 = Plugin.Log;
						if (log15 != null)
						{
							log15.LogInfo((object)("[" + logTag + "] LoadResourceLocations 无结果"));
						}
					}
				}
				catch (Exception ex3)
				{
					Plugin.Log.LogWarning((object)("[" + logTag + "] key '" + item + "' 加载异常: " + ex3.Message));
				}
			}
			ManualLogSource log16 = Plugin.Log;
			if (log16 != null)
			{
				log16.LogWarning((object)("[" + logTag + "] 所有 key 尝试完毕,未成功提取"));
			}
			return null;
		}

		private static string ExtractSceneNameFromBundle(string bundleName)
		{
			string text = bundleName;
			int num = text.LastIndexOf('/');
			if (num >= 0)
			{
				text = text.Substring(num + 1);
			}
			text = BundleSuffixRegex.Replace(text, "");
			if (text.EndsWith(".bundle", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(0, text.Length - 7);
			}
			int num2 = text.IndexOf('_');
			if (num2 > 0)
			{
				text = text.Substring(num2 + 1);
			}
			int num3 = text.LastIndexOf('_');
			if (num3 > 0 && text.Length - num3 == 33)
			{
				text = text.Substring(0, num3);
			}
			return text;
		}

		public static List<Object> ProbeBundleAssets(AssetBundle bundle, Func<Object, bool> matcher = null, string logTag = "ChainFixer")
		{
			List<Object> list = new List<Object>();
			if ((Object)(object)bundle == (Object)null)
			{
				return list;
			}
			switch (DetectBundleType(bundle, logTag))
			{
			case BundleType.Normal:
			{
				Object[] array = bundle.LoadAllAssets();
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[{logTag}] 普通 bundle '{((Object)bundle).name}' 全量资产: {array.Length}");
				}
				Object[] array2 = array;
				foreach (Object val in array2)
				{
					if (val == (Object)null)
					{
						continue;
					}
					bool flag = matcher?.Invoke(val) ?? false;
					if (flag)
					{
						list.Add(val);
					}
					GameObject val2 = (GameObject)(object)((val is GameObject) ? val : null);
					if (val2 != null)
					{
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogInfo((object)string.Format("[{0}]   GO: '{1}' components=[{2}] hit={3}", logTag, ((Object)val2).name, string.Join(",", Array.ConvertAll(val2.GetComponents<Component>(), (Component c) => ((object)c)?.GetType().Name ?? "?")), flag));
						}
					}
					else
					{
						ManualLogSource log4 = Plugin.Log;
						if (log4 != null)
						{
							log4.LogInfo((object)$"[{logTag}]   Asset: '{val.name}' type={((object)val).GetType().Name} hit={flag}");
						}
					}
				}
				break;
			}
			case BundleType.StreamedScene:
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[" + logTag + "] streamed scene bundle '" + ((Object)bundle).name + "' → 需要通过加载场景访问内容"));
				}
				break;
			}
			}
			return list;
		}

		public static bool SetSpriteFromCollection(tk2dSprite sprite, tk2dSpriteCollectionData collection, string spriteName, string logTag = "ChainFixer")
		{
			if ((Object)(object)sprite == (Object)null || (Object)(object)collection == (Object)null)
			{
				return false;
			}
			int spriteIdByName = collection.GetSpriteIdByName(spriteName);
			if (spriteIdByName < 0)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[" + logTag + "] collection '" + ((Object)collection).name + "' 中未找到 sprite: '" + spriteName + "'"));
				}
				return false;
			}
			((tk2dBaseSprite)sprite).SetSprite(collection, spriteIdByName);
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[" + logTag + "] sprite 设置成功: '" + spriteName + "' (collection='" + ((Object)collection).name + "')"));
			}
			return true;
		}

		public static GameObject CreateTemplate(string name, Action<GameObject> builder, string logTag = "ChainFixer")
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.SetActive(false);
			try
			{
				builder(val);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[" + logTag + "] CreateTemplate builder 异常: " + ex.Message));
				}
			}
			Object.DontDestroyOnLoad((Object)(object)val);
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[" + logTag + "] 模板创建完成: '" + name + "'"));
			}
			return val;
		}

		public static tk2dSpriteCollectionData LoadTk2dCollectionBundle(string logTag = "ChainFixer")
		{
			if ((Object)(object)_cachedCoinRocksCollection != (Object)null)
			{
				return _cachedCoinRocksCollection;
			}
			if (_coinRocksLoadAttempted)
			{
				return null;
			}
			_coinRocksLoadAttempted = true;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[" + logTag + "] 搜索全内存 tk2dSpriteCollectionData..."));
			}
			tk2dSpriteCollectionData[] array = Resources.FindObjectsOfTypeAll<tk2dSpriteCollectionData>();
			foreach (tk2dSpriteCollectionData val in array)
			{
				if ((Object)(object)val == (Object)null || val.spriteDefinitions == null)
				{
					continue;
				}
				for (int j = 0; j < val.spriteDefinitions.Length; j++)
				{
					if (val.spriteDefinitions[j] != null && val.spriteDefinitions[j].name == "rosary_rock_type_020000")
					{
						_cachedCoinRocksCollection = val;
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogInfo((object)$"[{logTag}] ★ 找到 Coin Rocks collection: sprites={val.spriteDefinitions.Length} target_index={j}");
						}
						return _cachedCoinRocksCollection;
					}
				}
			}
			ManualLogSource log3 = Plugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)("[" + logTag + "] 全内存未命中,遍历已加载 bundle..."));
			}
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				if ((Object)(object)allLoadedAssetBundle == (Object)null)
				{
					continue;
				}
				try
				{
					tk2dSpriteCollectionData[] array2 = allLoadedAssetBundle.LoadAllAssets<tk2dSpriteCollectionData>();
					tk2dSpriteCollectionData[] array3 = array2;
					foreach (tk2dSpriteCollectionData val2 in array3)
					{
						if ((Object)(object)val2 == (Object)null || val2.spriteDefinitions == null)
						{
							continue;
						}
						for (int l = 0; l < val2.spriteDefinitions.Length; l++)
						{
							if (val2.spriteDefinitions[l] != null && val2.spriteDefinitions[l].name == "rosary_rock_type_020000")
							{
								_cachedCoinRocksCollection = val2;
								ManualLogSource log4 = Plugin.Log;
								if (log4 != null)
								{
									log4.LogInfo((object)$"[{logTag}] ★ 从 bundle '{((Object)allLoadedAssetBundle).name}' 找到 Coin Rocks collection: sprites={val2.spriteDefinitions.Length}");
								}
								return _cachedCoinRocksCollection;
							}
						}
					}
				}
				catch
				{
				}
			}
			ManualLogSource log5 = Plugin.Log;
			if (log5 != null)
			{
				log5.LogWarning((object)("[" + logTag + "] 全内存+全 bundle 搜索均未找到 Coin Rocks collection"));
			}
			return null;
		}

		public static void RunDemoSpawn()
		{
			try
			{
				Transform val = UIManagerFindCanvas();
				GameObject val2 = SpawnWithFullChain("prompts_assets_all.bundle", "Assets/Prefabs/UI/Messages/UI Msg Crest Evolve.prefab", ((Object)(object)val != (Object)null) ? ((Component)val).transform : null, "F5Demo");
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[F5Demo] 修复流程失败");
					}
					return;
				}
				val2.SetActive(true);
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("[F5Demo] 实例化成功: " + ((Object)val2).name));
				}
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("[F5Demo] " + ReportSpriteState(val2)));
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)$"[F5Demo] 异常: {arg}");
				}
			}
		}

		private static Transform UIManagerFindCanvas()
		{
			try
			{
				Type type = Type.GetType("UIManager, Assembly-CSharp");
				if (type != null)
				{
					Object val = Object.FindObjectOfType(type);
					if (val != (Object)null)
					{
						PropertyInfo property = type.GetProperty("UICanvas");
						if (property != null)
						{
							object? value = property.GetValue(val);
							Canvas val2 = (Canvas)((value is Canvas) ? value : null);
							if (val2 != null)
							{
								return ((Component)val2).transform;
							}
						}
					}
				}
			}
			catch
			{
			}
			Canvas[] array = Resources.FindObjectsOfTypeAll<Canvas>();
			foreach (Canvas val3 in array)
			{
				if ((Object)(object)val3 != (Object)null && !val3.overrideSorting)
				{
					return ((Component)val3).transform;
				}
			}
			return null;
		}

		public static void StartNativeClipPlay(GameObject go, string logTag = "原生采样")
		{
			if (!((Object)(object)go == (Object)null))
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(NativeClipCoroutine(go, logTag));
			}
		}

		private static IEnumerator NativeClipCoroutine(GameObject go, string logTag)
		{
			int fsmCount = 0;
			PlayMakerFSM[] componentsInChildren = go.GetComponentsInChildren<PlayMakerFSM>(true);
			foreach (PlayMakerFSM f in componentsInChildren)
			{
				((Behaviour)f).enabled = false;
				fsmCount++;
			}
			int animCount = 0;
			Animator[] componentsInChildren2 = go.GetComponentsInChildren<Animator>(true);
			foreach (Animator a in componentsInChildren2)
			{
				((Behaviour)a).enabled = false;
				animCount++;
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[{logTag}] 已禁用 FSM x{fsmCount} Animator x{animCount}");
			}
			Animator anim = null;
			Animator[] componentsInChildren3 = go.GetComponentsInChildren<Animator>(true);
			foreach (Animator a2 in componentsInChildren3)
			{
				if ((Object)(object)a2.runtimeAnimatorController != (Object)null)
				{
					anim = a2;
					break;
				}
			}
			if ((Object)(object)anim == (Object)null)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[" + logTag + "] 无 Animator"));
				}
				yield break;
			}
			RuntimeAnimatorController controller = anim.runtimeAnimatorController;
			AnimationClip clip = null;
			string clipName = "";
			try
			{
				AnimationClip[] clips = controller.animationClips;
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("[" + logTag + "] controller=" + ((Object)controller).name + " clips=" + ((clips == null) ? "null" : clips.Length.ToString())));
				}
				if (clips != null && clips.Length != 0)
				{
					clip = clips[0];
					clipName = (((Object)(object)clip != (Object)null) ? $"{((Object)clip).name} len={clip.length}" : "null");
				}
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)("[" + logTag + "] 取 clip 异常: " + ex2.Message));
				}
			}
			ManualLogSource log5 = Plugin.Log;
			if (log5 != null)
			{
				log5.LogInfo((object)("[" + logTag + "] clip0 = " + clipName));
			}
			Transform lvl1 = go.transform.Find("Tool_Socket_Evolve_lvl1");
			if ((Object)(object)lvl1 == (Object)null)
			{
				ManualLogSource log6 = Plugin.Log;
				if (log6 != null)
				{
					log6.LogWarning((object)("[" + logTag + "] 找不到 lvl1"));
				}
				yield break;
			}
			Transform icon = lvl1.Find("Pivot/Icon");
			SpriteRenderer srIcon = (((Object)(object)icon != (Object)null) ? ((Component)icon).GetComponent<SpriteRenderer>() : null);
			if ((Object)(object)clip == (Object)null)
			{
				ManualLogSource log7 = Plugin.Log;
				if (log7 != null)
				{
					log7.LogWarning((object)("[" + logTag + "] clip 为空,回退手动演出"));
				}
				yield return ManualPlayCoroutine(go, logTag);
				yield break;
			}
			AnimationEvent[] evts = clip.events;
			if (evts != null && evts.Length != 0)
			{
				Array.Sort(evts, (AnimationEvent val, AnimationEvent b) => val.time.CompareTo(b.time));
				ManualLogSource log8 = Plugin.Log;
				if (log8 != null)
				{
					log8.LogInfo((object)("[" + logTag + "] 事件表: " + string.Join(", ", Array.ConvertAll(evts, (AnimationEvent e) => $"{e.functionName}@{e.time:F2}s"))));
				}
			}
			float t = 0f;
			float dur = Mathf.Max(0.1f, clip.length);
			int evtIdx = 0;
			while (t < dur)
			{
				clip.SampleAnimation(((Component)anim).gameObject, t);
				if (evts != null)
				{
					for (; evtIdx < evts.Length && t >= evts[evtIdx].time; evtIdx++)
					{
						string fn = evts[evtIdx].functionName;
						ManualLogSource log9 = Plugin.Log;
						if (log9 != null)
						{
							log9.LogInfo((object)$"[{logTag}] 事件@{t:F2}s: {fn}");
						}
						((Component)anim).gameObject.SendMessage(fn, (SendMessageOptions)1);
						if ((Object)(object)go != (Object)null && (Object)(object)go != (Object)(object)((Component)anim).gameObject)
						{
							go.SendMessage(fn, (SendMessageOptions)1);
						}
					}
				}
				t += Time.deltaTime;
				yield return null;
			}
			clip.SampleAnimation(((Component)anim).gameObject, dur - 0.001f);
			string spriteAtEnd = (((Object)(object)srIcon != (Object)null && (Object)(object)srIcon.sprite != (Object)null) ? ((Object)srIcon.sprite).name : "nullSprite");
			ManualLogSource log10 = Plugin.Log;
			if (log10 != null)
			{
				log10.LogInfo((object)$"[{logTag}] 采样完成 dur={dur:F2} 终帧Icon={spriteAtEnd}");
			}
			yield return (object)new WaitForSeconds(1f);
			Object.Destroy((Object)(object)go);
		}

		public static Sprite FindLoadedSprite(string name)
		{
			if (_spriteCache != null && _spriteCache.TryGetValue(name, out var value))
			{
				return value;
			}
			if (_spriteCache == null)
			{
				_spriteCache = new Dictionary<string, Sprite>();
			}
			Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>();
			foreach (Sprite val in array)
			{
				if (!((Object)(object)val == (Object)null) && !(((Object)val).name != name))
				{
					_spriteCache[name] = val;
					return val;
				}
			}
			_spriteCache[name] = null;
			return null;
		}

		public static void StartManualPlay(GameObject go, string logTag = "手动演出")
		{
			if (!((Object)(object)go == (Object)null))
			{
				((MonoBehaviour)Plugin.Instance).StartCoroutine(ManualPlayCoroutine(go, logTag));
			}
		}

		private static IEnumerator ManualPlayCoroutine(GameObject go, string logTag)
		{
			int disabled = 0;
			Animator[] componentsInChildren = go.GetComponentsInChildren<Animator>(true);
			foreach (Animator a in componentsInChildren)
			{
				((Behaviour)a).enabled = false;
				disabled++;
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"[{logTag}] 已禁用 Animator x{disabled}");
			}
			int fsmCount = 0;
			PlayMakerFSM[] componentsInChildren2 = go.GetComponentsInChildren<PlayMakerFSM>(true);
			foreach (PlayMakerFSM f in componentsInChildren2)
			{
				((Behaviour)f).enabled = false;
				fsmCount++;
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"[{logTag}] 已禁用 PlayMakerFSM x{fsmCount}");
			}
			Transform lvl1 = go.transform.Find("Tool_Socket_Evolve_lvl1");
			if ((Object)(object)lvl1 == (Object)null)
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)("[" + logTag + "] 找不到 Tool_Socket_Evolve_lvl1"));
				}
				yield break;
			}
			Transform icon = lvl1.Find("Pivot/Icon");
			Transform iconGlow = lvl1.Find("Pivot/Icon_Glow");
			Transform crest = lvl1.Find("Pivot/Crest");
			Transform crestGlow = lvl1.Find("Pivot/Crest_Glow");
			Transform flash = lvl1.Find("white_flash");
			Transform burst = lvl1.Find("evolve_burst");
			Transform loop = lvl1.Find("evolve_loop");
			Transform bg = go.transform.Find("BG");
			SpriteRenderer srIcon = GetSR(icon);
			SpriteRenderer srIconGlow = GetSR(iconGlow);
			SpriteRenderer srCrest = GetSR(crest);
			SpriteRenderer srCrestGlow = GetSR(crestGlow);
			SpriteRenderer srFlash = GetSR(flash);
			SpriteRenderer srBG = GetSR(bg);
			Sprite sprSingle = FindLoadedSprite("UI_tool_slot_extra_sockets_single");
			Sprite sprTiny = FindLoadedSprite("UI_tool_slot_extra_sockets_0000_filled_tiny");
			Sprite sprGlow = FindLoadedSprite("UI_tool_slot_extra_sockets_0000_filled_glow");
			Sprite sprIcon = FindLoadedSprite("hornet_prompts_tool_sockets_0001_explorer_socket");
			sprSingle = snap(srCrest, sprSingle);
			sprTiny = snap(srCrest, sprTiny);
			sprGlow = snap(srCrestGlow, sprGlow);
			sprIcon = snap(srIcon, sprIcon);
			ManualLogSource log4 = Plugin.Log;
			if (log4 != null)
			{
				string[] obj = new string[12]
				{
					"[", logTag, "] sprite: single=", null, null, null, null, null, null, null,
					null, null
				};
				Sprite obj2 = sprSingle;
				obj[3] = ((obj2 != null) ? ((Object)obj2).name : null) ?? "null";
				obj[4] = " tiny=";
				Sprite obj3 = sprTiny;
				obj[5] = ((obj3 != null) ? ((Object)obj3).name : null) ?? "null";
				obj[6] = " glow=";
				Sprite obj4 = sprGlow;
				obj[7] = ((obj4 != null) ? ((Object)obj4).name : null) ?? "null";
				obj[8] = " icon=";
				Sprite obj5 = sprIcon;
				obj[9] = ((obj5 != null) ? ((Object)obj5).name : null) ?? "null";
				obj[10] = " bg=";
				object obj6;
				if (srBG == null)
				{
					obj6 = null;
				}
				else
				{
					Sprite sprite = srBG.sprite;
					obj6 = ((sprite != null) ? ((Object)sprite).name : null);
				}
				if (obj6 == null)
				{
					obj6 = "null";
				}
				obj[11] = (string)obj6;
				log4.LogInfo((object)string.Concat(obj));
			}
			ParticleSystem psBurst = (((Object)(object)burst != (Object)null) ? ((Component)burst).GetComponent<ParticleSystem>() : null);
			ParticleSystem psLoop = (((Object)(object)loop != (Object)null) ? ((Component)loop).GetComponent<ParticleSystem>() : null);
			if ((Object)(object)psBurst != (Object)null)
			{
				EmissionModule e = psBurst.emission;
				((EmissionModule)(ref e)).enabled = false;
				e = default(EmissionModule);
			}
			if ((Object)(object)psLoop != (Object)null)
			{
				EmissionModule e2 = psLoop.emission;
				((EmissionModule)(ref e2)).enabled = false;
				psLoop.Stop(true, (ParticleSystemStopBehavior)0);
				e2 = default(EmissionModule);
			}
			if ((Object)(object)srBG != (Object)null)
			{
				srBG.color = new Color(0f, 0f, 0f, 0f);
				bg.SetAsFirstSibling();
			}
			if ((Object)(object)srIcon != (Object)null)
			{
				srIcon.sprite = sprIcon;
				srIcon.color = new Color(1f, 1f, 1f, 0f);
			}
			if ((Object)(object)srIconGlow != (Object)null)
			{
				srIconGlow.color = new Color(1f, 1f, 1f, 0f);
			}
			if ((Object)(object)srCrest != (Object)null)
			{
				srCrest.sprite = sprSingle;
				srCrest.color = new Color(1f, 1f, 1f, 0f);
			}
			if ((Object)(object)srCrestGlow != (Object)null)
			{
				srCrestGlow.sprite = sprGlow;
				srCrestGlow.color = new Color(1f, 1f, 1f, 0f);
			}
			if ((Object)(object)srFlash != (Object)null)
			{
				srFlash.color = new Color(1f, 1f, 1f, 0f);
			}
			crest.localScale = Vector3.one * 0.4f;
			float t = 0f;
			float bgIn = 0.28f;
			while (t < 0.58000004f)
			{
				t += Time.deltaTime;
				float kb = Mathf.Clamp01(t / bgIn) * 0.85f;
				if ((Object)(object)srBG != (Object)null)
				{
					srBG.color = new Color(0f, 0f, 0f, kb);
				}
				float ki = Mathf.Clamp01((t - 0.05f) / 0.22f);
				if ((Object)(object)srIcon != (Object)null)
				{
					srIcon.color = new Color(1f, 1f, 1f, ki);
				}
				if ((Object)(object)srIconGlow != (Object)null)
				{
					srIconGlow.color = new Color(1f, 1f, 1f, ki * 0.5f);
				}
				yield return null;
			}
			while (t < 1f)
			{
				t += Time.deltaTime;
				float k = Mathf.Clamp01((t - 0.58f) / 0.42f);
				float e3 = 1f - Mathf.Pow(1f - k, 3f);
				crest.localScale = Vector3.one * Mathf.Lerp(0.4f, 1.12f, e3);
				if ((Object)(object)srCrest != (Object)null)
				{
					srCrest.color = new Color(1f, 1f, 1f, e3);
				}
				if ((Object)(object)srCrestGlow != (Object)null)
				{
					srCrestGlow.color = new Color(1f, 1f, 1f, e3);
					((Component)srCrestGlow).transform.localScale = Vector3.one * Mathf.Lerp(2.2f, 2.8f, e3);
				}
				yield return null;
			}
			if ((Object)(object)srCrest != (Object)null && (Object)(object)sprTiny != (Object)null)
			{
				srCrest.sprite = sprTiny;
			}
			yield return (object)new WaitForSeconds(0.12f);
			if ((Object)(object)srCrest != (Object)null && (Object)(object)sprGlow != (Object)null)
			{
				srCrest.sprite = sprGlow;
			}
			if ((Object)(object)psBurst != (Object)null)
			{
				psBurst.Play();
			}
			if ((Object)(object)srFlash != (Object)null)
			{
				float ft = 0f;
				while (ft < 0.22f)
				{
					ft += Time.deltaTime;
					float k2 = ((ft < 0.07f) ? (ft / 0.07f) : (1f - (ft - 0.07f) / 0.15f));
					srFlash.color = new Color(1f, 1f, 1f, Mathf.Clamp01(k2) * 0.95f);
					yield return null;
				}
				srFlash.color = new Color(1f, 1f, 1f, 0f);
			}
			if ((Object)(object)psBurst != (Object)null)
			{
				psBurst.Stop(true, (ParticleSystemStopBehavior)0);
			}
			yield return (object)new WaitForSeconds(1.2f);
			float ot = 0f;
			while (ot < 0.5f)
			{
				ot += Time.deltaTime;
				float k3 = 1f - Mathf.Clamp01(ot / 0.5f);
				if ((Object)(object)srBG != (Object)null && (Object)(object)srBG != (Object)null)
				{
					srBG.color = new Color(0f, 0f, 0f, 0.85f * k3);
				}
				if ((Object)(object)srIcon != (Object)null)
				{
					srIcon.color = new Color(1f, 1f, 1f, k3);
				}
				if ((Object)(object)srIconGlow != (Object)null)
				{
					srIconGlow.color = new Color(1f, 1f, 1f, k3 * 0.5f);
				}
				if ((Object)(object)srCrest != (Object)null)
				{
					srCrest.color = new Color(1f, 1f, 1f, k3);
				}
				if ((Object)(object)srCrestGlow != (Object)null)
				{
					srCrestGlow.color = new Color(1f, 1f, 1f, k3);
				}
				yield return null;
			}
			Object.Destroy((Object)(object)go);
			ManualLogSource log5 = Plugin.Log;
			if (log5 != null)
			{
				log5.LogInfo((object)("[" + logTag + "] 演出完成,已销毁"));
			}
			static SpriteRenderer GetSR(Transform val)
			{
				return ((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<SpriteRenderer>() : null;
			}
			static Sprite snap(SpriteRenderer sr, Sprite fallback)
			{
				if ((Object)(object)sr != (Object)null && (Object)(object)sr.sprite != (Object)null)
				{
					return sr.sprite;
				}
				return fallback;
			}
		}
	}
}

BepInEx/plugins/HKSilksong_SceneRandomizer.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using SilksongItemRandomizer;
using StartingAbilityPicker;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace HKSilksong_Randomizer;

public static class RoomMapGenerator
{
	private static readonly bool[,] letters;

	static RoomMapGenerator()
	{
		letters = new bool[128, 25];
		string[] array = new string[26]
		{
			"01110100011000111111000110001", "11110100011111010001100011111", "01110100011000010000100000111", "11110100011000110001100011110", "11111100001111010000100011111", "11111100001111010000100010000", "01110100011000010111100001111", "10001100011111110001100011000", "01110001000010000100001000111", "00111000100001000100011001100",
			"10001100101110010010100011000", "10000100001000010000100001111", "10001110111010110001100011000", "10001110011010110011100011000", "01110100011000110001100010111", "11110100011111010000100010000", "01110100011000110001101010101", "11110100011111010010100011001", "01111100000111000001100011110", "11111001000010000100001000010",
			"10001100011000110001100001110", "10001100011000101010001000100", "10001100011000110101101011010", "10001010100010001010100010001", "10001010100010000100001000010", "11111000100010001000100011111"
		};
		for (int i = 0; i < 26; i++)
		{
			string text = array[i];
			for (int j = 0; j < 25; j++)
			{
				letters[65 + i, j] = text[j] == '1';
			}
		}
		string[] array2 = new string[10] { "01110100011000110001100010111", "00100011000010000100001000111", "01110100010001000100010001111", "11110000111100000011100011110", "10001100111110000010000100010", "11111100001111000001100011111", "01110100001111010001100010111", "11111000010001000100001000010", "01110100011000101110100010111", "01110100011000101111000011110" };
		for (int k = 0; k < 10; k++)
		{
			string text2 = array2[k];
			for (int l = 0; l < 25; l++)
			{
				letters[48 + k, l] = text2[l] == '1';
			}
		}
		string text3 = "00000000000000000000011111";
		for (int m = 0; m < 25; m++)
		{
			letters[95, m] = text3[m] == '1';
		}
	}

	public static bool GenerateFromFile(string connectionsFilePath, string outputImagePath)
	{
		if (!File.Exists(connectionsFilePath))
		{
			Debug.LogWarning((object)("File not found: " + connectionsFilePath));
			return false;
		}
		string[] array = File.ReadAllLines(connectionsFilePath);
		Dictionary<string, HashSet<string>> dictionary = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
		string[] array2 = array;
		for (int i = 0; i < array2.Length; i++)
		{
			string text = array2[i]?.Trim();
			if (string.IsNullOrEmpty(text) || text.StartsWith("#"))
			{
				continue;
			}
			string[] array3 = text.Split(new char[1] { '|' });
			if (array3.Length != 4)
			{
				continue;
			}
			string text2 = array3[0];
			string text3 = array3[2];
			if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(text3))
			{
				if (!dictionary.ContainsKey(text2))
				{
					dictionary[text2] = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				}
				if (!dictionary.ContainsKey(text3))
				{
					dictionary[text3] = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				}
				dictionary[text2].Add(text3);
				dictionary[text3].Add(text2);
			}
		}
		if (dictionary.Count == 0)
		{
			Debug.LogWarning((object)"No connections found.");
			return false;
		}
		GenerateMapTexture(dictionary, outputImagePath);
		Debug.Log((object)("Map saved to " + outputImagePath));
		return true;
	}

	private static void GenerateMapTexture(Dictionary<string, HashSet<string>> graph, string outputPath)
	{
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: 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_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		int num = 250;
		int num2 = 120;
		int num3 = 100;
		int num4 = 80;
		List<string> list = graph.Keys.ToList();
		int num5 = (int)Math.Ceiling(Math.Sqrt(list.Count));
		int num6 = (int)Math.Ceiling((double)list.Count / (double)num5);
		int num7 = num5 * (num + num3) + num3;
		int num8 = num6 * (num2 + num4) + num4;
		Texture2D val = new Texture2D(num7, num8, (TextureFormat)4, false);
		Color[] array = (Color[])(object)new Color[num7 * num8];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = Color.black;
		}
		val.SetPixels(array);
		Dictionary<string, Vector2> dictionary = new Dictionary<string, Vector2>();
		int num9 = 0;
		int num10 = 0;
		foreach (string item in list)
		{
			dictionary[item] = new Vector2((float)(num3 + num9 * (num + num3)), (float)(num4 + num10 * (num2 + num4)));
			num9++;
			if (num9 >= num5)
			{
				num9 = 0;
				num10++;
			}
		}
		foreach (KeyValuePair<string, HashSet<string>> item2 in graph)
		{
			if (!dictionary.TryGetValue(item2.Key, out var value))
			{
				continue;
			}
			foreach (string item3 in item2.Value)
			{
				if (dictionary.TryGetValue(item3, out var value2))
				{
					DrawLine(val, (int)(value.x + (float)(num / 2)) + 2, (int)(value.y + (float)(num2 / 2)) + 2, (int)(value2.x + (float)(num / 2)) + 2, (int)(value2.y + (float)(num2 / 2)) + 2, Color.gray, 3);
				}
			}
		}
		foreach (KeyValuePair<string, Vector2> item4 in dictionary)
		{
			DrawEmptyRectangle(val, (int)item4.Value.x, (int)item4.Value.y, num, num2, Color.gray);
			DrawTextBitmap(val, (int)item4.Value.x + 10, (int)item4.Value.y + 35, item4.Key, Color.white);
		}
		val.Apply();
		string directoryName = Path.GetDirectoryName(outputPath);
		if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
		{
			Directory.CreateDirectory(directoryName);
		}
		File.WriteAllBytes(outputPath, ImageConversion.EncodeToPNG(val));
		Object.DestroyImmediate((Object)(object)val);
	}

	private static void DrawEmptyRectangle(Texture2D tex, int x, int y, int w, int h, Color color)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: 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)
		for (int i = x; i < x + w; i++)
		{
			if (i >= 0 && i < ((Texture)tex).width)
			{
				if (y >= 0 && y < ((Texture)tex).height)
				{
					tex.SetPixel(i, y, color);
				}
				if (y + h - 1 >= 0 && y + h - 1 < ((Texture)tex).height)
				{
					tex.SetPixel(i, y + h - 1, color);
				}
			}
		}
		for (int j = y; j < y + h; j++)
		{
			if (j >= 0 && j < ((Texture)tex).height)
			{
				if (x >= 0 && x < ((Texture)tex).width)
				{
					tex.SetPixel(x, j, color);
				}
				if (x + w - 1 >= 0 && x + w - 1 < ((Texture)tex).width)
				{
					tex.SetPixel(x + w - 1, j, color);
				}
			}
		}
	}

	private static void DrawTextBitmap(Texture2D tex, int x, int y, string text, Color color)
	{
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		int num = x;
		int num2 = 4;
		int num3 = 1;
		string text2 = text.ToUpper();
		foreach (char c in text2)
		{
			if ((c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_')
			{
				num += 5 * num2 + num2;
				continue;
			}
			for (int j = 0; j < 5; j++)
			{
				for (int k = 0; k < 5; k++)
				{
					if (!letters[(uint)c, j * 5 + k])
					{
						continue;
					}
					int num4 = ((c != '_') ? (4 - j) : (4 - j - num3));
					for (int l = 0; l < num2; l++)
					{
						for (int m = 0; m < num2; m++)
						{
							int num5 = num + k * num2 + l;
							int num6 = y + num4 * num2 + m;
							if (num5 >= 0 && num5 < ((Texture)tex).width && num6 >= 0 && num6 < ((Texture)tex).height)
							{
								tex.SetPixel(num5, num6, color);
							}
						}
					}
				}
			}
			num += 5 * num2 + num2;
		}
	}

	private static void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, Color color, int thickness = 2)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		int num = Math.Abs(x1 - x0);
		int num2 = ((x0 < x1) ? 1 : (-1));
		int num3 = -Math.Abs(y1 - y0);
		int num4 = ((y0 < y1) ? 1 : (-1));
		int num5 = num + num3;
		while (true)
		{
			for (int i = -thickness / 2; i <= thickness / 2; i++)
			{
				for (int j = -thickness / 2; j <= thickness / 2; j++)
				{
					int num6 = x0 + i;
					int num7 = y0 + j;
					if (num6 >= 0 && num6 < ((Texture)tex).width && num7 >= 0 && num7 < ((Texture)tex).height)
					{
						tex.SetPixel(num6, num7, color);
					}
				}
			}
			if (x0 != x1 || y0 != y1)
			{
				int num8 = 2 * num5;
				if (num8 >= num3)
				{
					num5 += num3;
					x0 += num2;
				}
				if (num8 <= num)
				{
					num5 += num;
					y0 += num4;
				}
				continue;
			}
			break;
		}
	}
}
[BepInPlugin("HardItemRandomizer.HKSilksong_SceneRandomizer", "Random Scene Loader", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class RandomSceneLoader : BaseUnityPlugin
{
	internal class SceneConfig
	{
		public List<string> Exits;

		public SceneConfig(List<string> exits)
		{
			Exits = exits ?? new List<string>();
		}
	}

	internal ManualLogSource log;

	private Random rng;

	internal readonly Dictionary<string, SceneConfig> sceneConfigs = new Dictionary<string, SceneConfig>(StringComparer.OrdinalIgnoreCase)
	{
		{
			"Tut_01",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "top1" })
		},
		{
			"Tut_01b",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Tut_02",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Tut_03",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Bonetown",
			new SceneConfig(new List<string>
			{
				"bot1", "bot2", "left1", "left2", "right1", "right2", "top1", "top2", "top3", "top4",
				"top5", "top6"
			})
		},
		{
			"Weave_02",
			new SceneConfig(new List<string> { "left2", "left3", "left4", "right1", "right2", "right3" })
		},
		{
			"Weave_03",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Weave_04",
			new SceneConfig(new List<string> { "left1", "right2" })
		},
		{
			"Weave_05b",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Weave_07",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Weave_08",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Weave_10",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Weave_11",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Weave_12",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Weave_13",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Weave_14",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Bone_01",
			new SceneConfig(new List<string> { "left2", "right1", "right2", "top2" })
		},
		{
			"Bone_04",
			new SceneConfig(new List<string> { "bot2", "left1", "left2", "right1", "top1" })
		},
		{
			"Bone_05",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_03",
			new SceneConfig(new List<string> { "bot1", "left1", "left2", "left4", "right1", "right3", "top1" })
		},
		{
			"Bone_05b",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Bone_06",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_07",
			new SceneConfig(new List<string> { "left1", "right1", "right2", "top1" })
		},
		{
			"Bone_08",
			new SceneConfig(new List<string> { "bot1", "left2", "left3", "right2", "right3" })
		},
		{
			"Bone_09",
			new SceneConfig(new List<string> { "left1", "right1", "right2", "top1" })
		},
		{
			"Bone_10",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_11",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2", "top1" })
		},
		{
			"Bone_14",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bone_15",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Bone_16",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Bone_17",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Bone_18",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Bone_19",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Bone_East_01",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Bone_East_02",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Bone_East_04",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2", "top2" })
		},
		{
			"Bone_East_05",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bone_East_07",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3", "right4", "right5", "top1" })
		},
		{
			"Bone_East_09",
			new SceneConfig(new List<string> { "left2", "left3", "right1", "right2", "top1" })
		},
		{
			"Bone_East_10",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Bone_East_11",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2" })
		},
		{
			"Bone_East_12",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_East_13",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Bone_East_14",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Bone_East_15",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_East_16",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Bone_East_17",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_East_18",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Bone_East_18b",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Bone_East_18c",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bone_East_20",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Bone_East_22",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Bone_East_24",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_East_25",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Bone_East_26",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Bone_East_27",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Bone_East_04c",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Bone_East_04b",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Bone_East_09b",
			new SceneConfig(new List<string> { "bot1", "left1", "top1" })
		},
		{
			"Bone_East_14b",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Ant_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Ant_03",
			new SceneConfig(new List<string> { "left2", "right3" })
		},
		{
			"Ant_04",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Ant_04_left",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Ant_04_mid",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Ant_05b",
			new SceneConfig(new List<string> { "bot1", "bot2", "right1" })
		},
		{
			"Ant_05c",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Ant_09",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Ant_14",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "left5", "right2", "right3" })
		},
		{
			"Ant_17",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Ant_19",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Ant_20",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Ant_21",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Ant_Merchant",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Ant_Queen",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Aspid_01",
			new SceneConfig(new List<string>
			{
				"bot1", "bot2", "bot3", "bot4", "bot5", "bot6", "bot7", "bot8", "left1", "left2",
				"right2", "right3", "right4", "top1", "top2", "top3", "top4", "top5", "top6", "top7"
			})
		},
		{
			"Belltown_04",
			new SceneConfig(new List<string> { "bot1", "left1", "left2" })
		},
		{
			"Belltown_06",
			new SceneConfig(new List<string> { "left1", "left3", "right1" })
		},
		{
			"Belltown_Room_shellwood",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Belltown_Shrine",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Belltown_basement_03",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Bellshrine",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bellshrine_03",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bonegrave",
			new SceneConfig(new List<string> { "right1", "right2", "top1" })
		},
		{
			"Bone_01c",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Bone_02",
			new SceneConfig(new List<string> { "left1", "right1", "top1", "top2" })
		},
		{
			"Bellshrine_05",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bellway_03",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Greymoor_01",
			new SceneConfig(new List<string> { "bot1", "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Bellshrine_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Greymoor_02",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" })
		},
		{
			"Greymoor_15",
			new SceneConfig(new List<string> { "left1", "left3", "right2", "right3" })
		},
		{
			"Greymoor_15b",
			new SceneConfig(new List<string> { "left2", "left3", "right1", "top1" })
		},
		{
			"Room_CrowCourt",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Room_CrowCourt_02",
			new SceneConfig(new List<string> { "top1" })
		},
		{
			"Clover_01",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Greymoor_22",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Greymoor_12",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Greymoor_03",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "right4", "right5" })
		},
		{
			"Dust_01",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Dust_02",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3", "top1" })
		},
		{
			"Dust_03",
			new SceneConfig(new List<string> { "bot1", "left1", "top1" })
		},
		{
			"Dust_Chef",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Dust_04",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Dust_Shack",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Dust_10",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Dust_05",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Dust_06",
			new SceneConfig(new List<string> { "left1", "right1", "right2", "right3" })
		},
		{
			"Dust_12",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Dust_11",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Greymoor_17",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Halfway_01",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Greymoor_04",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" })
		},
		{
			"Greymoor_11",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Greymoor_06",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "right4", "top1" })
		},
		{
			"Greymoor_10",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Wisp_03",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Wisp_06",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Greymoor_07",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2" })
		},
		{
			"Greymoor_20b",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Greymoor_20c",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Greymoor_08",
			new SceneConfig(new List<string> { "left2", "right1", "top1" })
		},
		{
			"Greymoor_16",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Bellway_04",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Greymoor_05",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Belltown",
			new SceneConfig(new List<string> { "left3", "right2" })
		},
		{
			"Memory_Needolin",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Belltown_07",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shellwood_01",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Shellwood_02",
			new SceneConfig(new List<string> { "left2", "left3", "right1", "right2" })
		},
		{
			"Shellwood_16",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shellwood_03",
			new SceneConfig(new List<string> { "bot1", "left1", "left3", "right1", "right2", "right3" })
		},
		{
			"Shellwood_04b",
			new SceneConfig(new List<string> { "left1", "right1", "top1", "top2" })
		},
		{
			"Shellwood_08c",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shellwood_04c",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Shellwood_08",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Coral_19",
			new SceneConfig(new List<string>
			{
				"bot1", "bot2", "bot3", "bot4", "bot5", "bot6", "bot7", "right1", "top1", "top2",
				"top3", "top4", "top5", "top6", "top7", "top8"
			})
		},
		{
			"Shellwood_19",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shellwood_14",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shellwood_10",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" })
		},
		{
			"Shellwood_11",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Shellwood_26",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Shellwood_18",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Shellwood_13",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Shellwood_01b",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Shellwood_20",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shellwood_Witch",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Dock_08",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Dock_01",
			new SceneConfig(new List<string> { "left1", "right1", "right2" })
		},
		{
			"Bellway_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Dock_16",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Bone_East_03",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Room_Forge",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Dock_04",
			new SceneConfig(new List<string> { "left1", "right1", "right2", "right3" })
		},
		{
			"Dock_06_Church",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Dock_10",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Dock_15",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Dock_13",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Dock_11",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Dock_12",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Dock_14",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Dock_09",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Dock_02",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Dock_02b",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" })
		},
		{
			"Dock_03c",
			new SceneConfig(new List<string> { "left2", "top1", "top2" })
		},
		{
			"Dock_03",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Dock_03b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shellwood_15",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_19b",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Coral_02",
			new SceneConfig(new List<string> { "bot2", "right1" })
		},
		{
			"Coral_03",
			new SceneConfig(new List<string>
			{
				"bot1", "bot2", "bot3", "bot4", "bot5", "bot6", "left1", "left2", "left3", "right1",
				"right2", "right3"
			})
		},
		{
			"Coral_12",
			new SceneConfig(new List<string> { "left2", "left3", "right1" })
		},
		{
			"Coral_11",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_11b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_34",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Coral_25",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Coral_23",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Coral_39",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Coral_35b",
			new SceneConfig(new List<string> { "bot1", "left2", "left3", "left4", "left5", "right1", "right2" })
		},
		{
			"Coral_40",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Coral_41",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Coral_35",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "top1" })
		},
		{
			"Coral_24",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_26",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Coral_38",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Coral_44",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_29",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Coral_27",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_28",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Coral_Tower_01",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Coral_42",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Coral_43",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bellway_08",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_32",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Coral_Judge_Arena",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Coral_10",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Song_19_entrance",
			new SceneConfig(new List<string> { "left1", "right1", "right2" })
		},
		{
			"Song_01c",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Song_01",
			new SceneConfig(new List<string> { "bot1", "right2", "top1" })
		},
		{
			"Under_07b",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Song_01b",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Song_05",
			new SceneConfig(new List<string> { "left3", "left4", "left5", "right2", "right3", "right4" })
		},
		{
			"Song_02",
			new SceneConfig(new List<string> { "left2", "right1" })
		},
		{
			"Ward_01",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" })
		},
		{
			"Ward_02",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Ward_02b",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Ward_03",
			new SceneConfig(new List<string> { "bot1", "left1", "top1" })
		},
		{
			"Ward_07",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Ward_06",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Song_07",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Song_27",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Song_20",
			new SceneConfig(new List<string> { "left1", "left2", "right4", "right5", "right6", "top1" })
		},
		{
			"Bellway_City",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Library_13",
			new SceneConfig(new List<string> { "left1", "right1", "right2" })
		},
		{
			"Song_11",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3" })
		},
		{
			"Song_15",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Song_17",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Hang_01",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Hang_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Hang_03",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "top1" })
		},
		{
			"Hang_10",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Hang_03_top",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Hang_13",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Hang_08",
			new SceneConfig(new List<string> { "bot1", "left1", "left2", "left3", "left4", "right1" })
		},
		{
			"Hang_09",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Hang_16",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Hang_06",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" })
		},
		{
			"Hang_06b",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Hang_17b",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Hang_04",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Hang_12",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Hang_07",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" })
		},
		{
			"Song_09",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Song_09b",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Cog_05",
			new SceneConfig(new List<string> { "left1", "right2", "top1" })
		},
		{
			"Cog_Dancers",
			new SceneConfig(new List<string> { "bot1", "bot2", "left1", "right1", "top1" })
		},
		{
			"Cog_04",
			new SceneConfig(new List<string> { "left2", "right2", "right3", "top1", "top2" })
		},
		{
			"Cog_Bench",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Song_25",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1", "top2" })
		},
		{
			"Song_Enclave",
			new SceneConfig(new List<string> { "bot1", "left1", "left2", "top1" })
		},
		{
			"Song_Enclave_Tube",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Under_01",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1" })
		},
		{
			"Under_27",
			new SceneConfig(new List<string> { "left1", "right1", "right2" })
		},
		{
			"Shellwood_22",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Shellwood_11b",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Under_01b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Under_02",
			new SceneConfig(new List<string> { "left1", "left3", "right1", "right2", "right3", "right4" })
		},
		{
			"Under_14",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Under_16",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Under_03b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Under_07",
			new SceneConfig(new List<string> { "left3", "right2" })
		},
		{
			"Under_07c",
			new SceneConfig(new List<string> { "left2", "top1" })
		},
		{
			"Under_06",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Under_08",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Under_05",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" })
		},
		{
			"Under_11",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Under_23",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Wisp_09",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Wisp_05",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Wisp_02",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Belltown_08",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Wisp_04",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Wisp_08",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Wisp_07",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Under_04",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Under_03c",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Under_03",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Under_10",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Under_12",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Under_13",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3" })
		},
		{
			"Under_22",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Under_21",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Under_19",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Under_19c",
			new SceneConfig(new List<string> { "bot1", "left1", "left2" })
		},
		{
			"Under_19b",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Under_18",
			new SceneConfig(new List<string> { "left1", "right1", "top1", "top2" })
		},
		{
			"Under_17",
			new SceneConfig(new List<string> { "bot1", "bot2", "left1", "right1", "top1" })
		},
		{
			"Library_11b",
			new SceneConfig(new List<string> { "left3", "right1" })
		},
		{
			"Library_11",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" })
		},
		{
			"Library_13b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Library_04",
			new SceneConfig(new List<string>
			{
				"left1", "left2", "left3", "left4", "right1", "right2", "right3", "right4", "right5", "right6",
				"top1"
			})
		},
		{
			"Library_16",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Library_10",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Library_12b",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Library_12",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Library_05",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Library_06",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Library_07",
			new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "left1", "left2", "top1" })
		},
		{
			"Library_08",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Library_09",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Library_14",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Library_01",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2" })
		},
		{
			"Library_15",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Library_03",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Song_24",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Song_20b",
			new SceneConfig(new List<string> { "bot1", "left2", "left4", "right2", "right3", "top1" })
		},
		{
			"Library_02",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Song_29",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Arborium_01",
			new SceneConfig(new List<string> { "bot1", "left1", "left2", "left3", "right1", "right2", "right3", "right4", "right5" })
		},
		{
			"Cog_10",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Cog_07",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Cog_06",
			new SceneConfig(new List<string> { "left2", "right1" })
		},
		{
			"Arborium_04",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Arborium_03",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2" })
		},
		{
			"Arborium_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Arborium_05",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Arborium_06",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Arborium_09",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Arborium_Tube",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Arborium_07",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Arborium_08",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Song_13",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Song_18",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Song_03",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Song_04",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "right2" })
		},
		{
			"Song_10",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Song_12",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "left4", "right1", "right2", "right3" })
		},
		{
			"Song_14",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Song_26",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Song_28",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Song_08",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Slab_01",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Slab_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Slab_03",
			new SceneConfig(new List<string>
			{
				"left1", "left2", "left3", "left4", "left5", "left6", "left7", "left8", "right1", "right2",
				"right3", "right4", "right5", "right7", "right8", "right9"
			})
		},
		{
			"Slab_04",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Slab_23",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Slab_21",
			new SceneConfig(new List<string> { "left1", "left3", "top1" })
		},
		{
			"Slab_22",
			new SceneConfig(new List<string> { "bot1", "bot2" })
		},
		{
			"Slab_Cell_Creature",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Slab_20",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Slab_17",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Slab_18",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Slab_16",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" })
		},
		{
			"Slab_15",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" })
		},
		{
			"Peak_01",
			new SceneConfig(new List<string>
			{
				"left1", "left2", "left3", "left4", "right1", "right2", "right3", "right4", "top1", "top2",
				"top3", "top4"
			})
		},
		{
			"Slab_14",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Slab_13",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Slab_05",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Slab_06",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Peak_07",
			new SceneConfig(new List<string> { "bot1", "bot2", "bot3", "bot4", "bot5", "top1", "top2" })
		},
		{
			"Peak_08b",
			new SceneConfig(new List<string> { "bot4", "bot5", "bot6", "left1", "left2" })
		},
		{
			"Peak_08",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Peak_05d",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Peak_05",
			new SceneConfig(new List<string> { "bot1", "right3", "top2" })
		},
		{
			"Peak_05c",
			new SceneConfig(new List<string> { "left2", "right1" })
		},
		{
			"Peak_05e",
			new SceneConfig(new List<string> { "left1", "right1", "right2" })
		},
		{
			"Peak_06b",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Peak_02",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "right4" })
		},
		{
			"Peak_04d",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Peak_04",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Bellway_Peak",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "top1" })
		},
		{
			"Bellway_Peak_02",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Peak_04c",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Peak_10",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Slab_08",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Slab_Cell_Quiet",
			new SceneConfig(new List<string> { "left1", "left2" })
		},
		{
			"Slab_19b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Slab_07",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Slab_12",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Slab_10c",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Slab_10b",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Cog_10_Destroyed",
			new SceneConfig(new List<string> { "bot1", "left1" })
		},
		{
			"Cog_09_Destroyed",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Song_Tower_Destroyed",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Arborium_10",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Arborium_11",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Aqueduct_01",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Aqueduct_02",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3" })
		},
		{
			"Bellway_Aqueduct",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Aqueduct_07",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Aqueduct_04",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Aqueduct_03",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Aqueduct_06",
			new SceneConfig(new List<string> { "bot1", "left1", "left2" })
		},
		{
			"Aqueduct_08",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Aqueduct_05",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shadow_01",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1", "right2", "right3", "top1" })
		},
		{
			"Shadow_18",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_12",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_19",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Shadow_24",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shadow_10",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Shadow_25",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shadow_08",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Shadow_27",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_26",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2" })
		},
		{
			"Shadow_16",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_15",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Shadow_14",
			new SceneConfig(new List<string> { "right1", "right2" })
		},
		{
			"Shadow_02",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Shadow_11",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_13",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shadow_23",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shadow_03",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Shadow_21",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Shadow_09",
			new SceneConfig(new List<string> { "left1", "left2", "left3", "right1" })
		},
		{
			"Shadow_Weavehome",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Shadow_05",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_04b",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Shadow_04",
			new SceneConfig(new List<string> { "left1", "right1", "right2", "top1" })
		},
		{
			"Shadow_20",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Bellway_Shadow",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Tube_Hub",
			new SceneConfig(new List<string> { "left1", "left3", "left4" })
		},
		{
			"Cradle_01",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Cradle_02",
			new SceneConfig(new List<string> { "left2", "right1", "right2" })
		},
		{
			"Cradle_02b",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Cradle_03",
			new SceneConfig(new List<string> { "left2", "right2" })
		},
		{
			"Crawl_04",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Crawl_02",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Crawl_06",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Crawl_01",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Crawl_03",
			new SceneConfig(new List<string> { "bot1", "left1", "right1", "top1" })
		},
		{
			"Crawl_08",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Crawl_05",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Crawl_03b",
			new SceneConfig(new List<string> { "bot1", "right1", "top1" })
		},
		{
			"Crawl_07",
			new SceneConfig(new List<string> { "bot1", "left1", "top1" })
		},
		{
			"Crawl_09",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Crawl_10",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Abyss_12",
			new SceneConfig(new List<string> { "left1", "right2" })
		},
		{
			"Abyss_05",
			new SceneConfig(new List<string> { "left2", "right1" })
		},
		{
			"Abyss_08",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Abyss_07",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Abyss_01",
			new SceneConfig(new List<string> { "left1", "right2", "right3", "right4" })
		},
		{
			"Abyss_06",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Abyss_04",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Abyss_02b",
			new SceneConfig(new List<string> { "left2", "right1", "top1" })
		},
		{
			"Abyss_02",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Abyss_03",
			new SceneConfig(new List<string> { "left1", "left2" })
		},
		{
			"Abyss_13",
			new SceneConfig(new List<string> { "left1", "right1", "top1" })
		},
		{
			"Abyss_11",
			new SceneConfig(new List<string> { "bot1", "right1" })
		},
		{
			"Abyss_09",
			new SceneConfig(new List<string> { "bot1", "top1" })
		},
		{
			"Greymoor_13",
			new SceneConfig(new List<string> { "bot1", "left1", "right1" })
		},
		{
			"Clover_01b",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Clover_02c",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Clover_05c",
			new SceneConfig(new List<string> { "left1", "left2", "right1", "right2", "right3" })
		},
		{
			"Clover_21",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Clover_16",
			new SceneConfig(new List<string> { "right1", "top1" })
		},
		{
			"Clover_06",
			new SceneConfig(new List<string> { "bot1", "bot2" })
		},
		{
			"Clover_19",
			new SceneConfig(new List<string> { "left1", "top1" })
		},
		{
			"Clover_04b",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Clover_11",
			new SceneConfig(new List<string> { "right1" })
		},
		{
			"Clover_03",
			new SceneConfig(new List<string> { "left1", "left2", "right1" })
		},
		{
			"Clover_18",
			new SceneConfig(new List<string> { "left1" })
		},
		{
			"Tut_04",
			new SceneConfig(new List<string> { "left1", "right1" })
		},
		{
			"Cog_09",
			new SceneConfig(new List<string> { "bot1" })
		},
		{
			"Cog_08",
			new SceneConfig(new List<string> { "bot1", "top1" })
		}
	};

	private string lastEntryGateUsed;

	private string previousSceneName;

	private string currentSceneName = "(unknown)";

	private bool isTransitioning;

	private bool loadRequested;

	public static bool SuppressTransitionPatch;

	private bool autoDiscoveryMode;

	private HashSet<string> discoveredScenes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private string discoveryFilePath;

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

	private List<string> _cachedPreferredLowered;

	private WaitForSeconds waitHalfSecond;

	private WaitForSeconds waitThirdSecond;

	private WaitForSeconds waitTenthSecond;

	private WaitForSeconds waitFifthSecond;

	private GUIStyle sceneLabelStyle;

	private string cachedSceneLabel = "";

	private string lastRenderedScene = "";

	private ConfigEntry<bool> cfgShowSceneLabel;

	private ConfigEntry<string> cfgTeleportScene;

	private ConfigEntry<bool> cfgTeleportConfirm;

	private HashSet<string> visitedScenesF6 = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	public static bool EnableRandomization;

	private ConfigEntry<bool> cfgEnableRandomization;

	private ConfigEntry<bool> cfgInstantMusicTransition;

	private bool _apiInitialized;

	public static int CurrentSeed { get; internal set; }

	private void Awake()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Expected O, but got Unknown
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Expected O, but got Unknown
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d6: Expected O, but got Unknown
		log = ((BaseUnityPlugin)this).Logger;
		rng = new Random();
		Scene activeScene = SceneManager.GetActiveScene();
		currentSceneName = ((Scene)(ref activeScene)).name;
		waitHalfSecond = new WaitForSeconds(0.5f);
		waitThirdSecond = new WaitForSeconds(0.3f);
		waitTenthSecond = new WaitForSeconds(0.1f);
		waitFifthSecond = new WaitForSeconds(0.2f);
		sceneLabelStyle = new GUIStyle();
		cfgShowSceneLabel = GlobalConfig.ShowSceneLabel;
		cfgTeleportScene = GlobalConfig.TeleportScene;
		cfgTeleportConfirm = GlobalConfig.TeleportConfirm;
		cfgEnableRandomization = GlobalConfig.EnableRandomization;
		EnableRandomization = cfgEnableRandomization.Value;
		cfgInstantMusicTransition = GlobalConfig.InstantMusicTransition;
		discoveryFilePath = Path.Combine(Paths.PluginPath, "discovered_exits.txt");
		log.LogInfo((object)("RandomSceneLoader loaded. Current scene: " + currentSceneName + ". F5=random, F7=discover"));
		try
		{
			if (sceneConfigs != null)
			{
				discoveredScenes.UnionWith(sceneConfigs.Keys);
				log.LogInfo((object)$"Preloaded {discoveredScenes.Count} known scenes into discovered set");
			}
		}
		catch
		{
		}
		try
		{
			string path = Path.Combine(Paths.PluginPath, "roomrando_connections.txt");
			if (File.Exists(path))
			{
				string[] array = File.ReadAllLines(path);
				foreach (string text in array)
				{
					if (text.StartsWith("#seed|", StringComparison.OrdinalIgnoreCase))
					{
						string[] array2 = text.Split(new char[1] { '|' });
						if (array2.Length >= 2 && int.TryParse(array2[1], out var result))
						{
							CurrentSeed = result;
							log.LogInfo((object)$"Preloaded room random seed: {CurrentSeed}");
							break;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			log.LogWarning((object)("Failed to preload room random seed: " + ex.Message));
		}
		if (autoDiscoveryMode)
		{
			log.LogInfo((object)("Auto-discovery mode enabled. RoomRando disabled. Results saved to: " + discoveryFilePath));
			return;
		}
		try
		{
			new Harmony("HardItemRandomizer.HKSilksong_SceneRandomizer").PatchAll();
			log.LogInfo((object)"Harmony patches applied successfully");
		}
		catch (Exception ex2)
		{
			log.LogError((object)("Failed to apply Harmony patches: " + ex2.Message));
		}
		try
		{
			if ((Object)(object)GameObject.Find("__RoomRando") == (Object)null)
			{
				GameObject val = new GameObject("__RoomRando");
				val.AddComponent<RoomRando>().Initialize(this);
				Object.DontDestroyOnLoad((Object)val);
			}
		}
		catch (Exception ex3)
		{
			log.LogError((object)("Failed to create RoomRando: " + ex3.Message));
		}
		try
		{
			if ((Object)(object)GameObject.Find("__SeedManager") == (Object)null)
			{
				GameObject val2 = new GameObject("__SeedManager");
				val2.AddComponent<SeedManager>().Initialize(this);
				Object.DontDestroyOnLoad((Object)val2);
			}
		}
		catch (Exception ex4)
		{
			log.LogError((object)("Failed to create SeedManager: " + ex4.Message));
		}
		GameObject obj2 = GameObject.Find("__RoomRando");
		RoomRando rando = ((obj2 != null) ? obj2.GetComponent<RoomRando>() : null);
		HKSilksong_RandomizerAPI.Initialize(this, rando);
		SceneManager.sceneLoaded += OnSceneLoaded;
		SceneManager.activeSceneChanged += OnActiveSceneChanged;
		_apiInitialized = true;
	}

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

	public string GetCurrentSceneName()
	{
		return currentSceneName;
	}

	public void SetShowSceneLabel(bool show)
	{
		if (cfgShowSceneLabel != null)
		{
			cfgShowSceneLabel.Value = show;
		}
	}

	public bool GetShowSceneLabel()
	{
		return cfgShowSceneLabel?.Value ?? true;
	}

	public void SetLastEntryGate(string gateName)
	{
		lastEntryGateUsed = gateName;
	}

	public void TeleportToScene(string sceneName)
	{
		try
		{
			if (isTransitioning)
			{
				log.LogInfo((object)"Teleport skipped: transition already in progress");
				return;
			}
			if (string.IsNullOrWhiteSpace(sceneName))
			{
				log.LogWarning((object)"TeleportToScene called with empty scene name");
				return;
			}
			string text = null;
			string scenePart = sceneName.Trim();
			int num = scenePart.LastIndexOf(' ');
			if (num > 0)
			{
				text = scenePart.Substring(num + 1).Trim();
				scenePart = scenePart.Substring(0, num).Trim();
				if (string.IsNullOrEmpty(text))
				{
					text = null;
				}
			}
			string text2 = null;
			SceneConfig value = null;
			string text3 = null;
			if (sceneConfigs != null && sceneConfigs.TryGetValue(scenePart, out value))
			{
				text3 = scenePart;
			}
			else if (sceneConfigs != null)
			{
				List<string> source = sceneConfigs.Keys.ToList();
				string inputLetters = new string(scenePart.Where(char.IsLetter).ToArray());
				string inputDigits = new string(scenePart.Where(char.IsDigit).ToArray());
				text3 = source.FirstOrDefault((string s) => string.Equals(s, scenePart, StringComparison.OrdinalIgnoreCase));
				if (text3 == null && !string.IsNullOrEmpty(inputLetters) && !string.IsNullOrEmpty(inputDigits))
				{
					text3 = source.FirstOrDefault(delegate(string s)
					{
						string text4 = new string(s.Where(char.IsDigit).ToArray());
						string text5 = new string(s.Where(char.IsLetter).ToArray());
						return !string.IsNullOrEmpty(text4) && text5.IndexOf(inputLetters, StringComparison.OrdinalIgnoreCase) >= 0 && text4.IndexOf(inputDigits, StringComparison.OrdinalIgnoreCase) >= 0;
					});
				}
				if (text3 == null && !string.IsNullOrEmpty(inputLetters) && string.IsNullOrEmpty(inputDigits))
				{
					text3 = source.FirstOrDefault((string s) => string.IsNullOrEmpty(new string(s.Where(char.IsDigit).ToArray())) && s.IndexOf(inputLetters, StringComparison.OrdinalIgnoreCase) >= 0);
				}
				if (text3 == null)
				{
					text3 = source.FirstOrDefault((string s) => s.IndexOf(scenePart, StringComparison.OrdinalIgnoreCase) >= 0);
				}
			}
			if (text3 != null && sceneConfigs.TryGetValue(text3, out value))
			{
				if (text != null)
				{
					if (value.Exits != null && value.Exits.Contains<string>(text, StringComparer.OrdinalIgnoreCase))
					{
						text2 = text;
					}
					else
					{
						log.LogWarning((object)("TeleportToScene: entry '" + text + "' not valid for scene '" + text3 + "', will pick random."));
						if (value.Exits != null && value.Exits.Count > 0)
						{
							text2 = value.Exits[rng.Next(value.Exits.Count)];
						}
					}
				}
				else if (value.Exits != null && value.Exits.Count > 0)
				{
					text2 = value.Exits[rng.Next(value.Exits.Count)];
				}
				log.LogInfo((object)("Teleport: " + scenePart + " -> " + text3 + " (entry '" + (text2 ?? "(null)") + "')"));
			}
			else
			{
				log.LogWarning((object)("TeleportToScene: scene '" + scenePart + "' not found in sceneConfigs. Attempting direct load."));
				text3 = scenePart;
				if (text != null)
				{
					text2 = text;
				}
			}
			SuppressTransitionPatch = true;
			((MonoBehaviour)this).StartCoroutine(LoadSceneCoroutine(text3, text2));
		}
		catch (Exception arg)
		{
			log.LogError((object)$"TeleportToScene failed: {arg}");
		}
	}

	private List<string> GetCachedPreferredLowered()
	{
		if (_cachedPreferredLowered == null)
		{
			_cachedPreferredLowered = (from s in preferredSceneSubstrings
				where !string.IsNullOrWhiteSpace(s)
				select s.ToLower()).ToList();
		}
		return _cachedPreferredLowered;
	}

	private void LoadRandomUniqueScene()
	{
		if (isTransitioning)
		{
			log.LogInfo((object)"LoadRandomUniqueScene skipped: transition already in progress");
			return;
		}
		List<string> list = sceneConfigs.Keys.Where((string k) => !string.Equals(k, currentSceneName, StringComparison.OrdinalIgnoreCase) && !visitedScenesF6.Contains(k)).ToList();
		if (list.Count == 0)
		{
			log.LogInfo((object)"F6: All scenes have been visited already (or no candidates available). Clearing visited list.");
			visitedScenesF6.Clear();
			list = sceneConfigs.Keys.Where((string k) => !string.Equals(k, currentSceneName, StringComparison.OrdinalIgnoreCase)).ToList();
			if (list.Count == 0)
			{
				return;
			}
		}
		List<string> list2 = null;
		try
		{
			List<string> lowered = GetCachedPreferredLowered();
			list2 = list.Where((string c) => lowered.Any((string sub) => c.ToLower().Contains(sub))).ToList();
		}
		catch
		{
		}
		List<string> list3 = ((list2 != null && list2.Count > 0) ? list2 : list);
		string text = list3[rng.Next(list3.Count)];
		SceneConfig sceneConfig = (sceneConfigs.ContainsKey(text) ? sceneConfigs[text] : null);
		string text2 = null;
		if (sceneConfig != null && sceneConfig.Exits != null && sceneConfig.Exits.Count > 0)
		{
			text2 = sceneConfig.Exits[rng.Next(sceneConfig.Exits.Count)];
		}
		visitedScenesF6.Add(text);
		lastEntryGateUsed = text2;
		log.LogInfo((object)("[F6] Selected unique random scene: " + text + " (enter via gate '" + (text2 ?? "(null)") + "')"));
		SuppressTransitionPatch = true;
		((MonoBehaviour)this).StartCoroutine(LoadSceneCoroutine(text, text2));
	}

	private void LoadRandomScene()
	{
		if (isTransitioning)
		{
			log.LogInfo((object)"LoadRandomScene skipped: transition already in progress");
			return;
		}
		loadRequested = true;
		List<string> list = sceneConfigs.Keys.Where((string k) => !string.Equals(k, currentSceneName, StringComparison.OrdinalIgnoreCase)).ToList();
		if (list.Count == 0)
		{
			log.LogWarning((object)"No candidate scenes found in sceneConfigs.");
			return;
		}
		List<string> list2 = null;
		try
		{
			List<string> lowered = GetCachedPreferredLowered();
			list2 = list.Where((string c) => lowered.Any((string sub) => c.ToLower().Contains(sub))).ToList();
		}
		catch
		{
		}
		List<string> list3 = ((list2 != null && list2.Count > 0) ? list2 : list);
		string text = list3[rng.Next(list3.Count)];
		SceneConfig sceneConfig = (sceneConfigs.ContainsKey(text) ? sceneConfigs[text] : null);
		string text2 = null;
		if (sceneConfig != null && sceneConfig.Exits != null && sceneConfig.Exits.Count > 0)
		{
			text2 = sceneConfig.Exits[rng.Next(sceneConfig.Exits.Count)];
		}
		lastEntryGateUsed = text2;
		log.LogInfo((object)("Selected random scene: " + text + " (enter via gate '" + (text2 ?? "(null)") + "')"));
		SuppressTransitionPatch = true;
		((MonoBehaviour)this).StartCoroutine(LoadSceneCoroutine(text, text2));
	}

	private IEnumerator LoadSceneCoroutine(string sceneName, string entryGate)
	{
		if (!isTransitioning)
		{
			loadRequested = false;
			isTransitioning = true;
			lastEntryGateUsed = entryGate;
			float timeout = 8f;
			float startTime = Time.time;
			if (!string.IsNullOrEmpty(sceneName) && (Object)(object)GameManager.instance != (Object)null)
			{
				try
				{
					GameManager.instance.BeginSceneTransition(new SceneLoadInfo
					{
						SceneName = sceneName,
						EntryGateName = entryGate,
						PreventCameraFadeOut = false,
						WaitForSceneTransitionCameraFade = true,
						Visualization = (SceneLoadVisualizations)0
					});
				}
				catch (Exception ex)
				{
					log.LogWarning((object)("BeginSceneTransition failed: " + ex.Message));
					isTransitioning = false;
					SuppressTransitionPatch = false;
					yield break;
				}
				while (true)
				{
					Scene activeScene = SceneManager.GetActiveScene();
					if (!(((Scene)(ref activeScene)).name != sceneName))
					{
						break;
					}
					if (Time.time - startTime > timeout)
					{
						log.LogWarning((object)("LoadSceneCoroutine timeout waiting for scene " + sceneName));
						isTransitioning = false;
						SuppressTransitionPatch = false;
						yield break;
					}
					yield return waitTenthSecond;
				}
				yield return waitFifthSecond;
				isTransitioning = false;
			}
			else
			{
				try
				{
					SceneManager.LoadScene(sceneName);
				}
				catch (Exception ex2)
				{
					log.LogWarning((object)("SceneManager.LoadScene failed: " + ex2.Message));
				}
				finally
				{
					isTransitioning = false;
				}
			}
		}
		SuppressTransitionPatch = false;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		currentSceneName = ((Scene)(ref scene)).name;
		cachedSceneLabel = Locale.Get("Scene: ") + currentSceneName;
		lastRenderedScene = currentSceneName;
		log.LogInfo((object)("Scene loaded: " + currentSceneName));
		if (autoDiscoveryMode)
		{
			((MonoBehaviour)this).StartCoroutine(AutoDiscoverAfterLoad());
		}
		else
		{
			((MonoBehaviour)this).StartCoroutine(DetectEntryGateAfterLoad());
		}
		if (cfgInstantMusicTransition != null && cfgInstantMusicTransition.Value)
		{
			SetMusicRegionsInstantTransition();
		}
		if (_apiInitialized && ((Scene)(ref scene)).name != "Menu_Title" && ((Scene)(ref scene)).name != "Menu" && ((Scene)(ref scene)).name != "Loading" && (Object)(object)HeroController.instance != (Object)null)
		{
			HKSilksong_RandomizerAPI.MarkGameReady();
		}
	}

	private IEnumerator AutoDiscoverAfterLoad()
	{
		yield return waitHalfSecond;
		DiscoverGatesInCurrentScene();
	}

	private void DiscoverGatesInCurrentScene()
	{
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		log.LogInfo((object)"=== DISCOVERING GATES ===");
		log.LogInfo((object)("Scene: " + currentSceneName));
		try
		{
			List<GameObject> list = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0).Where(delegate(GameObject obj)
			{
				string text2 = ((Object)obj).name.ToLower();
				return (text2.StartsWith("left") || text2.StartsWith("right") || text2.StartsWith("top") || text2.StartsWith("bot")) && text2.Length <= 6 && char.IsDigit(text2[text2.Length - 1]);
			}).ToList();
			log.LogInfo((object)$"Found {list.Count} gates:");
			IOrderedEnumerable<IGrouping<string, GameObject>> orderedEnumerable = from g in list
				group g by ((Object)g).name into g
				orderby g.Key
				select g;
			foreach (IGrouping<string, GameObject> item in orderedEnumerable)
			{
				log.LogInfo((object)$"  - {item.Key} (count: {item.Count()}, pos: {item.First().transform.position})");
			}
			List<string> list2 = orderedEnumerable.Select((IGrouping<string, GameObject> g) => g.Key).ToList();
			if (list2.Count > 0)
			{
				string text = "{ \"" + currentSceneName + "\", new SceneConfig(new List<string> { " + string.Join(", ", list2.Select((string e) => "\"" + e + "\"")) + " }) },";
				log.LogInfo((object)("Suggested: " + text));
				if (autoDiscoveryMode)
				{
					SaveDiscoveryToFile(currentSceneName, list2, text);
				}
			}
		}
		catch (Exception ex)
		{
			log.LogError((object)("DiscoverGates failed: " + ex.Message));
		}
	}

	private void SaveDiscoveryToFile(string sceneName, List<string> exitNames, string configLine)
	{
		try
		{
			if (!discoveredScenes.Contains(sceneName))
			{
				if (sceneConfigs != null && sceneConfigs.ContainsKey(sceneName))
				{
					log.LogInfo((object)("Discovery skipped for " + sceneName + ": already exists in sceneConfigs."));
					discoveredScenes.Add(sceneName);
					return;
				}
				discoveredScenes.Add(sceneName);
				File.AppendAllText(discoveryFilePath, string.Format("\n[{0:yyyy-MM-dd HH:mm:ss}] {1}\n  Gates found: {2}\n  Config: {3}\n", DateTime.Now, sceneName, string.Join(", ", exitNames), configLine));
				log.LogInfo((object)$"Saved discovery for {sceneName} to file ({exitNames.Count} exits)");
			}
		}
		catch (Exception ex)
		{
			log.LogError((object)("Failed to save discovery to file: " + ex.Message));
		}
	}

	private IEnumerator DetectEntryGateAfterLoad()
	{
		yield return waitThirdSecond;
		try
		{
			HeroController instance = HeroController.instance;
			if (!((Object)(object)instance != (Object)null))
			{
				yield break;
			}
			Vector3 position = ((Component)instance).transform.position;
			GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0);
			foreach (GameObject val in array)
			{
				string text = ((Object)val).name.ToLower();
				if ((text.StartsWith("left") || text.StartsWith("right") || text.StartsWith("top") || text.StartsWith("bot")) && text.Length <= 6 && char.IsDigit(text[text.Length - 1]) && (double)Vector3.Distance(position, val.transform.position) < 10.0)
				{
					if (string.IsNullOrEmpty(lastEntryGateUsed))
					{
						lastEntryGateUsed = ((Object)val).name;
						log.LogInfo((object)("Auto-detected entry gate: " + ((Object)val).name));
					}
					break;
				}
			}
		}
		catch (Exception ex)
		{
			log.LogWarning((object)("DetectEntryGate failed: " + ex.Message));
		}
	}

	private void OnActiveSceneChanged(Scene prev, Scene next)
	{
		if (((Scene)(ref next)).name == "Menu_Title" || ((Scene)(ref next)).name == "Quit_To_Menu")
		{
			lastEntryGateUsed = null;
			return;
		}
		previousSceneName = currentSceneName;
		currentSceneName = ((Scene)(ref next)).name;
		try
		{
			GameObject obj = GameObject.Find("__RoomRando");
			RoomRando roomRando = ((obj != null) ? obj.GetComponent<RoomRando>() : null);
			if ((Object)(object)roomRando != (Object)null && !string.IsNullOrEmpty(previousSceneName) && !string.IsNullOrEmpty(lastEntryGateUsed))
			{
				roomRando.OnExitUsed(previousSceneName, lastEntryGateUsed);
			}
		}
		catch (Exception ex)
		{
			log.LogWarning((object)("RoomRando notify failed: " + ex.Message));
		}
		lastEntryGateUsed = null;
	}

	private void OnGUI()
	{
		//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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Expected O, but got Unknown
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (sceneLabelStyle.normal.textColor != Color.white || sceneLabelStyle.fontSize != 14)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label);
				val.normal.textColor = Color.white;
				val.fontSize = 14;
				sceneLabelStyle = val;
			}
			if (cfgShowSceneLabel == null || cfgShowSceneLabel.Value)
			{
				if (currentSceneName != lastRenderedScene)
				{
					cachedSceneLabel = Locale.Get("Scene: ") + currentSceneName;
					lastRenderedScene = currentSceneName;
				}
				GUI.Label(new Rect(8f, 8f, 300f, 20f), cachedSceneLabel, sceneLabelStyle);
			}
		}
		catch
		{
		}
	}

	private void SetMusicRegionsInstantTransition()
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Type type = Type.GetType("MusicRegion, Assembly-CSharp");
			if (type == null)
			{
				return;
			}
			Object[] array = Resources.FindObjectsOfTypeAll(type);
			FieldInfo field = type.GetField("enterTransitionTime");
			FieldInfo field2 = type.GetField("exitTransitionTime");
			FieldInfo field3 = type.GetField("delay");
			if (field == null || field2 == null)
			{
				return;
			}
			int num = 0;
			Object[] array2 = array;
			foreach (Object val in array2)
			{
				if (val == (Object)null)
				{
					continue;
				}
				Object obj = ((val is Component) ? val : null);
				GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null);
				if ((Object)(object)val2 != (Object)null && val2.scene == SceneManager.GetActiveScene())
				{
					field.SetValue(val, 0f);
					field2.SetValue(val, 0f);
					if (field3 != null)
					{
						field3.SetValue(val, 0);
					}
					num++;
				}
			}
			if (num > 0)
			{
				log.LogInfo((object)$"Set {num} MusicRegion transition times to 0.");
			}
		}
		catch (Exception ex)
		{
			log.LogWarning((object)("SetMusicRegionsInstantTransition error: " + ex.Message));
		}
	}
}
public class RoomRando : MonoBehaviour
{
	private Dictionary<string, (string targetScene, string targetGate)> connections = new Dictionary<string, (string, string)>(StringComparer.OrdinalIgnoreCase);

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

	private bool enableRandomization = true;

	private RandomSceneLoader sceneLoader;

	private string saveFilePath;

	private Random rng;

	private int generationSeed;

	private bool enableMapGeneration;

	private List<(string beforeScene, string afterScene)> precedencePairs = new List<(string, string)>();

	private bool forceExactSeed;

	private static readonly HashSet<string> BlacklistedExits = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
	{
		"Bone_11_top1", "Bellshrine_right1", "Bellshrine_05_right1", "Dock_06_Church_right1", "Bone_East_09_top1", "Bellshrine_02_left1", "Dust_04_right1", "Dust_05_right1", "Dust_06_left1", "Shadow_20_bot1",
		"Bellshrine_03_right1", "Shellwood_19_left1", "Shellwood_01b_right2", "Bellshrine_02_right1", "Dust_06_right1", "Mosstown_03_top1", "Coral_10_left1", "Song_27_left1", "Dock_01_right1", "Dock_01_right2",
		"Bone_East_14_right1", "Bone_East_14_right2", "Greymoor_01_right1", "Greymoor_01_right2", "Dust_02_right1", "Dust_02_right2", "Dust_04_left1", "Dust_04_left2", "Song_25_top1", "Song_25_top2",
		"Arborium_05_top1", "Hang_07_top1", "Hang_07_left1", "Slab_02_left1", "Slab_05_right1", "Cog_06_right1", "Library_11b_right1", "Dock_03_bot1", "Dock_03c_top1", "Dock_03c_left2",
		"Dock_02_left1", "Shellwood_02_right2", "Shellwood_01_left2", "Dust_Chef_left1", "Song_11_left4", "Slab_03_right1", "Slab_03_right2", "Slab_03_right5", "Slab_03_right7", "Slab_03_left6",
		"Under_05_left2", "Under_02_right4", "Under_02_left1", "Bone_East_12_right1", "Shadow_27_right1", "Halfway_01_right1", "Wisp_03_top1", "Arborium_01_right1", "Arborium_04_left1", "Library_13_left1",
		"Hang_03_right2", "Aqueduct_02_right3", "Song_19_entrance_left1", "Weave_04_right2", "Slab_16_right1", "Bone_East_04_left1", "Bone_East_10_right1", "Bone_East_18c_left1", "Greymoor_05_left1", "Hang_08_left1",
		"Arborium_08_left1"
	};

	private static readonly Dictionary<string, int> SingleExitPairedCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

	private static readonly HashSet<string> HighPriorityRooms = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
	{
		"Bonegrave", "Shellwood_04c", "Coral_02", "Coral_35", "Coral_32", "Coral_24", "Coral_23", "Coral_25", "Dust_03", "Dust_06",
		"Shadow_05", "Shadow_08", "Shadow_09", "Shadow_16", "Shadow_10", "Shadow_19", "Shadow_24", "Shadow_01", "Shadow_14", "Aqueduct_04",
		"Aqueduct_03", "Aqueduct_01", "Arborium_11", "Arborium_09", "Arborium_05", "Song_Enclave", "Song_09b", "Song_11", "Song_01", "Song_19_entrance",
		"Under_02", "Under_07c", "Under_27", "Under_17", "Under_10", "Under_19c", "Library_11", "Library_12", "Library_12b", "Library_02",
		"Song_20b", "Song_20", "Library_03", "Slab_06", "Slab_05", "Slab_19b", "Slab_15", "Coral_27", "Coral_44", "Abyss_13",
		"Abyss_01", "Cog_08", "Cog_09", "Ward_02", "Wisp_05", "Wisp_08", "Slab_07", "Weave_08", "Song_03", "Abyss_05",
		"Cradle_02", "Hang_02", "Hang_03", "Hang_13", "Hang_10", "Hang_16", "Bone_East_15", "Cog_04", "Arborium_08", "Under_23",
		"Bellway_03", "Dock_15", "Dust_04"
	};

	private static readonly HashSet<string> SkipExits = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
	{
		"Bone_01_bot1", "Bone_01_left4", "Bone_01_right3", "Aspid_01_bot8", "Aspid_01_left2", "Aspid_01_right4", "Crawl_03b_right1", "Shellwood_10_left3", "Shellwood_10_right3", "Dust_02_left2",
		"Dust_02_right2", "Coral_24_left1", "Coral_24_right1", "Coral_35b_bot1", "Coral_35b_left5", "Coral_35b_right2", "Peak_07_bot5", "Peak_07_top2", "Peak_01_left4", "Peak_01_right4",
		"Peak_01_top4", "Peak_02_left3", "Peak_02_right4", "Peak_04_left1", "Peak_04_right1", "Peak_05_bot1", "Peak_05_right3", "Peak_05_top2", "Peak_05c_left2", "Peak_05c_right1",
		"Peak_05e_left1", "Peak_05e_right2", "Song_05_left5", "Song_05_right4", "Song_11_right3", "Song_01c"
	};

	private RoomRandomConfig _cachedConfig;

	private bool _hasPendingConfig;

	private bool _isInitialized;

	private Dictionary<string, HashSet<string>> _blacklistedExitsByScene;

	private Dictionary<string, int> _cachedActualExitCounts;

	public void Initialize(RandomSceneLoader loader)
	{
		sceneLoader = loader;
		if ((Object)(object)sceneLoader != (Object)null)
		{
			foreach (string key in sceneLoader.sceneConfigs.Keys)
			{
				if (key.StartsWith("Peak_", StringComparison.OrdinalIgnoreCase))
				{
					HighPriorityRooms.Add(key);
				}
				if (key.StartsWith("Ward_", StringComparison.OrdinalIgnoreCase))
				{
					HighPriorityRooms.Add(key);
				}
				if (key.StartsWith("Clover_", StringComparison.OrdinalIgnoreCase))
				{
					HighPriorityRooms.Add(key);
				}
			}
		}
		_isInitialized = true;
		if (_hasPendingConfig && _cachedConfig != null)
		{
			ApplyConfig();
		}
		else
		{
			InitializeRoomRando();
		}
	}

	public void SetConfig(RoomRandomConfig config)
	{
		_cachedConfig = config;
		_hasPendingConfig = true;
		if (_isInitialized)
		{
			ApplyConfig();
		}
	}

	private void ApplyConfig()
	{
		if (_cachedConfig != null)
		{
			generationSeed = _cachedConfig.Seed;
			enableRandomization = _cachedConfig.EnableRandomization;
			enableMapGeneration = _cachedConfig.EnableMapGeneration;
			precedencePairs = new List<(string, string)>(_cachedConfig.PrecedencePairs);
			_hasPendingConfig = false;
			if (enableRandomization)
			{
				InitializeRoomRando();
			}
		}
	}

	private void InitializeRoomRando()
	{
		try
		{
			availableScenes = sceneLoader.sceneConfigs.Keys.ToList();
			BuildCaches();
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("RoomRando: failed to populate availableScenes from sceneLoader: " + ex.Message));
		}
		try
		{
			saveFilePath = Path.Combine(Paths.PluginPath, "roomrando_connections.txt");
		}
		catch
		{
			saveFilePath = "roomrando_connections.txt";
		}
		Debug.Log((object)$"RoomRando: saveFilePath set to '{saveFilePath}' (exists={File.Exists(saveFilePath)})");
		if (!enableRandomization)
		{
			return;
		}
		if (TryLoadConnectionsFromFile())
		{
			bool flag = false;
			foreach (KeyValuePair<string, (string, string)> connection in connections)
			{
				int num = connection.Key.LastIndexOf('_');
				if (num > 0)
				{
					string sceneA = connection.Key.Substring(0, num);
					string exitA = connection.Key.Substring(num + 1);
					string item = connection.Value.Item1;
					string item2 = connection.Value.Item2;
					if (!IsConnectionAllowed(sceneA, exitA, item, item2))
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
			{
				Debug.LogWarning((object)"RoomRando: Loaded connections conflict with current rules. Forcing regeneration...");
				connections.Clear();
				GenerateAllConnectionsAtStart();
				SaveConnectionsToFile();
			}
			else
			{
				Debug.Log((object)("RoomRando: loaded randomized connections from " + saveFilePath));
			}
		}
		else
		{
			GenerateAllConnectionsAtStart();
			SaveConnectionsToFile();
		}
		if (enableMapGeneration)
		{
			TryGenerateMap();
		}
	}

	private void GenerateAllConnectionsAtStart()
	{
		int num = ((generationSeed == 0) ? Environment.TickCount : generationSeed);
		int finalConnectionCount = 0;
		RandomSceneLoader.SceneConfig value3;
		List<string> list = availableScenes.Where((string s) => (Object)(object)sceneLoader != (Object)null && sceneLoader.sceneConfigs.TryGetValue(s, out value3) && value3.Exits != null && value3.Exits.Count > 0).ToList();
		List<string> list2 = new List<string>();
		List<string> list3 = new List<string>();
		List<string> list4 = new List<string>();
		foreach (string item4 in list)
		{
			if (GetActualExitCount(item4) == 1)
			{
				list4.Add(item4);
			}
			else if (HighPriorityRooms.Contains(item4))
			{
				list3.Add(item4);
			}
			else
			{
				list2.Add(item4);
			}
		}
		Debug.Log((object)$"RoomRando: 普通房间(>1出口)数量: {list2.Count}, 高房间(>1出口)数量: {list3.Count}, 单出口房间数量: {list4.Count}");
		bool flag = false;
		int num2 = (forceExactSeed ? 1 : 8);
		for (int num3 = 0; num3 < num2; num3++)
		{
			if (flag)
			{
				break;
			}
			int num4 = (forceExactSeed ? num : (num + num3));
			rng = new Random(num4);
			connections.Clear();
			finalConnectionCount = 0;
			Debug.Log((object)$"RoomRando: generation attempt {num3 + 1}/{num2} using seed={num4}");
			Dictionary<string, List<string>> dictionary = BuildFreeExits(list2);
			SingleExitPairedCounts.Clear();
			foreach (KeyValuePair<string, (string, string)> item5 in connections.ToList())
			{
				int num5 = item5.Key.LastIndexOf('_');
				if (num5 > 0)
				{
					string key = item5.Key.Substring(0, num5);
					string item = item5.Key.Substring(num5 + 1);
					if (dictionary.ContainsKey(key))
					{
						dictionary[key].Remove(item);
					}
				}
			}
			try
			{
				foreach (var (text, text2) in precedencePairs)
				{
					if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && dictionary.ContainsKey(text) && dictionary.ContainsKey(text2) && dictionary[text].Count > 0 && dictionary[text2].Count > 0)
					{
						ConnectScenesWithFreeExits(text, text2, dictionary);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("precedencePairs error: " + ex.Message));
			}
			List<string> list5 = new List<string>(list2);
			Shuffle(list5);
			for (int num6 = 1; num6 < list5.Count; num6++)
			{
				string text3 = null;
				string text4 = null;
				for (int num7 = num6 - 1; num7 >= 0; num7--)
				{
					if (dictionary[list5[num7]].Count > 0)
					{
						text3 = list5[num7];
						break;
					}
				}
				for (int num8 = num6; num8 < list5.Count; num8++)
				{
					if (dictionary[list5[num8]].Count > 0)
					{
						text4 = list5[num8];
						break;
					}
				}
				if (text3 != null && text4 != null && !string.Equals(text3, text4, StringComparison.OrdinalIgnoreCase))
				{
					ConnectScenesWithFreeExits(text3, text4, dictionary);
				}
			}
			Dictionary<string, HashSet<string>> neighbors = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
			foreach (KeyValuePair<string, (string, string)> connection in connections)
			{
				int num9 = connection.Key.LastIndexOf('_');
				if (num9 > 0)
				{
					AddNeighborEdge(neighbors, connection.Key.Substring(0, num9), connection.Value.Item1);
				}
			}
			List<(string, string)> collection = dictionary.SelectMany((KeyValuePair<string, List<string>> kv) => kv.Value.Select((string e) => (Key: kv.Key, e: e))).ToList();
			bool flag2 = false;
			int num10 = 6;
			for (int num11 = 0; num11 < num10; num11++)
			{
				if (flag2)
				{
					break;
				}
				List<(string, string)> list6 = new List<(string, string)>(collection);
				Shuffle(list6);
				HashSet<int> hashSet = new HashSet<int>();
				List<((string, string), (string, string))> list7 = new List<((string, string), (string, string))>();
				bool flag3 = false;
				for (int num12 = 0; num12 < list6.Count; num12++)
				{
					if (hashSet.Contains(num12))
					{
						continue;
					}
					(string, string) tuple2 = list6[num12];
					int num13 = -1;
					int num14 = int.MinValue;
					for (int num15 = num12 + 1; num15 < list6.Count; num15++)
					{
						if (hashSet.Contains(num15))
						{
							continue;
						}
						(string, string) tuple3 = list6[num15];
						if (!string.Equals(tuple2.Item1, tuple3.Item1, StringComparison.OrdinalIgnoreCase))
						{
							int num16 = 0;
							if (!IsOriginalSingle(tuple3.Item1))
							{
								num16 += 20;
							}
							if (!IsOriginalSingle(tuple2.Item1))
							{
								num16 += 10;
							}
							if (IsOriginalSingle(tuple2.Item1) && IsOriginalSingle(tuple3.Item1))
							{
								num16 -= 1000;
							}
							neighbors.TryGetValue(tuple2.Item1, out var value);
							neighbors.TryGetValue(tuple3.Item1, out var value2);
							int num17 = value?.Count((string n) => IsLeaf(neighbors, n)) ?? 0;
							int num18 = value2?.Count((string n) => IsLeaf(neighbors, n)) ?? 0;
							bool flag4 = IsLeaf(neighbors, tuple3.Item1);
							bool flag5 = IsLeaf(neighbors, tuple2.Item1);
							if (num17 + (flag4 ? 1 : 0) > 1)
							{
								num16 -= 50;
							}
							if (num18 + (flag5 ? 1 : 0) > 1)
							{
								num16 -= 50;
							}
							if (num16 > num14)
							{
								num14 = num16;
								num13 = num15;
							}
						}
					}
					if (num13 < 0)
					{
						flag3 = true;
						break;
					}
					hashSet.Add(num12);
					hashSet.Add(num13);
					list7.Add((list6[num12], list6[num13]));
					AddNeighborEdge(neighbors, list6[num12].Item1, list6[num13].Item1);
				}
				if (flag3)
				{
					neighbors.Clear();
					foreach (KeyValuePair<string, (string, string)> connection2 in connections)
					{
						int num19 = connection2.Key.LastIndexOf('_');
						if (num19 > 0)
						{
							AddNeighborEdge(neighbors, connection2.Key.Substring(0, num19), connection2.Value.Item1);
						}
					}
					continue;
				}
				bool flag6 = false;
				foreach (var (tuple5, tuple6) in list7)
				{
					if (IsOriginalSingle(tuple5.Item1) && IsOriginalSingle(tuple6.Item1))
					{
						flag6 = true;
						break;
					}
				}
				Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
				foreach (KeyValuePair<string, HashSet<string>> item6 in neighbors)
				{
					dictionary2[item6.Key] = item6.Value.Count((string n) => IsLeaf(neighbors, n));
				}
				if (dictionary2.Values.Any((int c) => c > 1))
				{
					flag6 = true;
				}
				if (flag6)
				{
					neighbors.Clear();
					foreach (KeyValuePair<string, (string, string)> connection3 in connections)
					{
						int num20 = connection3.Key.LastIndexOf('_');
						if (num20 > 0)
						{
							AddNeighborEdge(neighbors, connection3.Key.Substring(0, num20), connection3.Value.Item1);
						}
					}
					continue;
				}
				foreach (var item7 in list7)
				{
					(string, string) item2 = item7.Item1;
					(string, string) item3 = item7.Item2;
					string key2 = MakeKey(item2.Item1, item2.Item2);
					string key3 = MakeKey(item3.Item1, item3.Item2);
					if (!connections.ContainsKey(key2) && !connections.ContainsKey(key3))
					{
						connections[key2] = (item3.Item1, item3.Item2);
						connections[key3] = (item2.Item1, item2.Item2);
						dictionary[item2.Item1].Remove(item2.Item2);
						dictionary[item3.Item1].Remove(item3.Item2);
						finalConnectionCount++;
					}
				}
				flag2 = true;
			}
			if (!flag2)
			{
				Debug.LogWarning((object)"第一阶段智能配对失败,使用贪心配对");
				List<(string, string)> list8 = new List<(string, string)>(collection);
				Shuffle(list8);
				for (int num21 = 0; num21 + 1 < list8.Count; num21 += 2)
				{
					(string, string) tuple7 = list8[num21];
					(string, string) tuple8 = list8[num21 + 1];
					if (!string.Equals(tuple7.Item1, tuple8.Item1, StringComparison.OrdinalIgnoreCase))
					{
						string key4 = MakeKey(tuple7.Item1, tuple7.Item2);
						string key5 = MakeKey(tuple8.Item1, tuple8.Item2);
						if (!connections.ContainsKey(key4) && !connections.ContainsKey(key5))
						{
							connections[key4] = (tuple8.Item1, tuple8.Item2);
							connections[key5] = (tuple7.Item1, tuple7.Item2);
							finalConnectionCount++;
							dictionary[tuple7.Item1].Remove(tuple7.Item2);
							dictionary[tuple8.Item1].Remove(tuple8.Item2);
						}
					}
				}
			}
			List<(string, string)> list9 = dictionary.SelectMany((KeyValuePair<string, List<string>> kv) => kv.Value.Select((string e) => (Key: kv.Key, e: e))).ToList();
			if (list9.Count > 0)
			{
				Debug.LogWarning((object)$"第一阶段剩余 {list9.Count} 个未配对出口");
			}
			Dictionary<string, List<string>> dictionary3 = BuildFreeExits(list3);
			List<(string, string)> list10 = new List<(string, string)>();
			list10.AddRange(list9);
			foreach (KeyValuePair<string, List<string>> item8 in dictionary3)
			{
				foreach (string item9 in item8.Value)
				{
					list10.Add((item8.Key, item9));
				}
			}
			if (list10.Count > 0)
			{
				Debug.Log((object)$"第二阶段开始,共 {list10.Count} 个出口");
				PairExitsSimple(list10);
			}
			neighbors.Clear();
			foreach (KeyValuePair<string, (string, string)> connection4 in connections)
			{
				int num22 = connection4.Key.LastIndexOf('_');
				if (num22 > 0)
				{
					AddNeighborEdge(neighbors, connection4.Key.Substring(0, num22), connection4.Value.Item1);
				}
			}
			bool flag7 = false;
			foreach (KeyValuePair<string, HashSet<string>> item10 in neighbors)
			{
				if (item10.Value.Count((string n) => IsLeaf(neighbors, n)) > 3)
				{
					flag7 = true;
					break;
				}
			}
			if (!flag7)
			{
				flag = true;
				generationSeed = num4;
				RandomSceneLoader.CurrentSeed = generationSeed;
				Debug.Log((object)$"成功,种子={num4}");
			}
			else
			{
				Debug.LogWarning((object)$"尝试 {num3 + 1} 失败:叶子节点过多");
			}
		}
		if (!flag)
		{
			Debug.LogWarning((object)$"所有尝试失败,使用最后一次结果,种子={generationSeed}");
		}
		Debug.Log((object)$"生成了 {finalConnectionCount} 对双向连接 ({connections.Count} 条单向)");
		static void AddNeighborEdge(Dictionary<string, HashSet<string>> graph, string s1, string s2)
		{
			if (!string.Equals(s1, s2, StringComparison.OrdinalIgnoreCase))
			{
				if (!graph.ContainsKey(s1))
				{
					graph[s1] = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				}
				if (!graph.ContainsKey(s2))
				{
					graph[s2] = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				}
				graph[s1].Add(s2);
				graph[s2].Add(s1);
			}
		}
		void ConnectScenesWithFreeExits(string scA, string scB, Dictionary<string, List<string>> freeExits)
		{
			if (freeExits.ContainsKey(scA) && freeExits.ContainsKey(scB) && freeExits[scA].Count != 0 && freeExits[scB].Count != 0)
			{
				string text5 = freeExits[scA][rng.Next(freeExits[scA].Count)];
				string text6 = freeExits[scB][rng.Next(freeExits[scB].Count)];
				if (IsConnectionAllowed(scA, text5, scB, text6))
				{
					string key6 = MakeKey(scA, text5);
					string key7 = MakeKey(scB, text6);
					if (!connections.ContainsKey(key6) && !connections.ContainsKey(key7))
					{
						connections[key6] = (scB, text6);
						connections[key7] = (scA, text5);
						freeExits[scA].Remove(text5);
						freeExits[scB].Remove(text6);
						finalConnectionCount++;
						UpdateSingleExitCount(scA, scB);
					}
				}
			}
		}
		static bool IsLeaf(Dictionary<string, HashSet<string>> graph, string scene)
		{
			if (graph.TryGetValue(scene, out value3))
			{
				return value3.Count == 1;
			}
			return false;
		}
		bool IsOriginalSingle(string scene)
		{
			if (sceneLoader.sceneConfigs.TryGetValue(scene, out value3) && value3.Exits != null)
			{
				return value3.Exits.Count == 1;
			}
			return false;
		}
	}

	private Dictionary<string, List<string>> BuildFreeExits(List<string> scenes)
	{
		Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
		foreach (string scene in scenes)
		{
			List<string> list = new List<string>(sceneLoader.sceneConfigs[scene].Exits);
			if (_blacklistedExitsByScene != null && _blacklistedExitsByScene.TryGetValue(scene, out var value))
			{
				foreach (string item in value)
				{
					list.Remove(item);
				}
			}
			dictionary[scene] = list;
		}
		return dictionary;
	}

	private void PairExitsSimple(List<(string scene, string exit)> exitPool)
	{
		List<(string, string)> list = new List<(string, string)>(exitPool);
		Shuffle(list);
		HashSet<int> hashSet = new HashSet<int>();
		for (int i = 0; i < list.Count; i++)
		{
			if (hashSet.Contains(i))
			{
				continue;
			}
			(string, string) tuple = list[i];
			int num = -1;
			for (int j = i + 1; j < list.Count; j++)
			{
				if (!hashSet.Contains(j))
				{
					(string, string) tuple2 = list[j];
					if (!string.Equals(tuple.Item1, tuple2.Item1, StringComparison.OrdinalIgnoreCase) && (!(tuple.Item1 == "Tut_01") || !HighPriorityRooms.Contains(tuple2.Item1)) && (!(tuple2.Item1 == "Tut_01") || !HighPriorityRooms.Contains(tuple.Item1)))
					{
						num = j;
						break;
					}
				}
			}
			if (num >= 0)
			{
				hashSet.Add(i);
				hashSet.Add(num);
				(string, string) tuple3 = list[num];
				string key = MakeKey(tuple.Item1, tuple.Item2);
				string key2 = MakeKey(tuple3.Item1, tuple3.Item2);
				if (!connections.ContainsKey(key) && !connections.ContainsKey(key2))
				{
					connections[key] = (tuple3.Item1, tuple3.Item2);
					connections[key2] = (tuple.Item1, tuple.Item2);
				}
			}
		}
		if (list.Count - hashSet.Count > 0)
		{
			Debug.LogWarning((object)$"第二阶段配对后剩余 {list.Count - hashSet.Count} 个未配对出口");
		}
	}

	private int GetActualExitCount(string scene)
	{
		if (_cachedActualExitCounts == null || !_cachedActualExitCounts.TryGetValue(scene, out var value))
		{
			return 0;
		}
		return value;
	}

	private bool IsConnectionAllowed(string sceneA, string exitA, string sceneB, string exitB)
	{
		if (string.Equals(sceneA, sceneB, StringComparison.OrdinalIgnoreCase))
		{
			return false;
		}
		if ((sceneA == "Tut_01" && HighPriorityRooms.Contains(sceneB)) || (sceneB == "Tut_01" && HighPriorityRooms.Contains(sceneA)))
		{
			return false;
		}
		string text = MakeKey(sceneA, exitA);
		string text2 = MakeKey(sceneB, exitB);
		if (BlacklistedExits.Contains(text) || BlacklistedExits.Contains(text2))
		{
			return false;
		}
		int value;
		int num = ((_cachedActualExitCounts != null && _cachedActualExitCounts.TryGetValue(sceneA, out value)) ? value : 0);
		int value2;
		int num2 = ((_cachedActualExitCounts != null && _cachedActualExitCounts.TryGetValue(sceneB, out value2)) ? value2 : 0);
		if (num == 1 && num2 < 3)
		{
			return false;
		}
		if (num2 == 1 && num < 3)
		{
			return false;
		}
		if (num == 1 && num2 >= 3 && (SingleExitPairedCounts.TryGetValue(sceneB, out var value3) ? value3 : 0) >= num2 - 2)
		{
			return false;
		}
		if (num2 == 1 && num >= 3 && (SingleExitPairedCounts.TryGetValue(sceneA, out var value4) ? value4 : 0) >= num - 2)
		{
			return false;
		}
		if (text == "Tut_01_left3" || text2 == "Tut_01_left3")
		{
			_ = text == "Tut_01_left3";
			_ = text == "Tut_01_left3";
			string item = ((text == "Tut_01_left3") ? text2 : text);
			if (((text == "Tut_01_left3") ? num2 : num) == 1)
			{
				return false;
			}
			if (new HashSet<string>(StringComparer.OrdinalIgnoreCase).Contains(item))
			{
				return false;
			}
		}
		return true;
	}

	private void UpdateSingleExitCount(string sceneA, string sceneB)
	{
		int value;
		int num = ((_cachedActualExitCounts != null && _cachedActualExitCounts.TryGetValue(sceneA, out value)) ? value : 0);
		int value2;
		int num2 = ((_cachedActualExitCounts != null && _cachedActualExitCounts.TryGetValue(sceneB, out value2)) ? value2 : 0);
		if (num == 1 && num2 >= 3)
		{
			if (!SingleExitPairedCounts.ContainsKey(sceneB))
			{
				SingleExitPairedCounts[sceneB] = 1;
			}
			else
			{
				SingleExitPairedCounts[sceneB]++;
			}
		}
		if (num2 == 1 && num >= 3)
		{
			if (!SingleExitPairedCounts.ContainsKey(sceneA))
			{
				SingleExitPairedCounts[sceneA] = 1;
			}
			else
			{
				SingleExitPairedCounts[sceneA]++;
			}
		}
	}

	private bool TryLoadConnectionsFromFile()
	{
		try
		{
			if (string.IsNullOrWhiteSpace(saveFilePath))
			{
				Debug.LogWarning((object)"RoomRando: saveFilePath is empty or null");
				return false;
			}
			if (!File.Exists(saveFilePath))
			{
				Debug.Log((object)("RoomRando: connections file not found at " + saveFilePath));
				return false;
			}
			string[] array = File.ReadAllLines(saveFilePath);
			Debug.Log((object)$"RoomRando: read {array.Length} lines from {saveFilePath}");
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i]?.Trim();
				if (string.IsNullOrWhiteSpace(text))
				{
					num = i + 1;
					continue;
				}
				if (text.StartsWith("#seed|", StringComparison.OrdinalIgnoreCase))
				{
					string[] array2 = text.Split(new char[1] { '|' });
					if (array2.Length >= 2 && int.TryParse(array2[1], out var result))
					{
						generationSeed = result;
						RandomSceneLoader.CurrentSeed = generationSeed;
						rng = new Random(generationSeed);
						Debug.Log((object)$"RoomRando: loaded generation seed {generationSeed} from {saveFilePath}");
					}
					num = i + 1;
				}
				else
				{
					num = i;
				}
				break;
			}
			int num2 = 0;
			int num3 = 0;
			for (int j = num; j < array.Length; j++)
			{
				string text2 = array[j];
				if (string.IsNullOrWhiteSpace(text2) || text2.StartsWith("#"))
				{
					continue;
				}
				string[] array3 = text2.Split(new char[1] { '|' });
				if (array3.Length != 4)
				{
					num3++;
					continue;
				}
				string text3 = array3[0] + "_" + array3[1];
				string item = array3[2] + "_" + array3[3];
				if (BlacklistedExits.Contains(text3) || BlacklistedExits.Contains(item))
				{
					num3++;
					continue;
				}
				connections[text3] = (array3[2], array3[3]);
				num2++;
			}
			Debug.Log((object)$"RoomRando: parsed {num2} connection lines, skipped {num3} invalid lines, total connections now {connections.Count}");
			if (num2 != 0 || generationSeed == 0)
			{
				return connections.Count > 0;
			}
			Debug.Log((object)$"RoomRando: file contained seed {generationSeed} but no explicit connections; will regenerate deterministically using that seed");
			return false;
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("RoomRando: failed to load connections file: " + ex.Message));
			return false;
		}
	}

	private void SaveConnectionsToFile()
	{
		try
		{
			using (StreamWriter streamWriter = new StreamWriter(saveFilePath, append: false))
			{
				if (generationSeed == 0)
				{
					generationSeed = Environment.TickCount;
				}
				streamWriter.WriteLine($"#seed|{generationSeed}");
				foreach (KeyValuePair<string, (string, string)> connection in connections)
				{
					string key = connection.Key;
					int num = key.LastIndexOf('_');
					if (num > 0)
					{
						string text = key.Substring(0, num);
						string text2 = key.Substring(num + 1);
						streamWriter.WriteLine(text + "|" + text2 + "|" + connection.Value.Item1 + "|" + connection.Value.Item2);
					}
				}
			}
			Debug.Log((object)$"RoomRando: saved {connections.Count} connections to {saveFilePath}");
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("RoomRando: failed to save connections: " + ex.Message));
		}
	}

	private void TryGenerateMap()
	{
		if (!enableMapGeneration)
		{
			Debug.Log((object)"RoomRando: map generation is disabled");
			return;
		}
		try
		{
			string text = Path.Combine(Paths.PluginPath, "RoomRandoMap.png");
			if (RoomMapGenerator.GenerateFromFile(saveFilePath, text))
			{
				Debug.Log((object)("RoomRando: generated map image at " + text));
			}
			else
			{
				Debug.LogWarning((object)"RoomRando: map generation reported failure or no data.");
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("RoomRando: map generation failed: " + ex.Message));
		}
	}

	private string MakeKey(string scene, string exit)
	{
		return scene + "_" + exit;
	}

	private void BuildCaches()
	{
		_blacklistedExitsByScene = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
		_cachedActualExitCounts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
		if ((Object)(object)sceneLoader == (Object)null)
		{
			return;
		}
		foreach (KeyValuePair<string, RandomSceneLoader.SceneConfig> sceneConfig in sceneLoader.sceneConfigs)
		{
			string key = sceneConfig.Key;
			RandomSceneLoader.SceneConfig value = sceneConfig.Value;
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			int num = 0;
			foreach (string exit in value.Exits)
			{
				string item = MakeKey(key, exit);
				if (BlacklistedExits.Contains(item))
				{
					hashSet.Add(exit);
					num++;
				}
			}
			_blacklistedExitsByScene[key] = hashSet;
			_cachedActualExitCounts[key] = value.Exits.Count - num;
		}
	}

	private void Shuffle<T>(IList<T> list)
	{
		for (int num = list.Count - 1; num > 0; num--)
		{
			int index = rng.Next(num + 1);
			T value = list[num];
			list[num] = list[index];
			list[index] = value;
		}
	}

	public (string targetScene, string targetGate)? GetConnection(string currentScene, string exitName)
	{
		if (string.IsNullOrEmpty(exitName))
		{
			return null;
		}
		if (!connections.TryGetValue(MakeKey(currentScene, exitName), out (string, string) value))
		{
			return null;
		}
		return value;
	}

	public List<string> GetValidExitsForScene(string sceneName)
	{
		if (!((Object)(object)sceneLoader != (Object)null) || !sceneLoader.sceneConfigs.TryGetValue(sceneName, out va

BepInEx/plugins/MenuChanger.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using GlobalEnums;
using HKSilksong_Randomizer;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using NativeUIMaker;
using PharloomCore;
using PharloomCore.Data;
using PharloomCore.Logic;
using PharloomCore.Model;
using SilksongItemRandomizer;
using StartingAbilityPicker;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[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;
		}
	}
}
namespace MenuChanger
{
	[BepInPlugin("YourName.MenuChanger", "Menu Changer", "1.0.0")]
	public class MenuChangerMod : BaseUnityPlugin
	{
		private Coroutine _delayedFullApplyCoroutine;

		private bool _uiRebuildInProgress;

		private static readonly PropertyInfo EnemyRandoEnabledProp = Type.GetType("SilksongItemRandomizer.EnemyRandoAdjuster, SilksongItemRandomizer")?.GetProperty("Enabled", BindingFlags.Static | BindingFlags.Public);

		private static readonly WaitForSeconds PointOneSecond = new WaitForSeconds(0.1f);

		private static readonly WaitForSeconds ThirtySeconds = new WaitForSeconds(30f);

		private static readonly Action[] ApplyActions = new Action[25]
		{
			delegate
			{
				StartingAbilityPickerAPI.SetAttackPermissions(SharedRuntimeSettings.AttackUp, SharedRuntimeSettings.AttackLeft, SharedRuntimeSettings.AttackRight);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetSkillRandomMode(SharedRuntimeSettings.UseTypeMode);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetStartingItemCount(SharedRuntimeSettings.ItemCount);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetSeed(SharedRuntimeSettings.Seed);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetResetSeedWorld(SharedRuntimeSettings.ResetSeedWorld);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetFullRandomMode(SharedRuntimeSettings.FullRandomMode);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetForceCompletionDisplay(SharedRuntimeSettings.ForceCompletionDisplay);
			},
			delegate
			{
				StartingAbilityPickerAPI.SetMovementPermissions(NativeConfigPanel.BuildCurrentDirectionPermissions());
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetEnabled(SharedRuntimeSettings.ItemRandomEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetCrestRandomEnabled(SharedRuntimeSettings.CrestRandomEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetSkillItemRandomEnabled(SharedRuntimeSettings.SkillItemRandomEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetRelicRandomEnabled(SharedRuntimeSettings.RelicRandomEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetSilkRandomEnabled(SharedRuntimeSettings.SilkRandomEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetTrapEnabled(SharedRuntimeSettings.TrapEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetTrapMovementEnabled(SharedRuntimeSettings.TrapMovementEnabled);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetTrapDifficulty(SharedRuntimeSettings.TrapDifficulty);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetCurrencyThresholds(SharedRuntimeSettings.CurrencyFirstThreshold, SharedRuntimeSettings.CurrencySecondThreshold);
			},
			delegate
			{
				SilksongItemRandomizerAPI.SetSilkSpearPityCount(SharedRuntimeSettings.SilkSpearPityCount);
			},
			delegate
			{
				HKSilksong_RandomizerAPI.SetMode(SharedRuntimeSettings.RoomRandomizerMode);
			},
			delegate
			{
				HKSilksong_RandomizerAPI.SetEnabled(SharedRuntimeSettings.SceneRandomEnabled);
			},
			delegate
			{
				HKSilksong_RandomizerAPI.SetShowSceneLabel(SharedRuntimeSettings.ShowSceneLabel);
			},
			delegate
			{
				HKSilksong_RandomizerAPI.SetShowSeedOnScreen(SharedRuntimeSettings.ShowSeedLabel);
			},
			delegate
			{
				if (SharedRuntimeSettings.RoomSeed != 0)
				{
					HKSilksong_RandomizerAPI.RegenerateWithSeed(SharedRuntimeSettings.RoomSeed);
				}
			},
			delegate
			{
				EnemyRandoEnabledProp?.SetValue(null, SharedRuntimeSettings.EnemyRandomEnabled);
			}
		};

		internal static MenuChangerMod Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Harmony.CreateAndPatchAll(typeof(PlayModeMenuPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(SkipToFirstAct), (string)null);
			SceneManager.sceneLoaded += OnSceneLoaded;
			((MonoBehaviour)this).StartCoroutine(DelayedInit());
		}

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

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name == "Menu_Title")
			{
				((MonoBehaviour)this).StartCoroutine(EnsureUIRebuiltAfterSceneReload());
			}
		}

		private IEnumerator EnsureUIRebuiltAfterSceneReload()
		{
			if (_uiRebuildInProgress)
			{
				yield break;
			}
			_uiRebuildInProgress = true;
			try
			{
				UIManager ui = null;
				while ((Object)(object)ui == (Object)null)
				{
					ui = Object.FindObjectOfType<UIManager>();
					if ((Object)(object)ui == (Object)null)
					{
						yield return PointOneSecond;
					}
					else
					{
						yield return null;
					}
				}
				while ((Object)(object)ui.UICanvas == (Object)null)
				{
					yield return null;
				}
				yield return null;
				if (UIManagerEx.IsUIReady && UIManagerEx.IsUIDestroyed())
				{
					Debug.Log((object)"[MenuChanger] 检测到 UI 已随场景销毁,开始重建 UI...");
					UIManagerEx.ResetUI();
					NativeConfigPanel.Instance.Reset();
					yield return PerformUIFullInit();
				}
			}
			finally
			{
				_uiRebuildInProgress = false;
			}
		}

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

		private IEnumerator DelayedInit()
		{
			yield return PerformUIFullInit();
		}

		private IEnumerator PerformUIFullInit()
		{
			UIManager ui = null;
			while ((Object)(object)ui == (Object)null)
			{
				ui = Object.FindObjectOfType<UIManager>();
				if ((Object)(object)ui == (Object)null)
				{
					yield return PointOneSecond;
				}
				else
				{
					yield return null;
				}
			}
			while ((Object)(object)ui.UICanvas == (Object)null)
			{
				yield return null;
			}
			yield return null;
			PrefabMenuObjects.Initialize();
			yield return null;
			NativeConfigPanel.Instance.Initialize();
			yield return null;
			string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "NativeUIMaker_Config.json");
			if (!File.Exists(text))
			{
				text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "PageConfigs", "NativeUIMaker_Config.json");
			}
			UIManagerEx.InitializeUI(text);
			yield return null;
			while (!UIManagerEx.IsUIReady)
			{
				yield return null;
			}
			LoadSharedSettingsFromAPIs();
			NativeConfigPanel.Instance.RefreshPageList();
			NativeConfigPanel.Instance.RefreshAllValues();
			Canvas.ForceUpdateCanvases();
			Debug.Log((object)"[MenuChanger] 初始化完成");
			ApplyModeSelectButtonIcons();
			ApplySharedSettingsToModules();
			if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.ShowUI)
			{
				Plugin.Instance.ShowUI = false;
				Plugin.Instance.ShowUI = true;
			}
		}

		private void ApplyModeSelectButtonIcons()
		{
			try
			{
				Dictionary<string, string> dictionary = new Dictionary<string, string>
				{
					{ "ClassicModeBtn", "Icons/classic.png" },
					{ "SteelModeBtn", "Icons/steel.png" },
					{ "RandomModeBtn", "Icons/random.png" }
				};
				foreach (NativeButton allInstance in NativeButton.AllInstances)
				{
					if (allInstance != null && !((Object)(object)allInstance.gameObject == (Object)null) && dictionary.TryGetValue(((Object)allInstance.gameObject).name, out var value))
					{
						allInstance.SetIconFromFile(value);
						allInstance.SetIconScale(2f / 3f);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[MenuChanger] 应用模式按钮图标失败: " + ex.Message));
			}
		}

		private void LoadSharedSettingsFromAPIs()
		{
			try
			{
				SharedRuntimeSettings.SceneRandomEnabled = HKSilksong_RandomizerAPI.IsSceneRandomEnabled();
				SharedRuntimeSettings.ShowSceneLabel = HKSilksong_RandomizerAPI.GetShowSceneLabel();
				SharedRuntimeSettings.ShowSeedLabel = HKSilksong_RandomizerAPI.GetShowSeedOnScreen();
				SharedRuntimeSettings.RoomSeed = HKSilksong_RandomizerAPI.GetCurrentRoomSeed();
				SharedRuntimeSettings.RoomRandomizerMode = HKSilksong_RandomizerAPI.GetMode();
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[MenuChanger] 加载 SceneRandomizer 配置失败: " + ex.Message));
			}
			try
			{
				SharedRuntimeSettings.ItemRandomEnabled = SilksongItemRandomizerAPI.IsEnabled();
				SharedRuntimeSettings.CrestRandomEnabled = SilksongItemRandomizerAPI.IsCrestRandomEnabled();
				SharedRuntimeSettings.SkillItemRandomEnabled = SilksongItemRandomizerAPI.IsSkillItemRandomEnabled();
				SharedRuntimeSettings.RelicRandomEnabled = SilksongItemRandomizerAPI.IsRelicRandomEnabled();
				SharedRuntimeSettings.SilkRandomEnabled = SilksongItemRandomizerAPI.IsSilkRandomEnabled();
				SharedRuntimeSettings.TrapEnabled = SilksongItemRandomizerAPI.IsTrapEnabled();
				SharedRuntimeSettings.TrapMovementEnabled = SilksongItemRandomizerAPI.IsTrapMovementEnabled();
				SharedRuntimeSettings.TrapDifficulty = SilksongItemRandomizerAPI.GetTrapDifficulty();
				ValueTuple<int, int> currencyThresholds = SilksongItemRandomizerAPI.GetCurrencyThresholds();
				SharedRuntimeSettings.CurrencyFirstThreshold = currencyThresholds.Item1;
				SharedRuntimeSettings.CurrencySecondThreshold = currencyThresholds.Item2;
				SharedRuntimeSettings.SilkSpearPityCount = SilksongItemRandomizerAPI.GetSilkSpearPityCount();
				SharedRuntimeSettings.AttackUp = GlobalConfig.AttackUp.Value;
				SharedRuntimeSettings.AttackLeft = GlobalConfig.AttackLeft.Value;
				SharedRuntimeSettings.AttackRight = GlobalConfig.AttackRight.Value;
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[MenuChanger] 加载 SilksongItemRandomizer 配置失败: " + ex2.Message));
			}
			try
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					SharedRuntimeSettings.Seed = Plugin.RandomSeed.Value;
					SharedRuntimeSettings.FullRandomMode = Plugin.CfgFullRandomMode.Value;
					SharedRuntimeSettings.DashLeft = Plugin.CfgAllowDashLeft.Value;
					SharedRuntimeSettings.DashRight = Plugin.CfgAllowDashRight.Value;
					SharedRuntimeSettings.HarpoonLeft = Plugin.CfgAllowHarpoonLeft.Value;
					SharedRuntimeSettings.HarpoonRight = Plugin.CfgAllowHarpoonRight.Value;
					SharedRuntimeSettings.FloatLeft = Plugin.CfgAllowFloatLeft.Value;
					SharedRuntimeSettings.FloatRight = Plugin.CfgAllowFloatRight.Value;
					SharedRuntimeSettings.WallJumpLeft = Plugin.CfgAllowWallJumpLeft.Value;
					SharedRuntimeSettings.WallJumpRight = Plugin.CfgAllowWallJumpRight.Value;
					SharedRuntimeSettings.AllowHeal = Plugin.CfgAllowHeal.Value;
				}
			}
			catch (Exception ex3)
			{
				Debug.LogWarning((object)("[MenuChanger] 加载 StartingAbilityPicker 配置失败: " + ex3.Message));
			}
			try
			{
				SharedRuntimeSettings.SkillTriggerEnabled = false;
			}
			catch (Exception ex4)
			{
				Debug.LogWarning((object)("[MenuChanger] SkillTriggerMod 已停用: " + ex4.Message));
			}
			try
			{
				if (EnemyRandoEnabledProp != null)
				{
					SharedRuntimeSettings.EnemyRandomEnabled = (bool)EnemyRandoEnabledProp.GetValue(null);
				}
			}
			catch (Exception ex5)
			{
				Debug.LogWarning((object)("[MenuChanger] 加载 EnemyRandomizer 配置失败: " + ex5.Message));
			}
			Debug.Log((object)"[MenuChanger] SharedRuntimeSettings 已从各模块配置填充");
		}

		public void ApplySharedSettingsToModules()
		{
			for (int i = 0; i < ApplyActions.Length; i++)
			{
				ApplyActions[i]();
			}
		}

		public IEnumerator ApplySharedSettingsStaggered()
		{
			for (int i = 0; i < ApplyActions.Length; i++)
			{
				ApplyActions[i]();
				yield return null;
			}
		}

		public static void HideAllMenuPages()
		{
			if (NativeConfigPanel.Instance != null && NativeConfigPanel.Instance.IsShowing)
			{
				NativeConfigPanel.Instance.Hide();
			}
		}

		public void StartDelayedFullApply()
		{
			if (_delayedFullApplyCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_delayedFullApplyCoroutine);
			}
			_delayedFullApplyCoroutine = ((MonoBehaviour)this).StartCoroutine(DelayedFullApplyCoroutine());
		}

		private IEnumerator DelayedFullApplyCoroutine()
		{
			yield return ThirtySeconds;
			Debug.Log((object)"[MenuChanger] 30秒延迟到达,开始重置所有随机数据...");
			SilksongItemRandomizerAPI.ResetAllData();
			ApplySharedSettingsToModules();
			_delayedFullApplyCoroutine = null;
		}
	}
	[HarmonyPatch(typeof(UIManager))]
	public static class PlayModeMenuPatch
	{
		private static readonly MethodInfo SetMenuStateMethod = typeof(UIManager).GetMethod("SetMenuState", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly object[] SetMenuStateArgs = new object[1];

		[HarmonyPrefix]
		[HarmonyPatch("UIGoToPlayModeMenu")]
		public static bool Prefix(UIManager __instance)
		{
			if (!UIManagerEx.IsUIReady)
			{
				return true;
			}
			((MonoBehaviour)__instance).StartCoroutine(ShowModeSelect(__instance));
			return false;
		}

		private static IEnumerator ShowModeSelect(UIManager ui)
		{
			ManagerSingleton<InputHandler>.Instance.StopUIInput();
			if ((int)ui.menuState == 6)
			{
				yield return ui.HideSaveProfileMenu(true);
			}
			UIManagerEx.ShowPage("ModeSelect");
			NativeConfigPanel.Instance.RefreshAllValues();
			ManagerSingleton<InputHandler>.Instance.StartUIInput();
			SetMenuStateArgs[0] = (object)(MainMenuState)18;
			SetMenuStateMethod?.Invoke(ui, SetMenuStateArgs);
		}
	}
	public class NativeConfigPanel
	{
		private static NativeConfigPanel _instance;

		private GameObject root;

		private CanvasGroup canvasGroup;

		private UIManager uiManager;

		private NativePage parentPage;

		private NativeLabel pageIndicator;

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

		private bool _seedRolling;

		private bool _seedRolledOnce;

		private bool _seedRollCanceled;

		private bool _seedUserProvided;

		private List<NativeInput> _repeatLimitInputs = new List<NativeInput>();

		private static readonly Type EnemyRandoAdjusterType = Type.GetType("SilksongItemRandomizer.EnemyRandoAdjuster, SilksongItemRandomizer");

		private static readonly PropertyInfo EnemyEnabledProp = EnemyRandoAdjusterType?.GetProperty("Enabled", BindingFlags.Static | BindingFlags.Public);

		private static readonly PropertyInfo ScaleRandomEnabledProp = EnemyRandoAdjusterType?.GetProperty("ScaleRandomEnabled", BindingFlags.Static | BindingFlags.Public);

		private static readonly PropertyInfo ScaleMinProp = EnemyRandoAdjusterType?.GetProperty("ScaleMin", BindingFlags.Static | BindingFlags.Public);

		private static readonly PropertyInfo ScaleMaxProp = EnemyRandoAdjusterType?.GetProperty("ScaleMax", BindingFlags.Static | BindingFlags.Public);

		private static readonly Type ExtraCurrencyType = Type.GetType("SilksongItemRandomizer.Extracurrencypickup, SilksongItemRandomizer");

		private static readonly MethodInfo ExtraCurrencyResetAll = ExtraCurrencyType?.GetMethod("ResetAll", BindingFlags.Static | BindingFlags.Public);

		private static readonly Type TrapRandomizerType = Type.GetType("SilksongItemRandomizer.TrapRandomizer, SilksongItemRandomizer");

		private static readonly MethodInfo ResetFrostBanned = TrapRandomizerType?.GetMethod("ResetFrostBannedScenes", BindingFlags.Static | BindingFlags.Public);

		private readonly Dictionary<string, NativeButton> _buttonCache = new Dictionary<string, NativeButton>();

		private readonly Dictionary<string, NativeSlider> _sliderCache = new Dictionary<string, NativeSlider>();

		private readonly Dictionary<string, NativeInput> _inputCache = new Dictionary<string, NativeInput>();

		private readonly Dictionary<string, NativeOption> _optionCache = new Dictionary<string, NativeOption>();

		private readonly Dictionary<string, NativeLabel> _labelCache = new Dictionary<string, NativeLabel>();

		private static readonly string[] CategoryButtonNames = new string[6] { "CategoryBtn1", "CategoryBtn2", "CategoryBtn3", "CategoryBtn4", "CategoryBtn5", "CategoryBtn6" };

		private static readonly Color DisabledTextColor = new Color(0.8f, 0.8f, 0.8f);

		private static readonly string[] TrapDifficultyNames = new string[3] { "初猎", "专注", "满溢" };

		private EventHandler<NativeUIEventArgs> _uiEventHandler;

		public static NativeConfigPanel Instance => _instance ?? (_instance = new NativeConfigPanel());

		public bool IsShowing
		{
			get
			{
				if ((Object)(object)root != (Object)null)
				{
					return root.activeSelf;
				}
				return false;
			}
		}

		private NativeButton GetCachedButton(string name)
		{
			if (!_buttonCache.TryGetValue(name, out var value))
			{
				value = ((IEnumerable<NativeButton>)NativeButton.AllInstances).FirstOrDefault((Func<NativeButton, bool>)((NativeButton b) => ((Object)b.gameObject).name == name));
				if (value != null)
				{
					_buttonCache[name] = value;
				}
			}
			return value;
		}

		private NativeSlider GetCachedSlider(string name)
		{
			if (!_sliderCache.TryGetValue(name, out var value))
			{
				value = ((IEnumerable<NativeSlider>)NativeSlider.AllInstances).FirstOrDefault((Func<NativeSlider, bool>)((NativeSlider sl) => ((Object)sl.gameObject).name == name));
				if (value != null)
				{
					_sliderCache[name] = value;
				}
			}
			return value;
		}

		private NativeInput GetCachedInput(string name)
		{
			if (!_inputCache.TryGetValue(name, out var value))
			{
				value = ((IEnumerable<NativeInput>)NativeInput.AllInstances).FirstOrDefault((Func<NativeInput, bool>)((NativeInput inp) => ((Object)inp.gameObject).name == name));
				if (value != null)
				{
					_inputCache[name] = value;
				}
			}
			return value;
		}

		private NativeOption GetCachedOption(string name)
		{
			if (!_optionCache.TryGetValue(name, out var value))
			{
				value = ((IEnumerable<NativeOption>)NativeOption.AllInstances).FirstOrDefault((Func<NativeOption, bool>)((NativeOption opt) => ((Object)opt.gameObject).name == name));
				if (value != null)
				{
					_optionCache[name] = value;
				}
			}
			return value;
		}

		private NativeLabel GetCachedLabel(string name)
		{
			if (!_labelCache.TryGetValue(name, out var value))
			{
				value = ((IEnumerable<NativeLabel>)NativeLabel.AllInstances).FirstOrDefault((Func<NativeLabel, bool>)((NativeLabel lb) => ((Object)lb.gameObject).name == name));
				if (value != null)
				{
					_labelCache[name] = value;
				}
			}
			return value;
		}

		private NativeConfigPanel()
		{
		}

		public void Reset()
		{
			root = null;
			canvasGroup = null;
			uiManager = null;
			parentPage = null;
			pageIndicator = null;
			pageOrder.Clear();
			_repeatLimitInputs.Clear();
			_buttonCache.Clear();
			_sliderCache.Clear();
			_inputCache.Clear();
			_optionCache.Clear();
			_labelCache.Clear();
		}

		public void Initialize()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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)
			if (!((Object)(object)root != (Object)null))
			{
				PrefabMenuObjects.Initialize();
				uiManager = UIManager.instance;
				if (!((Object)(object)uiManager == (Object)null))
				{
					root = new GameObject("NativeConfigPanel");
					root.transform.SetParent(((Component)uiManager.UICanvas).transform, false);
					canvasGroup = root.AddComponent<CanvasGroup>();
					canvasGroup.alpha = 0f;
					canvasGroup.interactable = false;
					canvasGroup.blocksRaycasts = false;
					root.SetActive(false);
					GameObject val = new GameObject("Panel");
					val.transform.SetParent(root.transform, false);
					RectTransform val2 = val.AddComponent<RectTransform>();
					val2.sizeDelta = new Vector2(1200f, 800f);
					val2.anchorMin = Vector2.zero;
					val2.anchorMax = Vector2.one;
					val2.pivot = new Vector2(0.5f, 0.5f);
					val2.anchoredPosition = Vector2.zero;
					pageIndicator = NativeLabel.Create(val2);
					pageIndicator.SetText("1/1");
					pageIndicator.SetFontSize(32);
					pageIndicator.SetPosition(new Vector2(0f, -420f));
					pageIndicator.SetSize(200f, 60f);
					pageIndicator.SetAlignment((TextAnchor)4);
					pageIndicator.gameObject.SetActive(false);
					SubscribeToGlobalEvents();
					BindRepeatLimitInputs();
					RefreshAllValues();
				}
			}
		}

		public void StartAutoSeedRoll()
		{
			if (!_seedRolledOnce)
			{
				_seedRolledOnce = true;
				if ((Object)(object)uiManager != (Object)null)
				{
					((MonoBehaviour)uiManager).StartCoroutine(RollSeedCoroutine());
				}
			}
		}

		public void ResetAllToDefaults()
		{
			SharedRuntimeSettings.SceneRandomEnabled = false;
			SharedRuntimeSettings.ItemRandomEnabled = true;
			SharedRuntimeSettings.TrapEnabled = false;
			SharedRuntimeSettings.FullRandomMode = false;
			SharedRuntimeSettings.CrestRandomEnabled = false;
			SharedRuntimeSettings.SkillItemRandomEnabled = SilksongItemRandomizerAPI.IsSkillItemRandomEnabled();
			SharedRuntimeSettings.RelicRandomEnabled = SilksongItemRandomizerAPI.IsRelicRandomEnabled();
			SharedRuntimeSettings.SilkRandomEnabled = false;
			SharedRuntimeSettings.EnemyRandomEnabled = false;
			StartingAbilityPickerAPI.SetEnemyRandomEnabled(false);
			SharedRuntimeSettings.ShowSceneLabel = true;
			SharedRuntimeSettings.ShowSeedLabel = true;
			SharedRuntimeSettings.TrapMovementEnabled = false;
			SharedRuntimeSettings.ForceCompletionDisplay = true;
			SilksongItemRandomizerAPI.SetEnabled(true);
			SilksongItemRandomizerAPI.SetTrapEnabled(false);
			SilksongItemRandomizerAPI.SetTrapMovementEnabled(false);
			SilksongItemRandomizerAPI.SetCrestRandomEnabled(false);
			SilksongItemRandomizerAPI.SetRelicRandomEnabled(SilksongItemRandomizerAPI.IsRelicRandomEnabled());
			SilksongItemRandomizerAPI.SetSilkRandomEnabled(false);
			SharedRuntimeSettings.SkillTotal = 0;
			SharedRuntimeSettings.SkillVertical = 0;
			SharedRuntimeSettings.SkillHorizontal = 0;
			SharedRuntimeSettings.SkillSpecial = 0;
			SharedRuntimeSettings.SkillAttack = 0;
			StartingAbilityPickerAPI.SetSkillCounts(0, 0, 0, 0, 0);
			SharedRuntimeSettings.ItemCount = 0;
			StartingAbilityPickerAPI.SetStartingItemCount(0);
			if (ScaleRandomEnabledProp != null)
			{
				ScaleRandomEnabledProp.SetValue(null, true);
			}
			if (ScaleMinProp != null)
			{
				ScaleMinProp.SetValue(null, 1f);
			}
			if (ScaleMaxProp != null)
			{
				ScaleMaxProp.SetValue(null, 1f);
			}
			SharedRuntimeSettings.AllowHeal = false;
			SharedRuntimeSettings.DashLeft = false;
			SharedRuntimeSettings.DashRight = false;
			SharedRuntimeSettings.HarpoonLeft = false;
			SharedRuntimeSettings.HarpoonRight = false;
			SharedRuntimeSettings.FloatLeft = false;
			SharedRuntimeSettings.FloatRight = false;
			SharedRuntimeSettings.WallJumpLeft = false;
			SharedRuntimeSettings.WallJumpRight = false;
			StartingAbilityPickerAPI.SetAttackPermissions(true, true, true);
			SharedRuntimeSettings.ColdResistOwned = false;
			SharedRuntimeSettings.SwimOwned = false;
			SharedRuntimeSettings.TrapDifficulty = 0;
			StartingAbilityPickerAPI.SaveAllSettingsToConfig();
			RefreshAllValues();
			try
			{
				SilksongItemRandomizerAPI.ResetAllData();
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[MenuChanger] 重置 SIR 本地数据失败: " + ex.Message));
			}
			if ((Object)(object)MenuChangerMod.Instance != (Object)null)
			{
				((MonoBehaviour)MenuChangerMod.Instance).StartCoroutine(MenuChangerMod.Instance.ApplySharedSettingsStaggered());
			}
		}

		private void BindRepeatLimitInputs()
		{
			NativePage val = ((IEnumerable<NativePage>)NativePage.AllInstances).FirstOrDefault((Func<NativePage, bool>)((NativePage p) => ((Object)p.gameObject).name == "RepeatLimitPage"));
			if (val == null)
			{
				return;
			}
			_repeatLimitInputs = val.gameObject.GetComponentsInChildren<NativeInput>(true).ToList();
			if (_repeatLimitInputs.Count == 0)
			{
				Debug.LogWarning((object)"[NativeConfigPanel] RepeatLimitPage 下没有找到任何 NativeInput 控件");
				return;
			}
			foreach (NativeInput repeatLimitInput in _repeatLimitInputs)
			{
				string name = ((Object)repeatLimitInput.gameObject).name;
				repeatLimitInput.AddTextChangedListener((Action<string>)delegate(string text)
				{
					if (int.TryParse(text, out var result))
					{
						int limitValue = GetLimitValue(name);
						switch (name)
						{
						case "Input_LimitSkillItem":
							ItemLimitConfig.LimitSkillItem = result;
							break;
						case "Input_LimitRelic":
							ItemLimitConfig.LimitRelic = result;
							break;
						case "Input_LimitOtherItem":
							ItemLimitConfig.LimitOtherItem = result;
							break;
						case "Input_LimitUpSlash":
							ItemLimitConfig.LimitUpSlash = result;
							break;
						case "Input_LimitLeftSlash":
							ItemLimitConfig.LimitLeftSlash = result;
							break;
						case "Input_LimitRightSlash":
							ItemLimitConfig.LimitRightSlash = result;
							break;
						case "Input_LimitDashLeft":
							ItemLimitConfig.LimitDashLeft = result;
							break;
						case "Input_LimitDashRight":
							ItemLimitConfig.LimitDashRight = result;
							break;
						case "Input_LimitHarpoonLeft":
							ItemLimitConfig.LimitHarpoonLeft = result;
							break;
						case "Input_LimitHarpoonRight":
							ItemLimitConfig.LimitHarpoonRight = result;
							break;
						case "Input_LimitFloatLeft":
							ItemLimitConfig.LimitFloatLeft = result;
							break;
						case "Input_LimitFloatRight":
							ItemLimitConfig.LimitFloatRight = result;
							break;
						case "Input_LimitWallJumpLeft":
							ItemLimitConfig.LimitWallJumpLeft = result;
							break;
						case "Input_LimitWallJumpRight":
							ItemLimitConfig.LimitWallJumpRight = result;
							break;
						case "Input_LimitHeal":
							ItemLimitConfig.LimitHeal = result;
							break;
						case "Input_LimitNeedleThrow":
							ItemLimitConfig.LimitNeedleThrow = result;
							break;
						case "Input_LimitThreadSphere":
							ItemLimitConfig.LimitThreadSphere = result;
							break;
						case "Input_LimitHarpoonDash":
							ItemLimitConfig.LimitHarpoonDash = result;
							break;
						case "Input_LimitSilkCharge":
							ItemLimitConfig.LimitSilkCharge = result;
							break;
						case "Input_LimitSilkBomb":
							ItemLimitConfig.LimitSilkBomb = result;
							break;
						case "Input_LimitSilkBossNeedle":
							ItemLimitConfig.LimitSilkBossNeedle = result;
							break;
						case "Input_LimitNeedolin":
							ItemLimitConfig.LimitNeedolin = result;
							break;
						case "Input_LimitParry":
							ItemLimitConfig.LimitParry = result;
							break;
						case "Input_LimitNeedolinMemory":
							ItemLimitConfig.LimitNeedolinMemory = result;
							break;
						case "Input_LimitFastTravel":
							ItemLimitConfig.LimitFastTravel = result;
							break;
						case "Input_LimitEvaHeal":
							ItemLimitConfig.LimitEvaHeal = result;
							break;
						case "Input_LimitDash":
							ItemLimitConfig.LimitDash = result;
							break;
						case "Input_LimitBrolly":
							ItemLimitConfig.LimitBrolly = result;
							break;
						case "Input_LimitDoubleJump":
							ItemLimitConfig.LimitDoubleJump = result;
							break;
						case "Input_LimitSuperJump":
							ItemLimitConfig.LimitSuperJump = result;
							break;
						case "Input_LimitWallJump":
							ItemLimitConfig.LimitWallJump = result;
							break;
						case "Input_LimitChargeSlash":
							ItemLimitConfig.LimitChargeSlash = result;
							break;
						case "Input_LimitHeartPiece":
							ItemLimitConfig.LimitHeartPiece = result;
							break;
						case "Input_LimitSpoolPart":
							ItemLimitConfig.LimitSpoolPart = result;
							break;
						case "Input_LimitMaxSilkRegenUp":
							ItemLimitConfig.LimitMaxSilkRegenUp = result;
							break;
						case "Input_LimitUnlockCrestSlot":
							ItemLimitConfig.LimitUnlockCrestSlot = result;
							break;
						}
						if (GetLimitValue(name) != limitValue)
						{
							SilksongItemRandomizerAPI.SaveLimitsAndRegenerateMappings();
						}
					}
				});
				repeatLimitInput.SetText(GetLimitValue(name).ToString());
			}
		}

		private int GetLimitValue(string inputName)
		{
			return inputName switch
			{
				"Input_LimitSkillItem" => ItemLimitConfig.LimitSkillItem, 
				"Input_LimitRelic" => ItemLimitConfig.LimitRelic, 
				"Input_LimitOtherItem" => ItemLimitConfig.LimitOtherItem, 
				"Input_LimitUpSlash" => ItemLimitConfig.LimitUpSlash, 
				"Input_LimitLeftSlash" => ItemLimitConfig.LimitLeftSlash, 
				"Input_LimitRightSlash" => ItemLimitConfig.LimitRightSlash, 
				"Input_LimitDashLeft" => ItemLimitConfig.LimitDashLeft, 
				"Input_LimitDashRight" => ItemLimitConfig.LimitDashRight, 
				"Input_LimitHarpoonLeft" => ItemLimitConfig.LimitHarpoonLeft, 
				"Input_LimitHarpoonRight" => ItemLimitConfig.LimitHarpoonRight, 
				"Input_LimitFloatLeft" => ItemLimitConfig.LimitFloatLeft, 
				"Input_LimitFloatRight" => ItemLimitConfig.LimitFloatRight, 
				"Input_LimitWallJumpLeft" => ItemLimitConfig.LimitWallJumpLeft, 
				"Input_LimitWallJumpRight" => ItemLimitConfig.LimitWallJumpRight, 
				"Input_LimitHeal" => ItemLimitConfig.LimitHeal, 
				"Input_LimitNeedleThrow" => ItemLimitConfig.LimitNeedleThrow, 
				"Input_LimitThreadSphere" => ItemLimitConfig.LimitThreadSphere, 
				"Input_LimitHarpoonDash" => ItemLimitConfig.LimitHarpoonDash, 
				"Input_LimitSilkCharge" => ItemLimitConfig.LimitSilkCharge, 
				"Input_LimitSilkBomb" => ItemLimitConfig.LimitSilkBomb, 
				"Input_LimitSilkBossNeedle" => ItemLimitConfig.LimitSilkBossNeedle, 
				"Input_LimitNeedolin" => ItemLimitConfig.LimitNeedolin, 
				"Input_LimitParry" => ItemLimitConfig.LimitParry, 
				"Input_LimitNeedolinMemory" => ItemLimitConfig.LimitNeedolinMemory, 
				"Input_LimitFastTravel" => ItemLimitConfig.LimitFastTravel, 
				"Input_LimitEvaHeal" => ItemLimitConfig.LimitEvaHeal, 
				"Input_LimitDash" => ItemLimitConfig.LimitDash, 
				"Input_LimitBrolly" => ItemLimitConfig.LimitBrolly, 
				"Input_LimitDoubleJump" => ItemLimitConfig.LimitDoubleJump, 
				"Input_LimitSuperJump" => ItemLimitConfig.LimitSuperJump, 
				"Input_LimitWallJump" => ItemLimitConfig.LimitWallJump, 
				"Input_LimitChargeSlash" => ItemLimitConfig.LimitChargeSlash, 
				"Input_LimitHeartPiece" => ItemLimitConfig.LimitHeartPiece, 
				"Input_LimitSpoolPart" => ItemLimitConfig.LimitSpoolPart, 
				"Input_LimitMaxSilkRegenUp" => ItemLimitConfig.LimitMaxSilkRegenUp, 
				"Input_LimitUnlockCrestSlot" => ItemLimitConfig.LimitUnlockCrestSlot, 
				_ => 0, 
			};
		}

		private void RefreshRepeatLimitInputs()
		{
			foreach (NativeInput repeatLimitInput in _repeatLimitInputs)
			{
				repeatLimitInput.SetText(GetLimitValue(((Object)repeatLimitInput.gameObject).name).ToString());
			}
		}

		private void SubscribeToGlobalEvents()
		{
			if (_uiEventHandler != null)
			{
				NativeUIEventDispatcher.OnNativeUIEvent -= _uiEventHandler;
			}
			_uiEventHandler = delegate(object sender, NativeUIEventArgs args)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Invalid comparison between Unknown and I4
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Invalid comparison between Unknown and I4
				if ((int)args.EventType == 0)
				{
					HandleClickEvent(args);
				}
				else if ((int)args.EventType == 1)
				{
					HandleValueChangedEvent(args);
				}
				else if ((int)args.EventType == 2)
				{
					HandleOptionChangedEvent(args);
				}
			};
			NativeUIEventDispatcher.OnNativeUIEvent += _uiEventHandler;
		}

		private void HandleClickEvent(NativeUIEventArgs args)
		{
			if (args.ControlName == "CalcStartGameBtn")
			{
				Plugin.BlackoutShow();
			}
			if (args.ControlName == "RandomModeBtn")
			{
				ResetAllToDefaults();
				ShowPage(pageOrder.Contains("Main") ? "Main" : pageOrder[0]);
			}
			else if (args.ControlName == "ClassicModeBtn")
			{
				StartGame(permaDeath: false);
			}
			else if (args.ControlName == "SteelModeBtn")
			{
				StartGame(permaDeath: true);
			}
			else if (args.ControlName == "DetailBtn")
			{
				UIManagerEx.ShowPage("Detail0");
			}
			else if (args.ControlName == "BackToMainBtn_Calc")
			{
				_seedRollCanceled = true;
				NativeLabel cachedLabel = GetCachedLabel("SeedCalcStatus");
				if (cachedLabel != null)
				{
					cachedLabel.SetText(UILocale.Get("计算已取消,返回设置页"));
				}
				ShowPage("Main");
			}
			else if (args.ControlName.StartsWith("BackToMainBtn"))
			{
				ShowPage("Main");
			}
			else if (args.ControlName == "BackToModeSelectBtn")
			{
				ShowPage("ModeSelect");
			}
			else if (args.ControlName == "ItemPoolBtn")
			{
				ShowPage("ItemPoolPage");
			}
			else if (args.ControlName == "StartLocationBtn")
			{
				ShowPage("StartLocationPage");
			}
			else if (args.ControlName == "RepeatBtn")
			{
				ShowPage("RepeatLimitPage");
			}
			else if (args.ControlName.StartsWith("LeftArrow"))
			{
				SwitchPage(-1);
			}
			else if (args.ControlName.StartsWith("RightArrow"))
			{
				SwitchPage(1);
			}
			if (args.ControlType == "Button")
			{
				object source = args.Source;
				NativeButton val = (NativeButton)((source is NativeButton) ? source : null);
				if (val == null)
				{
					return;
				}
				switch (args.ControlName)
				{
				case "RoomBtn":
					StartingAbilityPickerAPI.SetSceneRandomEnabled(SharedRuntimeSettings.SceneRandomEnabled = !SharedRuntimeSettings.SceneRandomEnabled);
					break;
				case "ItemBtn":
					StartingAbilityPickerAPI.SetItemRandomEnabled(SharedRuntimeSettings.ItemRandomEnabled = !SharedRuntimeSettings.ItemRandomEnabled);
					break;
				case "TrapBtn":
					StartingAbilityPickerAPI.SetTrapRandomEnabled(SharedRuntimeSettings.TrapEnabled = !SharedRuntimeSettings.TrapEnabled);
					break;
				case "EnemyBtn":
					StartingAbilityPickerAPI.SetEnemyRandomEnabled(SharedRuntimeSettings.EnemyRandomEnabled = !SharedRuntimeSettings.EnemyRandomEnabled);
					break;
				case "FullRandomBtn":
				case "RandomModeMainBtn":
					StartingAbilityPickerAPI.SetFullRandomMode(SharedRuntimeSettings.FullRandomMode = !SharedRuntimeSettings.FullRandomMode);
					UpdateFullRandomUI();
					break;
				case "TrapMovementBtn":
					SilksongItemRandomizerAPI.SetTrapMovementEnabled(SharedRuntimeSettings.TrapMovementEnabled = !SharedRuntimeSettings.TrapMovementEnabled);
					break;
				case "EnemyScaleRandomBtn":
					if (ScaleRandomEnabledProp != null)
					{
						bool flag2 = (bool)ScaleRandomEnabledProp.GetValue(null);
						ScaleRandomEnabledProp.SetValue(null, !flag2);
					}
					break;
				case "SilkRandomBtn":
					SilksongItemRandomizerAPI.SetSilkRandomEnabled(SharedRuntimeSettings.SilkRandomEnabled = !SharedRuntimeSettings.SilkRandomEnabled);
					break;
				case "UpBtn":
				{
					bool flag = (SharedRuntimeSettings.AttackUp = !SharedRuntimeSettings.AttackUp);
					(bool, bool, bool) attackPermissions = StartingAbilityPickerAPI.GetAttackPermissions();
					StartingAbilityPickerAPI.SetAttackPermissions(flag, attackPermissions.Item2, attackPermissions.Item3);
					UpdateCategoryButtonStates();
					break;
				}
				case "LeftBtn":
				{
					bool flag = (SharedRuntimeSettings.AttackLeft = !SharedRuntimeSettings.AttackLeft);
					(bool, bool, bool) attackPermissions = StartingAbilityPickerAPI.GetAttackPermissions();
					StartingAbilityPickerAPI.SetAttackPermissions(attackPermissions.Item1, flag, attackPermissions.Item3);
					UpdateCategoryButtonStates();
					break;
				}
				case "RightBtn":
				{
					bool flag = (SharedRuntimeSettings.AttackRight = !SharedRuntimeSettings.AttackRight);
					(bool, bool, bool) attackPermissions = StartingAbilityPickerAPI.GetAttackPermissions();
					StartingAbilityPickerAPI.SetAttackPermissions(attackPermissions.Item1, attackPermissions.Item2, flag);
					UpdateCategoryButtonStates();
					break;
				}
				case "ShowRoomNameBtn":
					HKSilksong_RandomizerAPI.SetShowSceneLabel(SharedRuntimeSettings.ShowSceneLabel = !SharedRuntimeSettings.ShowSceneLabel);
					break;
				case "ShowRoomSeedBtn":
					HKSilksong_RandomizerAPI.SetShowSeedOnScreen(SharedRuntimeSettings.ShowSeedLabel = !SharedRuntimeSettings.ShowSeedLabel);
					break;
				case "RoomModeBtn":
					HKSilksong_RandomizerAPI.SetMode(SharedRuntimeSettings.RoomRandomizerMode = ((SharedRuntimeSettings.RoomRandomizerMode != 1) ? 1 : 0));
					break;
				case "SilkHeartBtn":
					RoomRandomMode.Toggle();
					break;
				case "CompletionBtn":
					StartingAbilityPickerAPI.SetForceCompletionDisplay(SharedRuntimeSettings.ForceCompletionDisplay = !SharedRuntimeSettings.ForceCompletionDisplay);
					break;
				case "TrapDifficultyBtn":
					SilksongItemRandomizerAPI.SetTrapDifficulty(SharedRuntimeSettings.TrapDifficulty = (SharedRuntimeSettings.TrapDifficulty + 1) % 3);
					if (SharedRuntimeSettings.TrapEnabled)
					{
						SilksongItemRandomizerAPI.RegenerateTrapsNow();
					}
					break;
				case "CategoryBtn1":
					if (SharedRuntimeSettings.FullRandomMode)
					{
						SharedRuntimeSettings.DashRight = (SharedRuntimeSettings.DashLeft = !SharedRuntimeSettings.DashLeft);
						StartingAbilityPickerAPI.SetMovementPermissions(BuildCurrentDirectionPermissions());
					}
					break;
				case "CategoryBtn2":
					if (SharedRuntimeSettings.FullRandomMode)
					{
						SharedRuntimeSettings.HarpoonRight = (SharedRuntimeSettings.HarpoonLeft = !SharedRuntimeSettings.HarpoonLeft);
						StartingAbilityPickerAPI.SetMovementPermissions(BuildCurrentDirectionPermissions());
					}
					break;
				case "CategoryBtn3":
					if (SharedRuntimeSettings.FullRandomMode)
					{
						SharedRuntimeSettings.FloatRight = (SharedRuntimeSettings.FloatLeft = !SharedRuntimeSettings.FloatLeft);
						StartingAbilityPickerAPI.SetMovementPermissions(BuildCurrentDirectionPermissions());
					}
					break;
				case "CategoryBtn4":
					if (SharedRuntimeSettings.FullRandomMode)
					{
						SharedRuntimeSettings.WallJumpRight = (SharedRuntimeSettings.WallJumpLeft = !SharedRuntimeSettings.WallJumpLeft);
						StartingAbilityPickerAPI.SetMovementPermissions(BuildCurrentDirectionPermissions());
					}
					break;
				case "CategoryBtn5":
					if (SharedRuntimeSettings.FullRandomMode)
					{
						bool flag = !SharedRuntimeSettings.AllowHeal;
						SharedRuntimeSettings.AllowHeal = flag;
						StartingAbilityPickerAPI.SetMovementPermissions(BuildCurrentDirectionPermissions());
					}
					break;
				case "CategoryBtn6":
				{
					bool flag = (SharedRuntimeSettings.AttackRight = (SharedRuntimeSettings.AttackLeft = (SharedRuntimeSettings.AttackUp = !SharedRuntimeSettings.AttackUp || !SharedRuntimeSettings.AttackLeft || !SharedRuntimeSettings.AttackRight)));
					StartingAbilityPickerAPI.SetAttackPermissions(flag, flag, flag);
					break;
				}
				case "CrestTypeBtn":
				{
					bool flag = (SharedRuntimeSettings.CrestRandomEnabled = !SharedRuntimeSettings.CrestRandomEnabled);
					SilksongItemRandomizerAPI.SetCrestRandomEnabled(flag);
					UpdateTypeButtonColor(val, flag);
					break;
				}
				case "SkillTypeBtn":
				{
					bool flag = (SharedRuntimeSettings.SkillItemRandomEnabled = !SharedRuntimeSettings.SkillItemRandomEnabled);
					SilksongItemRandomizerAPI.SetSkillItemRandomEnabled(flag);
					UpdateTypeButtonColor(val, flag);
					break;
				}
				case "RelicTypeBtn":
				{
					bool flag = (SharedRuntimeSettings.RelicRandomEnabled = !SharedRuntimeSettings.RelicRandomEnabled);
					SilksongItemRandomizerAPI.SetRelicRandomEnabled(flag);
					UpdateTypeButtonColor(val, flag);
					break;
				}
				}
			}
			switch (args.ControlName)
			{
			case "ConfirmBtn":
				StartSeedCalc();
				break;
			case "CalcStartGameBtn":
				Confirm();
				break;
			case "ResetShopBtn":
				SilksongItemRandomizerAPI.ResetAllData();
				break;
			case "ResetPickupBtn":
				ExtraCurrencyResetAll?.Invoke(null, null);
				break;
			case "ResetFrostBlacklistBtn":
				ResetFrostBanned?.Invoke(null, null);
				break;
			}
		}

		private IEnumerator RollSeedCoroutine()
		{
			if (_seedRolling)
			{
				yield break;
			}
			_seedRolling = true;
			_seedRollCanceled = false;
			NativeLabel statusLabel = GetCachedLabel("SeedCalcStatus");
			NativeLabel resultLabel = GetCachedLabel("SeedCalcResult");
			try
			{
				SetStatus("正在准备检查点数据…");
				NativeInput seedInput = GetCachedInput("SeedInput");
				int wait;
				if (seedInput == null)
				{
					for (wait = 0; wait < 120; wait++)
					{
						if (seedInput != null)
						{
							break;
						}
						seedInput = GetCachedInput("SeedInput");
						yield return null;
					}
					if (seedInput == null)
					{
						Debug.LogWarning((object)"[MenuChanger] SeedInput 控件 2 秒内未出现,跳过随机种子");
						SetStatus("SeedInput 控件未就绪,跳过随机种子");
						yield break;
					}
				}
				long baseTicks = DateTime.UtcNow.Ticks;
				int tickCount = Environment.TickCount;
				wait = 0;
				while (!_seedRollCanceled)
				{
					SetStatus("正在用真实映射判定候选种子(第 " + (wait + 1) + "/∞ 轮)…");
					for (int i = 0; i < 20; i++)
					{
						if (_seedRollCanceled)
						{
							SetStatus("计算已取消,保留当前种子");
							yield break;
						}
						int s = GameSeedValidator.NextDynamicSeed(baseTicks, tickCount, wait * 20 + i);
						seedInput.SetTextSilent(s.ToString());
						SetResult("判定中… 候选: " + s);
						yield return null;
						try
						{
							if (HKSilksong_RandomizerAPI.IsSceneRandomEnabled())
							{
								HKSilksong_RandomizerAPI.RegenerateWithSeed(s);
							}
						}
						catch (Exception ex)
						{
							Debug.LogWarning((object)("[MenuChanger] 候选种子房间连接生成失败: " + ex.Message));
						}
						if (GameSeedValidator.IsGameLive(s))
						{
							Debug.Log((object)("[MenuChanger] 已筛选出可行随机种子: " + s));
							ApplySeed(s, seedInput);
							SetStatus("活种确认完成,可以开始游戏");
							SetResult("可行种子: " + s);
							yield break;
						}
						SetResult("候选 " + s + " 非活种,继续寻找…");
						yield return null;
					}
					wait++;
				}
				SetStatus("计算已取消,保留当前种子");
			}
			finally
			{
				_seedRolling = false;
			}
			void SetResult(string text)
			{
				if (resultLabel != null)
				{
					resultLabel.SetText(UILocale.Get(text));
				}
			}
			void SetStatus(string text)
			{
				if (statusLabel != null)
				{
					statusLabel.SetText(UILocale.Get(text));
				}
			}
		}

		private void StartSeedCalc()
		{
			if (_seedRolling)
			{
				Debug.Log((object)"[MenuChanger] 活种计算正在进行中,忽略重复点击");
				return;
			}
			UIManagerEx.ShowPage("SeedCalcPage");
			NativeLabel cachedLabel = GetCachedLabel("SeedCalcStatus");
			NativeLabel cachedLabel2 = GetCachedLabel("SeedCalcResult");
			if (_seedUserProvided)
			{
				int seed = SharedRuntimeSettings.Seed;
				Debug.Log((object)("[MenuChanger] 检测到手填种子 " + seed + ",直接采用不重新计算"));
				if (cachedLabel != null)
				{
					cachedLabel.SetText(UILocale.Get("已采用手填种子"));
				}
				if (cachedLabel2 != null)
				{
					cachedLabel2.SetText(UILocale.Get("种子: ") + seed);
				}
			}
			else
			{
				if (cachedLabel != null)
				{
					cachedLabel.SetText(UILocale.Get("正在计算可行种子,请稍候…"));
				}
				if ((Object)(object)uiManager != (Object)null)
				{
					((MonoBehaviour)uiManager).StartCoroutine(RollSeedCoroutine());
				}
			}
		}

		private void ApplySeed(int seed, NativeInput seedInput)
		{
			SharedRuntimeSettings.Seed = seed;
			StartingAbilityPickerAPI.SetSeed(seed);
			SilksongItemRandomizerAPI.SetSeed(seed);
			_seedUserProvided = false;
			seedInput.SetTextSilent(seed.ToString());
		}

		private void HandleValueChangedEvent(NativeUIEventArgs args)
		{
			if (args.ControlType == "Slider")
			{
				float num = (float)args.Value;
				string controlName = args.ControlName;
				if (controlName == null)
				{
					return;
				}
				switch (controlName.Length)
				{
				case 7:
					switch (controlName[0])
					{
					case 'V':
						if (controlName == "VSlider")
						{
							SharedRuntimeSettings.SkillVertical = (int)num;
							StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, (int)num, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
						}
						break;
					case 'H':
						if (controlName == "HSlider")
						{
							SharedRuntimeSettings.SkillHorizontal = (int)num;
							StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, (int)num, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
						}
						break;
					case 'S':
						if (controlName == "SSlider")
						{
							SharedRuntimeSettings.SkillSpecial = (int)num;
							StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, (int)num, SharedRuntimeSettings.SkillAttack);
						}
						break;
					case 'A':
						if (controlName == "ASlider")
						{
							SharedRuntimeSettings.SkillAttack = (int)num;
							StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, (int)num);
						}
						break;
					}
					break;
				case 19:
					switch (controlName[11])
					{
					case 'i':
						if (controlName == "EnemyScaleMinSlider")
						{
							ScaleMinProp?.SetValue(null, num);
						}
						break;
					case 'a':
						if (controlName == "EnemyScaleMaxSlider")
						{
							ScaleMaxProp?.SetValue(null, num);
						}
						break;
					}
					break;
				case 15:
					if (controlName == "ItemCountSlider")
					{
						SharedRuntimeSettings.ItemCount = (int)num;
						StartingAbilityPickerAPI.SetStartingItemCount((int)num);
					}
					break;
				case 16:
					if (controlName == "TotalSkillSlider")
					{
						SharedRuntimeSettings.SkillTotal = (int)num;
						StartingAbilityPickerAPI.SetSkillCounts((int)num, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
					}
					break;
				}
			}
			else
			{
				if (!(args.ControlType == "Input"))
				{
					return;
				}
				string s = (string)args.Value;
				switch (args.ControlName)
				{
				case "CurrencyFirstThresholdInput":
				{
					if (int.TryParse(s, out var result4))
					{
						SharedRuntimeSettings.CurrencyFirstThreshold = result4;
						SilksongItemRandomizerAPI.SetCurrencyThresholds(result4, SharedRuntimeSettings.CurrencySecondThreshold);
					}
					break;
				}
				case "CurrencySecondThresholdInput":
				{
					if (int.TryParse(s, out var result2))
					{
						SharedRuntimeSettings.CurrencySecondThreshold = result2;
						SilksongItemRandomizerAPI.SetCurrencyThresholds(SharedRuntimeSettings.CurrencyFirstThreshold, result2);
					}
					break;
				}
				case "SilkSpearPityInput":
				{
					if (int.TryParse(s, out var result3))
					{
						SharedRuntimeSettings.SilkSpearPityCount = result3;
						SilksongItemRandomizerAPI.SetSilkSpearPityCount(result3);
					}
					break;
				}
				case "SeedInput":
				{
					if (int.TryParse(s, out var result))
					{
						_seedRollCanceled = true;
						_seedUserProvided = true;
						SharedRuntimeSettings.Seed = result;
						StartingAbilityPickerAPI.SetSeed(result);
						SilksongItemRandomizerAPI.SetSeed(result);
					}
					break;
				}
				}
			}
		}

		private void HandleOptionChangedEvent(NativeUIEventArgs args)
		{
			if (!(args.ControlType == "Option"))
			{
				return;
			}
			int num = (int)args.Value;
			string controlName = args.ControlName;
			if (!(controlName == "SkillModeOption"))
			{
				if (controlName == "ResetOption")
				{
					SharedRuntimeSettings.ResetSeedWorld = num == 1;
					StartingAbilityPickerAPI.SetResetSeedWorld(num == 1);
				}
			}
			else
			{
				SharedRuntimeSettings.UseTypeMode = num == 1;
				StartingAbilityPickerAPI.SetSkillRandomMode(num == 1);
				UpdateSlidersVisibility();
			}
		}

		private bool IsFullRandomEnabled()
		{
			return SharedRuntimeSettings.FullRandomMode;
		}

		internal static DirectionPermissions BuildCurrentDirectionPermissions()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			return new DirectionPermissions
			{
				DashLeft = SharedRuntimeSettings.DashLeft,
				DashRight = SharedRuntimeSettings.DashRight,
				HarpoonLeft = SharedRuntimeSettings.HarpoonLeft,
				HarpoonRight = SharedRuntimeSettings.HarpoonRight,
				FloatLeft = SharedRuntimeSettings.FloatLeft,
				FloatRight = SharedRuntimeSettings.FloatRight,
				WallJumpLeft = SharedRuntimeSettings.WallJumpLeft,
				WallJumpRight = SharedRuntimeSettings.WallJumpRight,
				AllowHeal = SharedRuntimeSettings.AllowHeal
			};
		}

		private void UpdateFullRandomUI()
		{
			bool interactable = IsFullRandomEnabled();
			string[] categoryButtonNames = CategoryButtonNames;
			foreach (string name in categoryButtonNames)
			{
				NativeButton cachedButton = GetCachedButton(name);
				if (cachedButton != null && (Object)(object)cachedButton.menuButton != (Object)null)
				{
					((Selectable)cachedButton.menuButton).interactable = interactable;
				}
			}
			NativeButton cachedButton2 = GetCachedButton("UpBtn");
			NativeButton cachedButton3 = GetCachedButton("LeftBtn");
			NativeButton cachedButton4 = GetCachedButton("RightBtn");
			if (cachedButton2 != null && (Object)(object)cachedButton2.menuButton != (Object)null)
			{
				((Selectable)cachedButton2.menuButton).interactable = true;
			}
			if (cachedButton3 != null && (Object)(object)cachedButton3.menuButton != (Object)null)
			{
				((Selectable)cachedButton3.menuButton).interactable = true;
			}
			if (cachedButton4 != null && (Object)(object)cachedButton4.menuButton != (Object)null)
			{
				((Selectable)cachedButton4.menuButton).interactable = true;
			}
		}

		private void UpdateCategoryButtonStates()
		{
			if (IsFullRandomEnabled())
			{
				NativeButton cachedButton = GetCachedButton("CategoryBtn1");
				if (cachedButton != null)
				{
					cachedButton.SetToggleIndex((SharedRuntimeSettings.DashLeft && SharedRuntimeSettings.DashRight) ? 1 : 0);
				}
				NativeButton cachedButton2 = GetCachedButton("CategoryBtn2");
				if (cachedButton2 != null)
				{
					cachedButton2.SetToggleIndex((SharedRuntimeSettings.HarpoonLeft && SharedRuntimeSettings.HarpoonRight) ? 1 : 0);
				}
				NativeButton cachedButton3 = GetCachedButton("CategoryBtn3");
				if (cachedButton3 != null)
				{
					cachedButton3.SetToggleIndex((SharedRuntimeSettings.FloatLeft && SharedRuntimeSettings.FloatRight) ? 1 : 0);
				}
				NativeButton cachedButton4 = GetCachedButton("CategoryBtn4");
				if (cachedButton4 != null)
				{
					cachedButton4.SetToggleIndex((SharedRuntimeSettings.WallJumpLeft && SharedRuntimeSettings.WallJumpRight) ? 1 : 0);
				}
				NativeButton cachedButton5 = GetCachedButton("CategoryBtn5");
				if (cachedButton5 != null)
				{
					cachedButton5.SetToggleIndex(SharedRuntimeSettings.AllowHeal ? 1 : 0);
				}
				NativeButton cachedButton6 = GetCachedButton("CategoryBtn6");
				if (cachedButton6 != null)
				{
					cachedButton6.SetToggleIndex((SharedRuntimeSettings.AttackUp && SharedRuntimeSettings.AttackLeft && SharedRuntimeSettings.AttackRight) ? 1 : 0);
				}
			}
		}

		private void UpdateTypeButtonColor(NativeButton btn, bool isEnabled)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (btn != null)
			{
				Text componentInChildren = btn.gameObject.GetComponentInChildren<Text>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Graphic)componentInChildren).color = (isEnabled ? Color.white : DisabledTextColor);
					((Graphic)componentInChildren).SetVerticesDirty();
				}
			}
		}

		private void UpdateSlidersVisibility()
		{
			bool flag = !SharedRuntimeSettings.UseTypeMode;
			NativeSlider cachedSlider = GetCachedSlider("TotalSkillSlider");
			if (cachedSlider != null)
			{
				cachedSlider.gameObject.SetActive(flag);
			}
			NativeSlider cachedSlider2 = GetCachedSlider("VSlider");
			NativeSlider cachedSlider3 = GetCachedSlider("HSlider");
			NativeSlider cachedSlider4 = GetCachedSlider("SSlider");
			NativeSlider cachedSlider5 = GetCachedSlider("ASlider");
			bool active = !flag;
			if (cachedSlider2 != null)
			{
				cachedSlider2.gameObject.SetActive(active);
			}
			if (cachedSlider3 != null)
			{
				cachedSlider3.gameObject.SetActive(active);
			}
			if (cachedSlider4 != null)
			{
				cachedSlider4.gameObject.SetActive(active);
			}
			if (cachedSlider5 != null)
			{
				cachedSlider5.gameObject.SetActive(active);
			}
		}

		public void RefreshAllValues()
		{
			SyncButtonState("RoomBtn", SharedRuntimeSettings.SceneRandomEnabled);
			SyncButtonState("ItemBtn", SharedRuntimeSettings.ItemRandomEnabled);
			SyncButtonState("TrapBtn", SharedRuntimeSettings.TrapEnabled);
			SyncButtonState("FullRandomBtn", SharedRuntimeSettings.FullRandomMode);
			SyncButtonState("RandomModeMainBtn", SharedRuntimeSettings.FullRandomMode);
			SyncButtonState("TrapMovementBtn", SharedRuntimeSettings.TrapMovementEnabled);
			SyncButtonState("ShowRoomNameBtn", SharedRuntimeSettings.ShowSceneLabel);
			SyncButtonState("ShowRoomSeedBtn", SharedRuntimeSettings.ShowSeedLabel);
			NativeButton cachedButton = GetCachedButton("RoomModeBtn");
			if (cachedButton != null)
			{
				cachedButton.SetToggleIndex((SharedRuntimeSettings.RoomRandomizerMode == 1) ? 1 : 0);
			}
			NativeButton cachedButton2 = GetCachedButton("EnemyScaleRandomBtn");
			if (cachedButton2 != null && ScaleRandomEnabledProp != null)
			{
				cachedButton2.SetToggleIndex(((bool)ScaleRandomEnabledProp.GetValue(null)) ? 1 : 0);
			}
			SyncButtonState("CompletionBtn", SharedRuntimeSettings.ForceCompletionDisplay);
			SyncButtonState("CrestTypeBtn", SharedRuntimeSettings.CrestRandomEnabled);
			SyncButtonState("SkillTypeBtn", SharedRuntimeSettings.SkillItemRandomEnabled);
			SyncButtonState("RelicTypeBtn", SharedRuntimeSettings.RelicRandomEnabled);
			bool value = GlobalConfig.AttackUp.Value;
			bool value2 = GlobalConfig.AttackLeft.Value;
			bool value3 = GlobalConfig.AttackRight.Value;
			SharedRuntimeSettings.AttackUp = value;
			SharedRuntimeSettings.AttackLeft = value2;
			SharedRuntimeSettings.AttackRight = value3;
			NativeButton cachedButton3 = GetCachedButton("UpBtn");
			if (cachedButton3 != null)
			{
				cachedButton3.SetToggleIndex((!value) ? 1 : 0);
			}
			NativeButton cachedButton4 = GetCachedButton("LeftBtn");
			if (cachedButton4 != null)
			{
				cachedButton4.SetToggleIndex((!value2) ? 1 : 0);
			}
			NativeButton cachedButton5 = GetCachedButton("RightBtn");
			if (cachedButton5 != null)
			{
				cachedButton5.SetToggleIndex((!value3) ? 1 : 0);
			}
			NativeButton cachedButton6 = GetCachedButton("SilkHeartBtn");
			if (cachedButton6 != null)
			{
				cachedButton6.SetToggleIndex(RoomRandomMode.IsPending ? 1 : 0);
			}
			SetSliderValue("ItemCountSlider", SharedRuntimeSettings.ItemCount);
			SetSliderValue("TotalSkillSlider", SharedRuntimeSettings.SkillTotal);
			SetSliderValue("VSlider", SharedRuntimeSettings.SkillVertical);
			SetSliderValue("HSlider", SharedRuntimeSettings.SkillHorizontal);
			SetSliderValue("SSlider", SharedRuntimeSettings.SkillSpecial);
			SetSliderValue("ASlider", SharedRuntimeSettings.SkillAttack);
			if (ScaleMinProp != null)
			{
				SetSliderValue("EnemyScaleMinSlider", (float)ScaleMinProp.GetValue(null));
			}
			if (ScaleMaxProp != null)
			{
				SetSliderValue("EnemyScaleMaxSlider", (float)ScaleMaxProp.GetValue(null));
			}
			SetOptionValue("SkillModeOption", SharedRuntimeSettings.UseTypeMode ? 1 : 0);
			SetOptionValue("ResetOption", SharedRuntimeSettings.ResetSeedWorld ? 1 : 0);
			NativeInput cachedInput = GetCachedInput("CurrencyFirstThresholdInput");
			if (cachedInput != null)
			{
				cachedInput.SetText(SharedRuntimeSettings.CurrencyFirstThreshold.ToString());
			}
			NativeInput cachedInput2 = GetCachedInput("CurrencySecondThresholdInput");
			if (cachedInput2 != null)
			{
				cachedInput2.SetText(SharedRuntimeSettings.CurrencySecondThreshold.ToString());
			}
			NativeInput cachedInput3 = GetCachedInput("SilkSpearPityInput");
			if (cachedInput3 != null)
			{
				cachedInput3.SetText(SharedRuntimeSettings.SilkSpearPityCount.ToString());
			}
			NativeLabel cachedLabel = GetCachedLabel("CurrentSeedValue");
			if (cachedLabel != null)
			{
				cachedLabel.SetText(SharedRuntimeSettings.Seed.ToString());
			}
			NativeButton cachedButton7 = GetCachedButton("TrapDifficultyBtn");
			if (cachedButton7 != null)
			{
				int trapDifficulty = SharedRuntimeSettings.TrapDifficulty;
				if (trapDifficulty >= 0 && trapDifficulty < TrapDifficultyNames.Length)
				{
					cachedButton7.SetTitle(TrapDifficultyNames[trapDifficulty]);
				}
			}
			RefreshRepeatLimitInputs();
			UpdateFullRandomUI();
			UpdateCategoryButtonStates();
			UpdateSlidersVisibility();
		}

		private void SetSliderValue(string sliderName, float value)
		{
			NativeSlider cachedSlider = GetCachedSlider(sliderName);
			if (cachedSlider != null)
			{
				cachedSlider.SetValueWithoutNotify(value);
			}
		}

		private void SetOptionValue(string optName, int value)
		{
			NativeOption cachedOption = GetCachedOption(optName);
			if (cachedOption != null)
			{
				cachedOption.SetValueWithoutNotify(value);
			}
		}

		private void SyncButtonState(string buttonName, bool isEnabled)
		{
			NativeButton cachedButton = GetCachedButton(buttonName);
			if (cachedButton != null)
			{
				cachedButton.SetToggleIndex(isEnabled ? 1 : 0);
			}
		}

		private void Confirm()
		{
			if (_seedRolling)
			{
				Debug.LogWarning((object)"[MenuChanger] 种子尚未确定,禁止开始游戏");
				return;
			}
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.SetPendingOpeningSettings(SharedRuntimeSettings.UseTypeMode, SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack, SharedRuntimeSettings.ItemCount);
			}
			SilksongItemRandomizerAPI.ResetAllData();
			PreGeneratedMap.Reset();
			PreGeneratedMap.Initialize();
			try
			{
				if (HKSilksong_RandomizerAPI.IsSceneRandomEnabled())
				{
					int seed = SharedRuntimeSettings.Seed;
					HKSilksong_RandomizerAPI.RegenerateWithSeed(seed);
					Debug.Log((object)("[MenuChanger] 房间随机化已开启,连接已按种子 " + seed + " 生成"));
				}
				else
				{
					Debug.Log((object)"[MenuChanger] 房间随机化未开启,场景图走原生流程");
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[MenuChanger] 房间连接定档生成失败: " + ex.Message));
			}
			StartingAbilityPickerAPI.SetEnemyRandomEnabled(SharedRuntimeSettings.EnemyRandomEnabled);
			SilksongItemRandomizerAPI.PrimeAllTemplates();
			SkipToFirstAct.EnableSkip();
			StartingAbilityPickerAPI.SaveAllSettingsToConfig();
			UIManager.instance.StartNewGame(false, false);
			Hide();
			if ((Object)(object)MenuChangerMod.Instance != (Object)null)
			{
				MenuChangerMod.Instance.StartDelayedFullApply();
			}
		}

		private void ApplyVanillaSettings()
		{
			SharedRuntimeSettings.ItemRandomEnabled = false;
			SharedRuntimeSettings.CrestRandomEnabled = false;
			SharedRuntimeSettings.SkillItemRandomEnabled = false;
			SharedRuntimeSettings.RelicRandomEnabled = false;
			SharedRuntimeSettings.TrapEnabled = false;
			SharedRuntimeSettings.TrapMovementEnabled = false;
			SharedRuntimeSettings.SceneRandomEnabled = false;
			SharedRuntimeSettings.SkillTriggerEnabled = false;
			SharedRuntimeSettings.EnemyRandomEnabled = false;
			SharedRuntimeSettings.FullRandomMode = false;
			SharedRuntimeSettings.ResetSeedWorld = false;
			SilksongItemRandomizerAPI.SetEnabled(false);
			SilksongItemRandomizerAPI.SetCrestRandomEnabled(false);
			SilksongItemRandomizerAPI.SetSkillItemRandomEnabled(false);
			SilksongItemRandomizerAPI.SetRelicRandomEnabled(false);
			SilksongItemRandomizerAPI.SetTrapEnabled(false);
			SilksongItemRandomizerAPI.SetTrapMovementEnabled(false);
			HKSilksong_RandomizerAPI.SetEnabled(false);
			EnemyEnabledProp?.SetValue(null, false);
			StartingAbilityPickerAPI.SetFullRandomMode(false);
			StartingAbilityPickerAPI.SetResetSeedWorld(false);
		}

		private void StartGame(bool permaDeath)
		{
			if (_seedRolling)
			{
				Debug.LogWarning((object)"[MenuChanger] 种子尚未确定,禁止开始游戏");
				return;
			}
			ApplyVanillaSettings();
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.SetPendingOpeningSettings(SharedRuntimeSettings.UseTypeMode, SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack, SharedRuntimeSettings.ItemCount);
			}
			StartingAbilityPickerAPI.SetEnemyRandomEnabled(SharedRuntimeSettings.EnemyRandomEnabled);
			SilksongItemRandomizerAPI.PrimeAllTemplates();
			SkipToFirstAct.EnableSkip();
			StartingAbilityPickerAPI.SaveAllSettingsToConfig();
			UIManager.instance.StartNewGame(permaDeath, false);
			Hide();
			if ((Object)(object)MenuChangerMod.Instance != (Object)null)
			{
				MenuChangerMod.Instance.StartDelayedFullApply();
			}
		}

		public void RefreshPageList()
		{
			pageOrder = NativePage.AllInstances.Select((NativePage p) => ((Object)p.gameObject).name).ToList();
		}

		public void ShowPage(string pageName)
		{
			if (!string.IsNullOrEmpty(pageName))
			{
				UIManagerEx.ShowPage(pageName);
				UpdatePageIndicator();
			}
		}

		public void UpdatePageIndicator()
		{
			if (pageIndicator == null)
			{
				return;
			}
			string currentShowingPageName = GetCurrentShowingPageName();
			if (!string.IsNullOrEmpty(currentShowingPageName) && pageOrder.Count != 0)
			{
				int num = pageOrder.IndexOf(currentShowingPageName);
				if (num >= 0)
				{
					pageIndicator.SetText($"{num + 1}/{pageOrder.Count}");
					pageIndicator.gameObject.SetActive(pageOrder.Count > 1);
				}
			}
		}

		public void SwitchPage(int delta)
		{
			if (pageOrder.Count != 0)
			{
				string currentShowingPageName = GetCurrentShowingPageName();
				if (!string.IsNullOrEmpty(currentShowingPageName))
				{
					int index = (pageOrder.IndexOf(currentShowingPageName) + delta + pageOrder.Count) % pageOrder.Count;
					ShowPage(pageOrder[index]);
				}
			}
		}

		private string GetCurrentShowingPageName()
		{
			foreach (NativePage allInstance in NativePage.AllInstances)
			{
				if (allInstance != null && allInstance.isShowing)
				{
					return ((Object)allInstance.gameObject).name;
				}
			}
			return null;
		}

		public void Show(NativePage fromPage = null)
		{
			parentPage = fromPage;
			RefreshAllValues();
			root.SetActive(true);
			((MonoBehaviour)uiManager).StartCoroutine(FadeIn());
			if (pageOrder.Contains("Main"))
			{
				ShowPage("Main");
			}
			else if (pageOrder.Count > 0)
			{
				ShowPage(pageOrder[0]);
			}
		}

		public void Hide()
		{
			((MonoBehaviour)uiManager).StartCoroutine(FadeOut());
		}

		private IEnumerator FadeIn()
		{
			canvasGroup.alpha = 0f;
			canvasGroup.interactable = true;
			canvasGroup.blocksRaycasts = true;
			while (canvasGroup.alpha < 1f)
			{
				CanvasGroup obj = canvasGroup;
				obj.alpha += Time.unscaledDeltaTime * 3f;
				yield return null;
			}
			canvasGroup.alpha = 1f;
		}

		private IEnumerator FadeOut()
		{
			canvasGroup.interactable = false;
			canvasGroup.blocksRaycasts = false;
			while (canvasGroup.alpha > 0f)
			{
				CanvasGroup obj = canvasGroup;
				obj.alpha -= Time.unscaledDeltaTime * 3f;
				yield return null;
			}
			canvasGroup.alpha = 0f;
			if ((Object)(object)root != (Object)null)
			{
				root.SetActive(false);
			}
			if (parentPage != null)
			{
				parentPage.Show(true);
			}
		}
	}
	[HarmonyPatch]
	public static class SkipToFirstAct
	{
		private static bool _shouldSkip = false;

		private static bool _skipTriggered = false;

		private static bool _tutorialRestorePending = false;

		private static bool _tutorialSkipped = false;

		private static readonly WaitForSeconds SkipInterval = new WaitForSeconds(0.2f);

		private static readonly MethodInfo SendHeroInPositionMethod = typeof(HeroController).GetMethod("SendHeroInPosition", BindingFlags.Instance | BindingFlags.NonPublic);

		private static Type _csmCachedType;

		private static readonly FieldInfo[] CsmFields = new FieldInfo[5];

		private static void EnsureCsmFieldCache(Type type)
		{
			if (!(type == _csmCachedType))
			{
				BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
				CsmFields[0] = type.GetField("musicCue", bindingAttr);
				CsmFields[1] = type.GetField("musicSnapshot", bindingAttr);
				CsmFields[2] = type.GetField("musicDelayTime", bindingAttr);
				CsmFields[3] = type.GetField("musicTransitionTime", bindingAttr);
				CsmFields[4] = type.GetField("atmosCue", bindingAttr);
				_csmCachedType = type;
			}
		}

		public static void EnableSkip()
		{
			_tutorialSkipped = false;
			if (!_shouldSkip)
			{
				_shouldSkip = true;
				_skipTriggered = false;
				SceneManager.sceneLoaded += OnSceneLoaded;
				Debug.Log((object)"[SkipToFirstAct] 已启用跳过开场模式");
			}
		}

		public static void DisableSkip()
		{
			if (_shouldSkip)
			{
				_shouldSkip = false;
				SceneManager.sceneLoaded -= OnSceneLoaded;
			}
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (!_shouldSkip)
			{
				return;
			}
			if (((Scene)(ref scene)).name != "Opening_Sequence" && ((Scene)(ref scene)).name != "Main_Menu")
			{
				if (((Scene)(ref scene)).name == "Tut_01" || ((Scene)(ref scene)).name == "tut_01")
				{
					_tutorialRestorePending = true;
				}
				else
				{
					GameManager instance = GameManager.instance;
					if ((Object)(object)instance != (Object)null)
					{
						((MonoBehaviour)instance).StartCoroutine(RestoreSceneMusic());
					}
				}
			}
			if (((Scene)(ref scene)).name == "Opening_Sequence")
			{
				if (!_skipTriggered)
				{
					_skipTriggered = true;
					Debug.Log((object)"[SkipToFirstAct] 检测到开场动画,开始跳过...");
					GameManager instance2 = GameManager.instance;
					if ((Object)(object)instance2 == (Object)null)
					{
						_skipTriggered = false;
					}
					else
					{
						((MonoBehaviour)instance2).StartCoroutine(SkipCutscenes());
					}
				}
			}
			else
			{
				if ((!(((Scene)(ref scene)).name == "Tut_01") && !(((Scene)(ref scene)).name == "tut_01")) || _tutorialSkipped)
				{
					return;
				}
				GameManager instance3 = GameManager.instance;
				try
				{
					if ((Object)(object)instance3 != (Object)null && instance3.GetPlayerDataBool("bindCutscenePlayed"))
					{
						_tutorialSkipped = true;
						return;
					}
				}
				catch
				{
				}
				GameManager instance4 = GameManager.instance;
				if (!((Object)(object)instance4 == (Object)null))
				{
					_tutorialSkipped = true;
					((MonoBehaviour)instance4).StartCoroutine(SkipEntireTutorial());
				}
			}
		}

		private static IEnumerator SkipCutscenes()
		{
			yield return null;
			GameManager gm = GameManager.instance;
			if ((Object)(object)gm == (Object)null)
			{
				Debug.LogError((object)"[SkipToFirstAct] GameManager 不可用");
				yield break;
			}
			for (int i = 0; i < 5; i++)
			{
				gm.SkipCutscene();
				yield return SkipInterval;
			}
			_skipTriggered = false;
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (!_tutorialSkipped && (name == "Tut_01" || name == "tut_01"))
			{
				_tutorialRestorePending = true;
				_tutorialSkipped = true;
				((MonoBehaviour)gm).StartCoroutine(SkipEntireTutorial());
			}
		}

		private static IEnumerator RestoreSceneMusic()
		{
			GameManager gm = null;
			for (int wait = 0; wait < 600; wait++)
			{
				gm = GameManager.instance;
				if ((Object)(object)gm != (Object)null && gm.HasFinishedEnteringScene && (Object)(object)gm.AudioManager != (Object)null)
				{
					break;
				}
				yield return null;
			}
			if ((Object)(object)gm == (Object)null || (Object)(object)gm.AudioManager == (Object)null)
			{
				Debug.LogWarning((object)"[SkipToFirstAct] 场景进入未完成/音频系统不可用,整体音乐恢复中止");
				yield break;
			}
			yield return null;
			AudioManager audioManager = gm.AudioManager;
			bool flag = string.Equals(gm.GetSceneNameString(), "tut_01", StringComparison.OrdinalIgnoreCase);
			try
			{
				HeroController instance = HeroController.instance;
				if ((Object)(object)instance != (Object)null && !instance.isHeroInPosition)
				{
					bool flag2 = false;
					try
					{
						MethodInfo sendHeroInPositionMethod = SendHeroInPositionMethod;
						if (sendHeroInPositionMethod != null)
						{
							sendHeroInPositionMethod.Invoke(instance, new object[1] { true });
							flag2 = true;
						}
					}
					catch (Exception ex)
					{
						Debug.LogWarning((object)("[SkipToFirstAct] SendHeroInPosition 反射调用失败,走字段兜底: " + ex.Message));
					}
					if (!flag2)
					{
						instance.isHeroInPosition = true;
					}
					Debug.Log((object)"[SkipToFirstAct] HeroController 就位标记已置位(isHeroInPosition=true),解锁音频/相机全链");
				}
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] HeroController 就位恢复异常: " + ex2.Message));
			}
			try
			{
				CameraController cameraCtrl = gm.cameraCtrl;
				if ((Object)(object)cameraCtrl != (Object)null && !cameraCtrl.HasBeenPositionedAtHero && !CameraController.IsPositioningCamera)
				{
					cameraCtrl.PositionToHero(true);
					Debug.Log((object)"[SkipToFirstAct] 相机未定位,主动触发 PositionToHero 解锁音频/相机链");
				}
			}
			catch (Exception ex3)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] 相机定位恢复异常: " + ex3.Message));
			}
			try
			{
				if (AudioListener.pause)
				{
					AudioListener.pause = false;
					Debug.Log((object)"[SkipToFirstAct] AudioListener.pause 已复位为 false(Control FSM 静音演出残留)");
				}
			}
			catch (Exception ex4)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] AudioListener.pause 复位异常: " + ex4.Message));
			}
			try
			{
				GameCameras instance2 = GameCameras.instance;
				if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.forceCameraAspect != (Object)null)
				{
					instance2.forceCameraAspect.SetFovOffset(0f, 0f, (AnimationCurve)null);
					Debug.Log((object)"[SkipToFirstAct] 相机 FOV offset 已复位为 0");
				}
			}
			catch (Exception ex5)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] 相机 FOV 复位异常: " + ex5.Message));
			}
			Plugin.BlackoutHide();
			if (flag)
			{
				try
				{
					PlayMakerFSM[] array = Object.FindObjectsByType<PlayMakerFSM>((FindObjectsInactive)1, (FindObjectsSortMode)0);
					foreach (PlayMakerFSM val in array)
					{
						if ((Object)(object)val == (Object)null || val.FsmStates == null || !HasFsmState(val, "Moss Music Up"))
						{
							continue;
						}
						FsmState state = val.Fsm.GetState("Moss Music Up");
						if (state == null || state.Actions == null)
						{
							continue;
						}
						for (int j = 0; j < state.Actions.Length; j++)
						{
							FsmStateAction obj = state.Actions[j];
							ApplyMusicCue val2 = (ApplyMusicCue)(object)((obj is ApplyMusicCue) ? obj : null);
							if (val2 != null)
							{
								Object value = val2.musicCue.Value;
								MusicCue val3 = (MusicCue)(object)((value is MusicCue) ? value : null);
								if ((Object)(object)val3 != (Object)null)
								{
									val3.Preload(((Component)val).gameObject);
									audioManager.ApplyMusicCue(val3, 0f, 0f, false);
									Debug.Log((object)("[SkipToFirstAct] tut_01 教程 BGM 重放: " + ((Object)val3).name));
								}
								continue;
							}
							FsmStateAction obj2 = state.Actions[j];
							TransitionToAudioSnapshot val4 = (TransitionToAudioSnapshot)(object)((obj2 is TransitionToAudioSnapshot) ? obj2 : null);
							if (val4 != null)
							{
								Object value2 = val4.snapshot.Value;
								AudioMixerSnapshot val5 = (AudioMixerSnapshot)(object)((value2 is AudioMixerSnapshot) ? value2 : null);
								if (val5 != null)
								{
									audioManager.ApplyMusicSnapshot(val5, 0f, val4.transitionTime.Value);
									Debug.Log((object)("[SkipToFirstAct] tut_01 音乐快照恢复: " + ((Object)val5).name));
								}
							}
						}
						break;
					}
				}
				catch (Exception ex6)
				{
					Debug.LogWarning((object)("[SkipToFirstAct] tut_01 教程 BGM 重放异常: " + ex6.Message));
				}
			}
			try
			{
				CustomSceneManager[] array2 = Object.FindObjectsByType<CustomSceneManager>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				if (array2 != null && array2.Length != 0)
				{
					CustomSceneManager val6 = array2[0];
					EnsureCsmFieldCache(((object)val6).GetType());
					object? obj3 = CsmFields[0]?.GetValue(val6);
					MusicCue val7 = (MusicCue)((obj3 is MusicCue) ? obj3 : null);
					object? obj4 = CsmFields[1]?.GetValue(val6);
					AudioMixerSnapshot val8 = (AudioMixerSnapshot)((obj4 is AudioMixerSnapshot) ? obj4 : null);
					float num = ((CsmFields[2]?.GetValue(val6) is float num2) ? num2 : 0f);
					float num3 = ((CsmFields[3]?.GetValue(val6) is float num4) ? num4 : 0f);
					if ((Object)(object)val7 != (Object)null && (Object)(object)audioManager.CurrentMusicCue == (Object)null)
					{
						val7.Preload(((Component)val6).gameObject);
						audioManager.ApplyMusicCue(val7, num, num3, false);
						Debug.Log((object)("[SkipToFirstAct] 场景音乐配置恢复: cue=" + ((Object)val7).name));
					}
					if ((Object)(object)val8 != (Object)null)
					{
						audioManager.ApplyMusicSnapshot(val8, num, num3);
					}
					object? obj5 = CsmFields[4]?.GetValue(val6);
					AtmosCue val9 = (AtmosCue)((obj5 is AtmosCue) ? obj5 : null);
					if ((Object)(object)val9 != (Object)null)
					{
						audioManager.ClearAtmosOverrides();
						audioManager.ApplyAtmosCue(val9, val6.transitionTime, true);
					}
					if ((Object)(object)val6.atmosSnapshot != (Object)null)
					{
						AudioManager.TransitionToAtmosOverride(val6.atmosSnapshot, val6.transitionTime);
					}
				}
			}
			catch (Exception ex7)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] 场景音乐配置恢复异常: " + ex7.Message));
			}
			try
			{
				MusicRegion[] array3 = Object.FindObjectsByType<MusicRegion>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				foreach (MusicRegion val10 in array3)
				{
					if (!((Object)(object)val10 == (Object)null))
					{
						if ((Object)(object)val10.enterMusicSnapshot != (Object)null)
						{
							audioManager.ApplyMusicSnapshot(val10.enterMusicSnapshot, 0f, val10.enterTransitionTime);
						}
						if ((Object)(object)val10.enterMusicCue != (Object)null && (Object)(object)audioManager.CurrentMusicCue == (Object)null)
						{
							val10.enterMusicCue.Preload(((Component)val10).gameObject);
							audioManager.ApplyMusicCue(val10.enterMusicCue, 0f, 0f, false);
							Debug.Log((object)("[SkipToFirstAct] 音乐区域恢复: " + ((Object)val10).name));
						}
					}
				}
			}
			catch (Exception ex8)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] 音乐区域恢复异常: " + ex8.Message));
			}
			Debug.Log((object)"[SkipToFirstAct] 整体音乐恢复完成");
		}

		private static IEnumerator SkipEntireTutorial()
		{
			yield return null;
			GameManager instance = GameManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Debug.LogError((object)"[SkipToFirstAct] GameManager 不可用,教程跳过中止");
				yield break;
			}
			try
			{
				instance.SetPlayerDataBool("bindCutscenePlayed", true);
				instance.SetPlayerDataBool("completedTutorial", true);
				instance.SetPlayerDataBool("enteredTutorialFirstTime", true);
				instance.SetPlayerDataBool("entered_Tut01b", true);
			}
			catch (Exception arg)
			{
				Debug.LogError((object)$"[SkipToFirstAct] 写入教程标志失败: {arg}");
			}
			PlayMakerFSM val = null;
			PlayMakerFSM val2 = null;
			try
			{
				PlayMakerFSM[] array = Object.FindObjectsByType<PlayMakerFSM>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				for (int i = 0; i < array.Length; i++)
				{
					if (!((Object)(object)array[i] == (Object)null) && !(array[i].FsmName != "Control"))
					{
						if ((Object)(object)val == (Object)null && HasFsmState(array[i], "Hornet Down"))
						{
							val = array[i];
						}
						else if ((Object)(object)val2 == (Object)null && HasFsmState(array[i], "Weak Start"))
						{
							val2 = array[i];
						}
					}
				}
				if ((Object)(object)val != (Object)null && HasFsmState(val, "End"))
				{
					val.SetState("End");
				}
				if ((Object)(object)val2 != (Object)null && HasFsmState(val2, "Resume"))
				{
					val2.SetState("Resume");
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] FSM 瞬跳异常: " + ex.Message));
			}
			try
			{
				Color colour = ScreenFaderUtils.GetColour();
				Color val3 = default(Color);
				((Color)(ref val3))..ctor(0f, 0f, 0f, 0f);
				ScreenFaderUtils.Fade(colour, val3, 0.5f);
				Plugin.BlackoutHide();
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] 清除黑幕异常: " + ex2.Message));
			}
			try
			{
				if ((Object)(object)HeroController.instance != (Object)null)
				{
					HeroController.instance.RegainControl();
				}
			}
			catch (Exception ex3)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] RegainControl 异常: " + ex3.Message));
			}
			try
			{
				if ((Object)(object)HeroController.instance != (Object)null)
				{
					HeroController.instance.RefillHealthToMax();
				}
			}
			catch (Exception ex4)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] 回满血异常: " + ex4.Message));
			}
			try
			{
				GameCameras instance2 = GameCameras.instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					EventRegister.SendEvent("SHOW HP", (GameObject)null);
					EventRegister.SendEvent("SPOOL APPEAR", (GameObject)null);
					try
					{
						SilkSpool silkSpool = instance2.silkSpool;
						if ((Object)(object)silkSpool != (Object)null)
						{
							silkSpool.DrawSpool();
							silkSpool.RefreshSilk();
						}
					}
					catch (Exception ex5)
					{
						Debug.LogWarning((object)("[SkipToFirstAct] 丝卷初始化异常: " + ex5.Message));
					}
					try
					{
						BindOrbHudFrame[] array2 = Object.FindObjectsByType<BindOrbHudFrame>((FindObjectsInactive)1, (FindObjectsSortMode)0);
						for (int j = 0; j < array2.Length; j++)
						{
							array2[j].AlreadyAppeared();
						}
					}
					catch (Exception ex6)
					{
						Debug.LogWarning((object)("[SkipToFirstAct] 纹章框初始化异常: " + ex6.Message));
					}
					EventRegister.SendEvent("HEALTH UPDATE", (GameObject)null);
					EventRegister.SendEvent("HERO HEALED TO MAX", (GameObject)null);
					EventRegister.SendEvent("TOOL EQUIPS CHANGED", (GameObject)null);
					EventRegister.SendEvent("POST TOOL EQUIPS CHANGED", (GameObject)null);
					instance2.HUDIn();
					HudGlobalHide.IsHidden = false;
					HudScalePositioner.IsReduced = false;
					if (!instance2.IsHudVisible)
					{
						Debug.LogWarning((object)"[SkipToFirstAct] HUD 初始化完成但 IsHudVisible 仍为 false");
					}
				}
			}
			catch (Exception ex7)
			{
				Debug.LogWarning((object)("[SkipToFirstAct] HUD 初始化异常: " + ex7.Message));
			}
			if (_tutorialRestorePending)
			{
				_tutorialRestorePending = false;
				((MonoBehaviour)instance).StartCoroutine(RestoreSceneMusic());
			}
			Debug.Log((object)"[SkipToFirstAct] 教程跳过完成,玩家原地留在 tut_01");
		}

		private static bool HasFsmState(PlayMakerFSM fsm, string stateName)
		{
			if ((Object)(object)fsm == (Object)null || fsm.FsmStates == null)
			{
				return false;
			}
			for (int i = 0; i < fsm.FsmStates.Length; i++)
			{
				if (fsm.FsmStates[i] != null && fsm.FsmStates[i].Name == stateName)
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class GameSeedValidator
	{
		private static PharloomCore _core;

		private static bool _initialized;

		private static string _lastError;

		private const string ConnectionsFileName = "roomrando_connections.txt";

		private static bool _connEnabled;

		private static string _connSig;

		private static bool _connSynced;

		public static string LastError => _lastError;

		public static bool IsReady
		{
			get
			{
				EnsureInit();
				return _core != null;
			}
		}

		private static void EnsureInit()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			try
			{
				_core = new PharloomCore(true);
				Debug.Log((object)("[MenuChanger] GameSeedValidator 初始化成功: " + _core.Regions.Length + " 区域"));
			}
			catch (Exception ex)
			{
				_lastError = ex.Message;
				Debug.LogWarning((object)("[MenuChanger] GameSeedValidator 初始化失败: " + ex));
			}
		}

		public static bool IsSimulatedLive(int seed)
		{
			EnsureInit();
			if (_core == null)
			{
				return false;
			}
			try
			{
				SyncSceneConnections();
				return _core.IsSeedLive(seed, IsFullRandomEnabled());
			}
			catch (Exception ex)
			{
				_lastError = ex.Message;
				return false;
			}
		}

		public static int ScoreSeed(int seed)
		{
			EnsureInit();
			if (_core == null)
			{
				Debug.LogWarning((object)("[MenuChanger] ScoreSeed: PharloomCore 初始化失败: " + _lastError));
				return int.MaxValue;
			}
			try
			{
				SyncSceneConnections();
				return _core.ScoreSeed(seed, IsFullRandomEnabled());
			}
			catch (Exception ex)
			{
				_lastError = ex.Message;
				Debug.LogWarning((object)("[MenuChanger] ScoreSeed(" + seed + ") 评分异常: " + ex));
				return int.MaxValue;
			}
		}

		private static bool IsFullRandomEnabled()
		{
			try
			{
				return SharedRuntimeSettings.FullRandomMode;
			}
			catch
			{
				return false;
			}
		}

		public static bool IsGameLive(int seed)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Invalid comparison between Unknown and I4
			EnsureInit();
			if (_core == null)
			{
				return false;
			}
			try
			{
				SilksongItemRandomizerAPI.SetSeed(seed);
				PreGeneratedMap.Reset();
				PreGeneratedMap.Initialize();
				Dictionary<string, string> preGeneratedMappings = Plugin.SaveData.PreGeneratedMappings;
				if (preGeneratedMappings == null || preGeneratedMappings.Count == 0)
				{
					return false;
				}
				SyncSceneConnections();
				Dictionary<ItemSlot, Item> dictionary = new Dictionary<ItemSlot, Item>();
				int num = 0;
				int num2 = 0;
				foreach (KeyValuePair<string, string> item in preGeneratedMappings)
				{
					Region val = ResolveRegion(item.Key);
					if (val == null)
					{
						num++;
						continue;
					}
					Item val2 = ParseGameItem(item.Value);
					if (val2 == null)
					{
						num2++;
						continue;
					}
					dictionary[new ItemSlot
					{
						Id = item.Key,
						Region = val,
						AccessGate = _core.FindPointGate(item.Key)
					}] = val2;
				}
				SeedVerdict val3 = _core.Detector.Evaluate((IReadOnlyDictionary<ItemSlot, Item>)dictionary, IsFullRandomEnabled());
				if (val3.IsDead)
				{
					int count = preGeneratedMappings.Count;
					StringBuilder stringBuilder = new StringBuilder();
					stringBuilder.Append("[GameSeedValidator] 种子 ").Append(seed).Append(" 真实映射判定为死种。总键=")
						.Append(count)
						.Append(", 区域解析忽略=")
						.Append(num)
						.Append(", 奖励解析失败=")
						.Append(num2)
						.Append(", 入assignment=")
						.Append(dictionary.Count)
						.Append(", 死因=")
						.Append(val3.Reason ?? "(无)")
						.Append(", 未达区域=")
						.Append(val3.UnreachedRegions.Count)
						.Append(" -> ")
						.Append(string.Join(",", val3.UnreachedRegions))
						.Append(", 阻塞点位=")
						.Append(val3.BlockedSlotIds.Count);
					List<string> list = new List<string>();
					foreach (KeyValuePair<string, string> item2 in preGeneratedMappings)
					{
						if (ResolveRegion(item2.Key) != null)
						{
							continue;
						}
						Item val4 = ParseGameItem(item2.Value);
						if (val4 != null)
						{
							if ((int)val4.Kind == 0 || (int)val4.Kind == 1)
							{
								list.Add(item2.Key + "=" + item2.Value);
							}
							if (list.Count >= 8)
							{
								break;
							}
						}
					}
					if (list.Count > 0)
					{
						stringBuilder.Append("  [忽略键含能力/权限]: ").Append(string.Join(",", list));
					}
					if (num > 0 || num2 > 0)
					{
						List<string> list2 = new List<string>();
						List<string> list3 = new List<string>();
						foreach (KeyValuePair<string, string> item3 in preGeneratedMappings)
						{
							if (list2.Count < 8 && ResolveRegion(item3.Key) == null)
							{
								list2.Add(item3.Key);
							}
							else if (list3.Count < 8 && ResolveRegion(item3.Key) != null && ParseGameItem(item3.Value) == null)
							{
								list3.Add(item3.Key + "=" + item3.Value);
							}
							if (list2.Count >= 8 && list3.Count >= 8)
							{
								break;
							}
						}
						if (list2.Count > 0)
						{
							stringBuilder.Append("  [区域解析忽略示例]: ").Append(string.Join(",", list2));
						}
						if (list3.Count > 0)
						{
							stringBuilder.Append("  [奖励解析失败示例]: ").Append(string.Join(",", list3));
						}
					}
					Debug.LogWarning((object)stringBuilder.ToString());
				}
				return !val3.IsDead;
			}
			catch (Exception ex)
			{
				_lastError = ex.Message;
				Debug.LogWarning((object)("[MenuChanger] 验证种子 " + seed + " 失败: " + ex));
				return false;
			}
		}

		public static int NextDynamicSeed(long baseTicks, int tickCount, int index)
		{
			int num = ((int)(baseTicks + index) ^ tickCount) & 0x7FFFFFFF;
			if (num > 0)
			{
				return num;
			}
			return 1;
		}

		public static int FindLiveSeed()
		{
			EnsureInit();
			if (_core == null)
			{
				return -1;
			}
			long ticks = DateTime.UtcNow.Ticks;
			int tickCount = Environment.TickCount;
			for (int i = 0; i < 2000; i++)
			{
				int num = NextDynamicSeed(ticks, tickCount, i);
				if (IsSimulatedLive(num) && IsGameLive(num))
				{
					return num;
				}
			}
			return -1;
		}

		private static void SyncSceneConnections()
		{
			if (_core == null)
			{
				return;
			}
			bool flag = false;
			try
			{
				flag = HKSilksong_RandomizerAPI.IsSceneRandomEnabled();
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[MenuChanger] 读取房间随机化开关失败: " + ex.Message));
			}
			string text = Path.Combine(Paths.PluginPath, "roomrando_connections.txt");
			bool flag2 = flag && File.Exists(text);
			string text2 = null;
			if (flag2)
			{
				FileInfo fileInfo = new FileInfo(text);
				text2 = fileInfo.LastWriteTimeUtc.Ticks + ":" + fileInfo.Length;
			}
			if (_connSynced && flag == _connEnabled && text2 == _connSig)
			{
				return;
			}
			_connSynced = true;
			_connEnabled = flag;
			_connSig = text2;
			try
			{
				if (!flag2)
				{
					_core.RestoreNativeSceneConnections();
					Debug.Log((object)"[MenuChanger] 场景图: 原生连接(房间随机化未启用或连接文件缺失)");
				}
				else
				{
					_core.MergeSceneConnections((IEnumerable<string>)File.ReadAllLines(text));
					Debug.Log((object)"[MenuChanger] 场景图: 随机连接已合并(txt 覆盖的出口用随机目标,其余走原生)");
				}
			}
			catch (Exception ex2)
			{
				_lastError = ex2.Message;
				_connSynced = false;
				Debug.LogWarning((object)("[MenuChanger] 场景连接切换失败,回退原生连接: " + ex2.Message));
				try
				{
					_core.RestoreNativeSceneConnections();
				}
				catch
				{
				}
			}
		}

		private static Region ResolveRegion(string key)
		{
			string value = null;
			if (key.StartsWith("lore:") || key.StartsWith("event:"))
			{
				string[] array = key.Split(new char[1] { ':' });
				if (array.Length >= 2)
				{
					value = array[1];
				}
			}
			else if (key.StartsWith("shop:"))
			{
				value = key.Substring("shop:".Length).Split(new char[1] { '_' })[0];
			}
			else if (key.StartsWith("check:"))
			{
				PreGeneratedMap.CheckSceneMap.TryGetValue(key, out value);
			}
			else if (key.StartsWith("heart:") || key.StartsWith("spool:") || key.StartsWith("moss:") || key.StartsWith("flower:"))
			{
				value = key.Substring(key.IndexOf(':') + 1);
			}
			else if (key.StartsWith("flea:"))
			{
				string text = key.Substring("flea:".Length);
				value = ((!int.TryParse(text, out var result)) ? text : FleaSceneMap.IndexToScene(result));
			}
			else
			{
				string[] array2 = key.Split(new char[1] { '_' });
				if (array2.Length < 4)
				{
					return null;
				}
				if (!float.TryParse(array2[^1], out var result2))
				{
					return null;
				}
				if (!float.TryParse(array2[^2], out result2))
				{
					return null;
				}
				if (!float.TryParse(array2[^3], out result2))
				{
					return null;
				}
				value = string.Join("_", array2, 0, array2.Length - 3);
			}
			if (string.IsNullOrEmpty(value))
			{
				return null;
			}
			return _core.Resolver.Resolve(value);
		}

		private static Item ParseGameItem(string reward)
		{
			//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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			if (string.IsNullOrEmpty(reward) || !reward.StartsWith("reward:"))
			{
				return null;
			}
			string text = reward.Substring("reward:".Length);
			if (text.StartsWith("perm:"))
			{
				string text2 = text.Substring("perm:".Length);
				if (text2.EndsWith("_R"))
				{
					return BuildPermission(text2.Substring(0, text2.Length - 2), (PermissionSide)1);
				}
				if (text2.EndsWith("_L"))
				{
					return BuildPermission(text2.Substring(0, text2.Length - 2), (PermissionSide)0);
				}
				return BuildAttackAbility(text);
			}
			if (!text.StartsWith("virt:"))
			{
				foreach (Ability value in AbilitiesData.All.Values)
				{
					if (value.Key == text)
					{
						return new Item
						{
							Kind = (ItemKind)0,
							AbilityId = value.Id
						};
					}
				}
				return new Item
				{
					Kind = (ItemKind)2,
					ItemName = text
				};
			}
			return new Item
			{
				Kind = (ItemKind)4,
				ItemName = text.Substring("virt:".Length)
			};
		}

		private static Item BuildAttackAbility(string id)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			foreach (Ability value in AbilitiesData.All.Values)
			{
				if (value.Key == id)
				{
					return new Item
					{
						Kind = (ItemKind)0,
						AbilityId = value.Id
					};
				}
			}
			return null;
		}

		private static Item BuildPermission(string skillField, PermissionSide side)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Invalid comparison between Unknown and I4
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			switch (skillField)
			{
			case "upward":
				return new Item
				{
					Kind = (ItemKind)0,
					AbilityId = (AbilityId)18
				};
			case "left":
				return new Item
				{
					Kind = (ItemKind)0,
					AbilityId = (AbilityId)19
				};
			case "right":
				return new Item
				{
					Kind = (ItemKind)0,
					AbilityId = (AbilityId)20
				};
			case "heal":
				return new Item
				{
					Kind = (ItemKind)0,
					AbilityId = (AbilityId)21
				};
			default:
			{
				string text = (skillField.StartsWith("has") ? skillField.Substring(3) : skillField);
				string permissionId = text + "_" + (((int)side == 1) ? "R" : "L");
				AbilityId abilityId;
				switch (text)
				{
				case "Dash":
					abilityId = (AbilityId)1;
					break;
				case "HarpoonDash":
					abilityId = (AbilityId)6;
					break;
				case "Brolly":
					abilityId = (AbilityId)3;
					break;
				case "Walljump":
					abilityId = (AbilityId)5;
					break;
				case "SuperJump":
					abilityId = (AbilityId)4;
					break;
				default:
					return null;
				}
				return new Item
				{
					Kind = (ItemKind)1,
					PermissionId = permissionId,
					AbilityId = abilityId
				};
			}
			}
		}
	}
}

BepInEx/plugins/NativeUIMaker.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using GlobalEnums;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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;
		}
	}
}
namespace NativeUIMaker
{
	[Serializable]
	public class UIControlConfig
	{
		public string name;

		public string type;

		public string page;

		public Vector2 position;

		public Vector2 size;

		public string title;

		public string description;

		public string[] toggleTexts;

		public int toggleIndex;

		public string labelText;

		public int fontSize;

		public Color color;

		public float minValue;

		public float maxValue;

		public float value;

		public bool wholeNumbers;

		public int optionIndex;

		public string[] options;

		public int direction;

		public bool playAnim;

		public bool clickable;

		public bool draggable;

		public string inputText;

		public string placeholderText;

		public int style;

		public Vector2 iconOffset;

		public Vector2 titleOffset;

		public Vector2 descOffset;

		public float sliderXOffset;

		public float sliderWidth;

		public float labelXOffset;

		public float valueXOffset;
	}
	[Serializable]
	public class ConfigData
	{
		public List<UIControlConfig> controls = new List<UIControlConfig>();
	}
	internal static class SlimJson
	{
		internal static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
		{
			Formatting = (Formatting)1,
			NullValueHandling = (NullValueHandling)1,
			DefaultValueHandling = (DefaultValueHandling)1
		};
	}
	public class DebugWindow : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Predicate<NativeButton> <>9__189_0;

			public static Predicate<NativeLabel> <>9__189_1;

			public static Predicate<NativeSlider> <>9__189_2;

			public static Predicate<NativeOption> <>9__189_3;

			public static Predicate<NativeArrow> <>9__189_4;

			public static Predicate<NativeInput> <>9__189_5;

			public static Func<NativePage, bool> <>9__208_0;

			public static Func<string, string> <>9__211_0;

			public static UnityAction <>9__211_1;

			public static UnityAction <>9__216_0;

			public static Func<string, string> <>9__234_0;

			public static Func<string, string> <>9__237_0;

			public static UnityAction <>9__248_0;

			public static Predicate<NativeButton> <>9__250_0;

			public static Predicate<NativeLabel> <>9__250_1;

			public static Predicate<NativeSlider> <>9__250_2;

			public static Predicate<NativeOption> <>9__250_3;

			public static Predicate<NativeArrow> <>9__250_4;

			public static Predicate<NativeInput> <>9__250_5;

			public static Predicate<NativeButton> <>9__253_0;

			public static UnityAction <>9__256_7;

			internal bool <CleanAllExternalLists>b__189_0(NativeButton b)
			{
				if (b != null)
				{
					return (Object)(object)b.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanAllExternalLists>b__189_1(NativeLabel l)
			{
				if (l != null)
				{
					return (Object)(object)l.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanAllExternalLists>b__189_2(NativeSlider s)
			{
				if (s != null)
				{
					return (Object)(object)s.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanAllExternalLists>b__189_3(NativeOption o)
			{
				if (o != null)
				{
					return (Object)(object)o.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanAllExternalLists>b__189_4(NativeArrow a)
			{
				if (a != null)
				{
					return (Object)(object)a.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanAllExternalLists>b__189_5(NativeInput i)
			{
				if (i != null)
				{
					return (Object)(object)i.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <RefreshPageDropdownList>b__208_0(NativePage p)
			{
				return p != null;
			}

			internal string <DrawCreateButtonSection>b__211_0(string s)
			{
				return s.Trim();
			}

			internal void <DrawCreateButtonSection>b__211_1()
			{
				Debug.Log((object)UILocale.Get("按钮被点击"));
			}

			internal void <CreateArrow>b__216_0()
			{
				Debug.Log((object)UILocale.Get("箭头被点击"));
			}

			internal string <DrawButtonEditor>b__234_0(string s)
			{
				return s.Trim();
			}

			internal string <DrawOptionEditor>b__237_0(string s)
			{
				return s.Trim();
			}

			internal void <ApplyConfigToControlInPage>b__248_0()
			{
				Debug.Log((object)UILocale.Get("箭头被点击"));
			}

			internal bool <CleanInvalidControls>b__250_0(NativeButton b)
			{
				if (b != null)
				{
					return (Object)(object)b.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanInvalidControls>b__250_1(NativeLabel l)
			{
				if (l != null)
				{
					return (Object)(object)l.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanInvalidControls>b__250_2(NativeSlider s)
			{
				if (s != null)
				{
					return (Object)(object)s.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanInvalidControls>b__250_3(NativeOption o)
			{
				if (o != null)
				{
					return (Object)(object)o.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanInvalidControls>b__250_4(NativeArrow a)
			{
				if (a != null)
				{
					return (Object)(object)a.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <CleanInvalidControls>b__250_5(NativeInput i)
			{
				if (i != null)
				{
					return (Object)(object)i.gameObject == (Object)null;
				}
				return true;
			}

			internal bool <SaveConfigToFile>b__253_0(NativeButton btn)
			{
				<>c__DisplayClass253_0 CS$<>8__locals1 = new <>c__DisplayClass253_0
				{
					btn = btn
				};
				return NativeArrow.AllInstances.Any((NativeArrow arr) => arr != null && (Object)(object)arr.gameObject == (Object)(object)CS$<>8__locals1.btn.gameObject);
			}

			internal void <LoadConfigFromFile>b__256_7()
			{
				Debug.Log((object)UILocale.Get("箭头被点击"));
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass253_0
		{
			public NativeButton btn;

			internal bool <SaveConfigToFile>b__1(NativeArrow arr)
			{
				if (arr != null)
				{
					return (Object)(object)arr.gameObject == (Object)(object)btn.gameObject;
				}
				return false;
			}
		}

		private static DebugWindow _instance;

		private Rect _windowRect = new Rect(50f, 50f, 800f, 1500f);

		private Vector2 _scrollPos;

		private bool _showWindow = true;

		private int _selectedTab;

		private HashSet<GameObject> _arrowGameObjectSet = new HashSet<GameObject>();

		private HashSet<NativeButton> _localButtonSet = new HashSet<NativeButton>();

		private HashSet<NativeLabel> _localLabelSet = new HashSet<NativeLabel>();

		private HashSet<NativeSlider> _localSliderSet = new HashSet<NativeSlider>();

		private HashSet<NativeOption> _localOptionSet = new HashSet<NativeOption>();

		private HashSet<NativeArrow> _localArrowSet = new HashSet<NativeArrow>();

		private HashSet<NativeInput> _localInputSet = new HashSet<NativeInput>();

		private object _selectedControl;

		private string _editTitle = "";

		private string _editDesc = "";

		private Vector2 _editPos = Vector2.zero;

		private Vector2 _editSize = Vector2.zero;

		private string _editLabelText = "";

		private int _editFontSize = 30;

		private Color _editColor = Color.white;

		private float _editSliderMin;

		private float _editSliderMax;

		private float _editSliderValue;

		private bool _editSliderWhole;

		private string _editSliderLabel = "";

		private float _editSliderXOffset;

		private float _editSliderWidth;

		private float _editLabelXOffset;

		private float _editValueXOffset;

		private string _editOptionLabel = "";

		private string _editOptionDesc = "";

		private string[] _editOptionOptions;

		private int _editOptionIndex;

		private int _editArrowDirection;

		private bool _editArrowPlayAnim;

		private bool _editArrowClickable;

		private bool _editArrowDraggable;

		private string _editInputText = "";

		private string _editInputPlaceholder = "";

		private string _editToggleTextsInput = "";

		private Vector2 _editIconOffset = Vector2.zero;

		private Vector2 _editTitleOffset = Vector2.zero;

		private Vector2 _editDescOffset = Vector2.zero;

		private string _strPosX = "0";

		private string _strPosY = "0";

		private string _strSizeW = "0";

		private string _strSizeH = "0";

		private string _strIconOffX = "0";

		private string _strIconOffY = "0";

		private string _strTitleOffX = "0";

		private string _strTitleOffY = "0";

		private string _strDescOffX = "0";

		private string _strDescOffY = "0";

		private string _strFontSize = "30";

		private string _strColor = "1.00,1.00,1.00";

		private string _lastParsedColor = "";

		private string _strSliderMin = "0";

		private string _strSliderMax = "100";

		private string _strSliderValue = "0";

		private string _strSliderXOff = "0";

		private string _strSliderWidth = "0";

		private string _strLabelXOff = "0";

		private string _strValueXOff = "0";

		private List<NativeButton> _allButtons = new List<NativeButton>();

		private List<NativeLabel> _allLabels = new List<NativeLabel>();

		private List<NativeSlider> _allSliders = new List<NativeSlider>();

		private List<NativeOption> _allOptions = new List<NativeOption>();

		private List<NativeArrow> _allArrows = new List<NativeArrow>();

		private List<NativeInput> _allInputs = new List<NativeInput>();

		private ButtonStyle _selectedCreateStyle;

		private string[] _styleNames = new string[3] { "图标按钮", "纯文字按钮", "小型按钮" };

		private string _toggleTextsInput = "选项1,选项2,选项3";

		private string _iconPathInput = "";

		private NativePage _selectedCreateTargetPage;

		private string[] _pageNamesForDropdown = new string[0];

		private int _selectedPageDropdownIndex;

		private int _pageDropdownVersion = -1;

		private List<NativeButton> _externalButtons = new List<NativeButton>();

		private List<NativeLabel> _externalLabels = new List<NativeLabel>();

		private List<NativeSlider> _externalSliders = new List<NativeSlider>();

		private List<NativeOption> _externalOptions = new List<NativeOption>();

		private List<NativeArrow> _externalArrows = new List<NativeArrow>();

		private List<NativeInput> _externalInputs = new List<NativeInput>();

		private bool _externalScanned;

		private NativePage _selectedPage;

		private List<UIControlConfig> _pageControlsCache = new List<UIControlConfig>();

		private bool _cachedIsChinese;

		private bool _localeCacheValid;

		private string _locApplyChanges;

		private string _locDeleteControl;

		private string _locDestroyed;

		private string _locNoSelection;

		private string _locDraggable;

		private string _locHideWindow;

		private string _locLocal;

		private string _locExternal;

		private string _locPageMgmt;

		private string _locTitle;

		private string _locDesc;

		private string _locPosXY;

		private string _locSizeWH;

		private string _locApplyIcon;

		private string _locApplyTitle;

		private string _locApplyDesc;

		private string _locText;

		private string _locFontSize;

		private string _locColorRGB;

		private string _locLabel;

		private string _locSliderXOff;

		private string _locSliderWidth;

		private string _locLabelXOff;

		private string _locValueXOff;

		private string _locMin;

		private string _locMax;

		private string _locIntStep;

		private string _locOptions;

		private string _locSelected;

		private string _locPrev;

		private string _locNext;

		private string _locDir;

		private string _locLeft;

		private string _locRight;

		private string _locUp;

		private string _locDown;

		private string _locFlash;

		private string _locClickable;

		private string _locPlaceholder;

		private string _locEnter;

		private string _locScanExternal;

		private string _locSaveConfig;

		private string _locLoadConfig;

		private string _locClickScanHint;

		private string _locExtBtns;

		private string _locExtLabels;

		private string _locExtSliders;

		private string _locExtOptions;

		private string _locExtArrows;

		private string _locExtInputs;

		private string _locPages;

		private string _locSavePage;

		private string _locLoadPage;

		private string _locRefresh;

		private string _locPageControls;

		private string _locPos;

		private string _locTarget;

		private string _locGlobalCanvas;

		private string _locGlobal;

		private string _locCurr;

		private string _locCreateBtn;

		private string _locCreateLabel;

		private string _locCreateSlider;

		private string _locCreateOption;

		private string _locCreateArrow;

		private string _locCreateInput;

		private string _locStyle;

		private string _locIcon;

		private string _locTextBtn;

		private string _locSmall;

		private string _locIconPath;

		private string _locToggleTexts;

		private string _locSetToggleTexts;

		private string _locApplyToggle;

		private string _locNewBtn;

		private string _locNewLabel;

		private string _locNewSlider;

		private string _locNewOpt;

		private string _locDescText;

		private string _locDescTextLabel;

		private string _locArrowClicked;

		private string _locClicked;

		private string _locEditButton;

		private string _locEditLabel;

		private string _locEditSlider;

		private string _locEditOption;

		private string _locEditArrow;

		private string _locEditInput;

		private string _locIconOffset;

		private string _locTitleOffset;

		private string _locDescOffset;

		private string _locCurrentValue;

		private string _locTextContent;

		private string _locWindowTitle;

		private string _locAuto;

		private string _locPinToPage;

		private const int EXTERNAL_CLEAN_INTERVAL = 30;

		private int _externalCleanFrameCounter;

		private static bool _tempDragEnabled;

		private static GameObject _tempDragTarget;

		public static DebugWindow Instance => _instance;

		private string PluginDirectory => NativeUIMakerMod.PluginDirectory;

		public static GameObject CurrentlySelectedForDrag { get; private set; }

		public static bool TempDragEnabled => _tempDragEnabled;

		public static GameObject TempDragTarget => _tempDragTarget;

		private void RefreshLocaleCache()
		{
			_locApplyChanges = UILocale.Get("应用更改");
			_locDeleteControl = UILocale.Get("删除此控件");
			_locDestroyed = UILocale.Get("控件已被销毁");
			_locNoSelection = UILocale.Get("未选中任何控件");
			_locDraggable = UILocale.Get("允许拖拽 (按住鼠标左键拖动)");
			_locHideWindow = UILocale.Get("隐藏窗口");
			_locLocal = UILocale.Get("本地控件");
			_locExternal = UILocale.Get("外部控件");
			_locPageMgmt = UILocale.Get("页面管理");
			_locTitle = UILocale.Get("标题:");
			_locDesc = UILocale.Get("描述:");
			_locPosXY = UILocale.Get("位置 (x, y):");
			_locSizeWH = UILocale.Get("尺寸 (宽, 高):");
			_locApplyIcon = UILocale.Get("应用图标偏移");
			_locApplyTitle = UILocale.Get("应用标题偏移");
			_locApplyDesc = UILocale.Get("应用描述偏移");
			_locText = UILocale.Get("文本:");
			_locFontSize = UILocale.Get("字体大小:");
			_locColorRGB = UILocale.Get("颜色 (R,G,B):");
			_locLabel = UILocale.Get("标签:");
			_locSliderXOff = UILocale.Get("滑块 X 偏移:");
			_locSliderWidth = UILocale.Get("滑块宽度 (0=原生):");
			_locLabelXOff = UILocale.Get("标签 X 偏移:");
			_locValueXOff = UILocale.Get("数值 X 偏移:");
			_locMin = UILocale.Get("最小值: {0}");
			_locMax = UILocale.Get("最大值: {0}");
			_locIntStep = UILocale.Get("整数步进");
			_locOptions = UILocale.Get("选项列表 (用逗号分隔):");
			_locSelected = UILocale.Get("当前选中: {0} (索引 {1})");
			_locPrev = UILocale.Get("上一个");
			_locNext = UILocale.Get("下一个");
			_locDir = UILocale.Get("方向:");
			_locLeft = UILocale.Get("左");
			_locRight = UILocale.Get("右");
			_locUp = UILocale.Get("上");
			_locDown = UILocale.Get("下");
			_locFlash = UILocale.Get("播放动画 (闪烁)");
			_locClickable = UILocale.Get("可点击 (添加按钮)");
			_locPlaceholder = UILocale.Get("占位符:");
			_locEnter = UILocale.Get("输入...");
			_locScanExternal = UILocale.Get("扫描外部控件");
			_locSaveConfig = UILocale.Get("保存配置");
			_locLoadConfig = UILocale.Get("加载配置");
			_locClickScanHint = UILocale.Get("点击“扫描外部控件”以发现其他模组创建的UI元素。");
			_locExtBtns = UILocale.Get("外部按钮");
			_locExtLabels = UILocale.Get("外部标签");
			_locExtSliders = UILocale.Get("外部滑块");
			_locExtOptions = UILocale.Get("外部选项行");
			_locExtArrows = UILocale.Get("外部箭头");
			_locExtInputs = UILocale.Get("外部输入框");
			_locPages = UILocale.Get("可用页面:");
			_locSavePage = UILocale.Get("保存页面配置");
			_locLoadPage = UILocale.Get("加载页面配置");
			_locRefresh = UILocale.Get("刷新");
			_locPageControls = UILocale.Get("页面内控件列表:");
			_locPos = UILocale.Get("位置");
			_locTarget = UILocale.Get("创建目标:");
			_locGlobalCanvas = UILocale.Get("全局画布 (独立于页面)");
			_locGlobal = UILocale.Get("全局画布");
			_locCurr = UILocale.Get("当前:");
			_locCreateBtn = UILocale.Get("=== 创建新按钮 ===");
			_locStyle = UILocale.Get("选择按钮样式:");
			_locIcon = UILocale.Get("图标按钮");
			_locTextBtn = UILocale.Get("纯文字按钮");
			_locSmall = UILocale.Get("小型按钮");
			_locIconPath = UILocale.Get("图标文件路径 (绝对或相对路径,留空则不设置):");
			_locToggleTexts = UILocale.Get("切换文字序列(逗号分隔):");
			_locSetToggleTexts = UILocale.Get("设置切换文字序列(逗号分隔):");
			_locApplyToggle = UILocale.Get("应用切换序列");
			_locNewBtn = UILocale.Get("新按钮");
			_locNewLabel = UILocale.Get("新标签");
			_locNewSlider = UILocale.Get("新滑块");
			_locNewOpt = UILocale.Get("新选项");
			_locDescText = UILocale.Get("这是描述文字");
			_locDescTextLabel = UILocale.Get("可编辑描述");
			_locArrowClicked = UILocale.Get("箭头被点击");
			_locClicked = UILocale.Get("按钮被点击");
			_locEditButton = UILocale.Get("编辑按钮: {0}");
			_locEditLabel = UILocale.Get("编辑标签: {0}");
			_locEditSlider = UILocale.Get("编辑滑块: {0}");
			_locEditOption = UILocale.Get("编辑选项行: {0}");
			_locEditArrow = UILocale.Get("编辑箭头: {0}");
			_locEditInput = UILocale.Get("编辑输入框");
			_locIconOffset = UILocale.Get("图标偏移 (x, y):");
			_locTitleOffset = UILocale.Get("标题文字偏移 (x, y):");
			_locDescOffset = UILocale.Get("描述文字偏移 (x, y):");
			_locCurrentValue = UILocale.Get("当前值: {0}");
			_locTextContent = UILocale.Get("文本内容:");
			_locWindowTitle = UILocale.Get("NativeUIMaker 调试窗口");
			_locAuto = UILocale.Get("Auto");
			_locPinToPage = UILocale.Get("固定到当前页面");
			_locCreateLabel = UILocale.Get("创建文本标签 (StandardLabel)");
			_locCreateSlider = UILocale.Get("创建滑块 (NativeSlider)");
			_locCreateOption = UILocale.Get("创建选项行 (NativeOption)");
			_locCreateArrow = UILocale.Get("创建新箭头");
			_locCreateInput = UILocale.Get("创建输入框");
			_cachedIsChinese = UILocale.IsChinese;
			_localeCacheValid = true;
		}

		private void CleanAllExternalLists()
		{
			if (_externalCleanFrameCounter++ % 30 == 0)
			{
				_externalButtons.RemoveAll((NativeButton b) => b == null || (Object)(object)b.gameObject == (Object)null);
				_externalLabels.RemoveAll((NativeLabel l) => l == null || (Object)(object)l.gameObject == (Object)null);
				_externalSliders.RemoveAll((NativeSlider s) => s == null || (Object)(object)s.gameObject == (Object)null);
				_externalOptions.RemoveAll((NativeOption o) => o == null || (Object)(object)o.gameObject == (Object)null);
				_externalArrows.RemoveAll((NativeArrow a) => a == null || (Object)(object)a.gameObject == (Object)null);
				_externalInputs.RemoveAll((NativeInput i) => i == null || (Object)(object)i.gameObject == (Object)null);
			}
		}

		public static void Create()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if (!((Object)(object)_instance != (Object)null))
			{
				GameObject val = new GameObject("DebugWindow");
				_instance = val.AddComponent<DebugWindow>();
				Object.DontDestroyOnLoad((Object)val);
			}
		}

		public GameObject GetSelectedGameObject()
		{
			if (_selectedControl == null)
			{
				return null;
			}
			if (_selectedControl is NativeButton nativeButton)
			{
				return nativeButton.gameObject;
			}
			if (_selectedControl is NativeLabel nativeLabel)
			{
				return nativeLabel.gameObject;
			}
			if (_selectedControl is NativeSlider nativeSlider)
			{
				return nativeSlider.gameObject;
			}
			if (_selectedControl is NativeOption nativeOption)
			{
				return nativeOption.gameObject;
			}
			if (_selectedControl is NativeArrow nativeArrow)
			{
				return nativeArrow.gameObject;
			}
			if (_selectedControl is NativeInput nativeInput)
			{
				return nativeInput.gameObject;
			}
			return null;
		}

		public void RefreshEditFieldsForSelected()
		{
			if (_selectedControl != null)
			{
				UpdateEditFieldsFromControl();
			}
		}

		private void OnGUI()
		{
			//IL_002b: 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_0047: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (_showWindow)
			{
				if (!_localeCacheValid || _cachedIsChinese != UILocale.IsChinese)
				{
					RefreshLocaleCache();
				}
				_windowRect = GUI.Window(123456, _windowRect, new WindowFunction(DrawWindow), _locWindowTitle);
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("CN", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				UILocale.SetForceChinese(true);
				_localeCacheValid = false;
			}
			if (GUILayout.Button("EN", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				UILocale.SetForceChinese(false);
				_localeCacheValid = false;
			}
			if (GUILayout.Button(_locAuto, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				UILocale.SetForceChinese(null);
				_localeCacheValid = false;
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(_locLocal, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				_selectedTab = 0;
			}
			if (GUILayout.Button(_locExternal, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				_selectedTab = 1;
			}
			if (GUILayout.Button(_locPageMgmt, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				_selectedTab = 2;
			}
			GUILayout.EndHorizontal();
			_scrollPos = GUILayout.BeginScrollView(_scrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			if (_selectedTab == 0)
			{
				DrawLocalControlsTab();
			}
			else if (_selectedTab == 1)
			{
				DrawExternalControlsTab();
			}
			else
			{
				DrawPageManagementTab();
			}
			GUILayout.EndScrollView();
			DrawUnifiedEditor();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(_locHideWindow, Array.Empty<GUILayoutOption>()))
			{
				_showWindow = false;
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
			GUI.DragWindow();
		}

		private void DrawLocalControlsTab()
		{
			DrawCreateTargetSelector();
			GUILayout.Space(10f);
			DrawCreateButtonSection();
			DrawLocalButtonsList();
			GUILayout.Space(10f);
			DrawCreateLabelSection();
			DrawLocalLabelsList();
			GUILayout.Space(10f);
			DrawCreateSliderSection();
			DrawLocalSlidersList();
			GUILayout.Space(10f);
			DrawCreateOptionSection();
			DrawLocalOptionsList();
			GUILayout.Space(10f);
			DrawCreateArrowSection();
			DrawLocalArrowsList();
			GUILayout.Space(10f);
			DrawCreateInputSection();
			DrawLocalInputsList();
		}

		private void RefreshPageDropdownList()
		{
			int count = NativePage.AllInstances.Count;
			bool flag = _pageDropdownVersion != count;
			if (!flag && _pageNamesForDropdown.Length > 1)
			{
				for (int i = 0; i < NativePage.AllInstances.Count; i++)
				{
					if (NativePage.AllInstances[i] == null)
					{
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			_pageDropdownVersion = count;
			List<NativePage> list = NativePage.AllInstances.Where((NativePage p) => p != null).ToList();
			_pageNamesForDropdown = new string[list.Count + 1];
			_pageNamesForDropdown[0] = UILocale.Get("全局画布 (独立于页面)");
			for (int num = 0; num < list.Count; num++)
			{
				_pageNamesForDropdown[num + 1] = ((Object)list[num].gameObject).name;
			}
			if (_selectedCreateTargetPage != null)
			{
				int num2 = list.IndexOf(_selectedCreateTargetPage);
				if (num2 >= 0)
				{
					_selectedPageDropdownIndex = num2 + 1;
					return;
				}
				_selectedCreateTargetPage = null;
				_selectedPageDropdownIndex = 0;
			}
			else
			{
				_selectedPageDropdownIndex = 0;
			}
		}

		private void DrawCreateTargetSelector()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(UILocale.Get("创建目标:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) });
			RefreshPageDropdownList();
			int num = GUILayout.SelectionGrid(_selectedPageDropdownIndex, _pageNamesForDropdown, 1, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
			if (num != _selectedPageDropdownIndex)
			{
				_selectedPageDropdownIndex = num;
				if (num == 0)
				{
					_selectedCreateTargetPage = null;
				}
				else
				{
					List<NativePage> list = NativePage.AllInstances.ToList();
					if (num - 1 < list.Count)
					{
						_selectedCreateTargetPage = list[num - 1];
					}
					else
					{
						_selectedCreateTargetPage = null;
					}
				}
			}
			if (_selectedCreateTargetPage != null)
			{
				GUILayout.Label(UILocale.Get("当前:") + " " + ((Object)_selectedCreateTargetPage.gameObject).name, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label(UILocale.Get("当前:") + " " + UILocale.Get("全局画布"), Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndHorizontal();
		}

		private RectTransform GetCurrentParent()
		{
			if (_selectedCreateTargetPage != null && (Object)(object)_selectedCreateTargetPage.rectTransform != (Object)null)
			{
				return _selectedCreateTargetPage.rectTransform;
			}
			return UIParent.GetDefaultParent();
		}

		private void DrawCreateButtonSection()
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			GUILayout.Label(UILocale.Get("=== 创建新按钮 ==="), Array.Empty<GUILayoutOption>());
			GUILayout.Label(UILocale.Get("选择按钮样式:"), Array.Empty<GUILayoutOption>());
			_selectedCreateStyle = (ButtonStyle)GUILayout.Toolbar((int)_selectedCreateStyle, new string[3]
			{
				UILocale.Get("图标按钮"),
				UILocale.Get("纯文字按钮"),
				UILocale.Get("小型按钮")
			}, Array.Empty<GUILayoutOption>());
			if (_selectedCreateStyle == ButtonStyle.IconButton)
			{
				GUILayout.Label(UILocale.Get("图标文件路径 (绝对或相对路径,留空则不设置):"), Array.Empty<GUILayoutOption>());
				_iconPathInput = GUILayout.TextField(_iconPathInput, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Label(UILocale.Get("切换文字序列(逗号分隔):"), Array.Empty<GUILayoutOption>());
			_toggleTextsInput = GUILayout.TextField(_toggleTextsInput, Array.Empty<GUILayoutOption>());
			if (!GUILayout.Button(string.Format(UILocale.Get("创建 {0}"), _styleNames[(int)_selectedCreateStyle]), Array.Empty<GUILayoutOption>()))
			{
				return;
			}
			NativeButton nativeButton = NativeButton.Create(GetCurrentParent(), _selectedCreateStyle);
			if (nativeButton == null)
			{
				return;
			}
			nativeButton.SetPosition(Vector2.zero);
			nativeButton.SetSize(400f, 100f);
			nativeButton.SetTitle(UILocale.Get("新按钮"));
			nativeButton.SetDescription(UILocale.Get("可编辑描述"));
			if (_selectedCreateStyle == ButtonStyle.IconButton && !string.IsNullOrEmpty(_iconPathInput))
			{
				Sprite val = NativeButton.LoadSpriteFromFile(_iconPathInput);
				if ((Object)(object)val != (Object)null)
				{
					nativeButton.SetIcon(val);
				}
			}
			string[] array = (from s in _toggleTextsInput.Split(new char[1] { ',' })
				select s.Trim()).ToArray();
			if (array.Length >= 2)
			{
				nativeButton.SetToggleTexts(array);
			}
			else if (array.Length == 1)
			{
				nativeButton.SetTitle(array[0]);
				nativeButton.SetDescription(array[0]);
			}
			else
			{
				object obj = <>c.<>9__211_1;
				if (obj == null)
				{
					UnityAction val2 = delegate
					{
						Debug.Log((object)UILocale.Get("按钮被点击"));
					};
					<>c.<>9__211_1 = val2;
					obj = (object)val2;
				}
				nativeButton.AddClickListener((UnityAction)obj);
			}
			_allButtons.Add(nativeButton);
			_selectedControl = nativeButton;
			UpdateEditFieldsFromControl();
		}

		private void DrawCreateLabelSection()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(UILocale.Get("=== 创建新标签 ==="), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("创建文本标签 (StandardLabel)"), Array.Empty<GUILayoutOption>()))
			{
				NativeLabel nativeLabel = NativeLabel.Create(GetCurrentParent());
				if (nativeLabel != null)
				{
					nativeLabel.SetPosition(Vector2.zero);
					nativeLabel.SetSize(400f, 60f);
					nativeLabel.SetText(UILocale.Get("新标签"));
					_allLabels.Add(nativeLabel);
					_selectedControl = nativeLabel;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawCreateSliderSection()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(UILocale.Get("=== 创建新滑块 ==="), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("创建滑块 (NativeSlider)"), Array.Empty<GUILayoutOption>()))
			{
				NativeSlider nativeSlider = NativeSlider.Create(GetCurrentParent());
				if (nativeSlider != null)
				{
					nativeSlider.SetPosition(Vector2.zero);
					nativeSlider.SetSize(600f, 60f);
					nativeSlider.SetLabel(UILocale.Get("新滑块"));
					nativeSlider.SetMinMax(0f, 100f);
					nativeSlider.Value = 50f;
					_allSliders.Add(nativeSlider);
					_selectedControl = nativeSlider;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawCreateOptionSection()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(UILocale.Get("=== 创建新选项行 (无滑块) ==="), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("创建选项行 (NativeOption)"), Array.Empty<GUILayoutOption>()))
			{
				NativeOption nativeOption = NativeOption.Create(GetCurrentParent());
				if (nativeOption != null)
				{
					nativeOption.SetPosition(Vector2.zero);
					nativeOption.SetSize(600f, 80f);
					nativeOption.SetLabel(UILocale.Get("新选项"));
					nativeOption.SetDescription(UILocale.Get("这是描述文字"));
					nativeOption.SetOptions(new string[2]
					{
						UILocale.Get("选项1"),
						UILocale.Get("选项2")
					});
					_allOptions.Add(nativeOption);
					_selectedControl = nativeOption;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawCreateArrowSection()
		{
			GUILayout.Label(UILocale.Get("=== 创建新箭头 ==="), Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("左箭头"), Array.Empty<GUILayoutOption>()))
			{
				CreateArrow(NativeArrow.Direction.Left);
			}
			if (GUILayout.Button(UILocale.Get("右箭头"), Array.Empty<GUILayoutOption>()))
			{
				CreateArrow(NativeArrow.Direction.Right);
			}
			if (GUILayout.Button(UILocale.Get("上箭头"), Array.Empty<GUILayoutOption>()))
			{
				CreateArrow(NativeArrow.Direction.Up);
			}
			if (GUILayout.Button(UILocale.Get("下箭头"), Array.Empty<GUILayoutOption>()))
			{
				CreateArrow(NativeArrow.Direction.Down);
			}
			GUILayout.EndHorizontal();
		}

		private void CreateArrow(NativeArrow.Direction dir)
		{
			//IL_0011: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			NativeArrow nativeArrow = NativeArrow.Create(GetCurrentParent(), dir);
			if (nativeArrow == null)
			{
				return;
			}
			nativeArrow.SetPosition(Vector2.zero);
			nativeArrow.SetSize(80f, 80f);
			object obj = <>c.<>9__216_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					Debug.Log((object)UILocale.Get("箭头被点击"));
				};
				<>c.<>9__216_0 = val;
				obj = (object)val;
			}
			nativeArrow.SetClickable(clickable: true, (UnityAction)obj);
			_allArrows.Add(nativeArrow);
			_selectedControl = nativeArrow;
			UpdateEditFieldsFromControl();
		}

		private void DrawCreateInputSection()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(UILocale.Get("=== 创建新输入框 ==="), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("创建输入框"), Array.Empty<GUILayoutOption>()))
			{
				NativeInput nativeInput = NativeInput.Create(GetCurrentParent());
				if (nativeInput != null)
				{
					nativeInput.SetPosition(Vector2.zero);
					nativeInput.SetSize(300f, 60f);
					nativeInput.SetText("");
					_allInputs.Add(nativeInput);
					_selectedControl = nativeInput;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawLocalButtonsList()
		{
			GUILayout.Label(UILocale.Get("=== 已创建的按钮 ==="), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _allButtons.Count; i++)
			{
				NativeButton nativeButton = _allButtons[i];
				if (nativeButton != null && !((Object)(object)nativeButton.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("按钮 {0}: {1}"), i, nativeButton.GetTitle()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeButton;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawLocalLabelsList()
		{
			GUILayout.Label(UILocale.Get("=== 已创建的标签 ==="), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _allLabels.Count; i++)
			{
				NativeLabel nativeLabel = _allLabels[i];
				if (nativeLabel != null && !((Object)(object)nativeLabel.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("标签 {0}: {1}"), i, nativeLabel.GetText()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeLabel;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawLocalSlidersList()
		{
			GUILayout.Label(UILocale.Get("=== 已创建的滑块 ==="), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _allSliders.Count; i++)
			{
				NativeSlider nativeSlider = _allSliders[i];
				if (nativeSlider != null && !((Object)(object)nativeSlider.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("滑块 {0}: {1} 当前值={2}"), i, nativeSlider.GetLabel(), nativeSlider.Value), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeSlider;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawLocalOptionsList()
		{
			GUILayout.Label(UILocale.Get("=== 已创建的选项行 ==="), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _allOptions.Count; i++)
			{
				NativeOption nativeOption = _allOptions[i];
				if (nativeOption != null && !((Object)(object)nativeOption.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("选项 {0}: {1} 当前值={2}"), i, nativeOption.GetLabel(), nativeOption.GetCurrentValue()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeOption;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawLocalArrowsList()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(UILocale.Get("=== 已创建的箭头 ==="), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _allArrows.Count; i++)
			{
				NativeArrow nativeArrow = _allArrows[i];
				if (nativeArrow != null && !((Object)(object)nativeArrow.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("箭头 {0}: {1} 位置={2}"), i, nativeArrow.GetDirection(), nativeArrow.GetPosition()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeArrow;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawLocalInputsList()
		{
			GUILayout.Label(UILocale.Get("=== 已创建的输入框 ==="), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _allInputs.Count; i++)
			{
				NativeInput nativeInput = _allInputs[i];
				if (nativeInput != null && !((Object)(object)nativeInput.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("输入框 {0}: {1}"), i, nativeInput.GetText()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeInput;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawExternalControlsTab()
		{
			CleanAllExternalLists();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("扫描外部控件"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				ScanExternalControls();
				_externalScanned = true;
			}
			if (GUILayout.Button(UILocale.Get("保存配置"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				SaveConfigToFile();
			}
			if (GUILayout.Button(UILocale.Get("加载配置"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				LoadConfigFromFile();
			}
			GUILayout.EndHorizontal();
			if (!_externalScanned)
			{
				GUILayout.Label(UILocale.Get("点击“扫描外部控件”以发现其他模组创建的UI元素。"), Array.Empty<GUILayoutOption>());
				return;
			}
			DrawExternalButtonsList();
			GUILayout.Space(10f);
			DrawExternalLabelsList();
			GUILayout.Space(10f);
			DrawExternalSlidersList();
			GUILayout.Space(10f);
			DrawExternalOptionsList();
			GUILayout.Space(10f);
			DrawExternalArrowsList();
			GUILayout.Space(10f);
			DrawExternalInputsList();
		}

		private void ScanExternalControls()
		{
			CleanInvalidControls();
			_externalButtons.Clear();
			_externalLabels.Clear();
			_externalSliders.Clear();
			_externalOptions.Clear();
			_externalArrows.Clear();
			_externalInputs.Clear();
			_arrowGameObjectSet.Clear();
			foreach (NativeArrow allInstance in NativeArrow.AllInstances)
			{
				if (allInstance != null && (Object)(object)allInstance.gameObject != (Object)null)
				{
					_arrowGameObjectSet.Add(allInstance.gameObject);
				}
			}
			BuildLocalControlSets();
			foreach (NativeButton allInstance2 in NativeButton.AllInstances)
			{
				if (allInstance2 != null && !((Object)(object)allInstance2.gameObject == (Object)null) && !_arrowGameObjectSet.Contains(allInstance2.gameObject) && !_localButtonSet.Contains(allInstance2))
				{
					_externalButtons.Add(allInstance2);
				}
			}
			foreach (NativeLabel allInstance3 in NativeLabel.AllInstances)
			{
				if (allInstance3 != null && !((Object)(object)allInstance3.gameObject == (Object)null) && !_localLabelSet.Contains(allInstance3))
				{
					_externalLabels.Add(allInstance3);
				}
			}
			foreach (NativeSlider allInstance4 in NativeSlider.AllInstances)
			{
				if (allInstance4 != null && !((Object)(object)allInstance4.gameObject == (Object)null) && !_localSliderSet.Contains(allInstance4))
				{
					_externalSliders.Add(allInstance4);
				}
			}
			foreach (NativeOption allInstance5 in NativeOption.AllInstances)
			{
				if (allInstance5 != null && !((Object)(object)allInstance5.gameObject == (Object)null) && !_localOptionSet.Contains(allInstance5))
				{
					_externalOptions.Add(allInstance5);
				}
			}
			foreach (NativeArrow allInstance6 in NativeArrow.AllInstances)
			{
				if (allInstance6 != null && !((Object)(object)allInstance6.gameObject == (Object)null) && !_localArrowSet.Contains(allInstance6))
				{
					_externalArrows.Add(allInstance6);
				}
			}
			foreach (NativeInput allInstance7 in NativeInput.AllInstances)
			{
				if (allInstance7 != null && !((Object)(object)allInstance7.gameObject == (Object)null) && !_localInputSet.Contains(allInstance7))
				{
					_externalInputs.Add(allInstance7);
				}
			}
			Debug.Log((object)$"扫描完成: 按钮={_externalButtons.Count}, 标签={_externalLabels.Count}, 滑块={_externalSliders.Count}, 选项={_externalOptions.Count}, 箭头={_externalArrows.Count}, 输入框={_externalInputs.Count}");
		}

		private void BuildLocalControlSets()
		{
			_localButtonSet.Clear();
			foreach (NativeButton allButton in _allButtons)
			{
				if (allButton != null)
				{
					_localButtonSet.Add(allButton);
				}
			}
			_localLabelSet.Clear();
			foreach (NativeLabel allLabel in _allLabels)
			{
				if (allLabel != null)
				{
					_localLabelSet.Add(allLabel);
				}
			}
			_localSliderSet.Clear();
			foreach (NativeSlider allSlider in _allSliders)
			{
				if (allSlider != null)
				{
					_localSliderSet.Add(allSlider);
				}
			}
			_localOptionSet.Clear();
			foreach (NativeOption allOption in _allOptions)
			{
				if (allOption != null)
				{
					_localOptionSet.Add(allOption);
				}
			}
			_localArrowSet.Clear();
			foreach (NativeArrow allArrow in _allArrows)
			{
				if (allArrow != null)
				{
					_localArrowSet.Add(allArrow);
				}
			}
			_localInputSet.Clear();
			foreach (NativeInput allInput in _allInputs)
			{
				if (allInput != null)
				{
					_localInputSet.Add(allInput);
				}
			}
		}

		private void DrawExternalButtonsList()
		{
			GUILayout.Label(string.Format("{0} ({1})", UILocale.Get("外部按钮"), _externalButtons.Count), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _externalButtons.Count; i++)
			{
				NativeButton nativeButton = _externalButtons[i];
				if (nativeButton != null && !((Object)(object)nativeButton.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("按钮 {0}: {1}"), i, nativeButton.GetTitle()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeButton;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawExternalLabelsList()
		{
			GUILayout.Label(string.Format("{0} ({1})", UILocale.Get("外部标签"), _externalLabels.Count), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _externalLabels.Count; i++)
			{
				NativeLabel nativeLabel = _externalLabels[i];
				if (nativeLabel != null && !((Object)(object)nativeLabel.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("标签 {0}: {1}"), i, nativeLabel.GetText()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeLabel;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawExternalSlidersList()
		{
			GUILayout.Label(string.Format("{0} ({1})", UILocale.Get("外部滑块"), _externalSliders.Count), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _externalSliders.Count; i++)
			{
				NativeSlider nativeSlider = _externalSliders[i];
				if (nativeSlider != null && !((Object)(object)nativeSlider.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("滑块 {0}: {1} 值={2}"), i, nativeSlider.GetLabel(), nativeSlider.Value), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeSlider;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawExternalOptionsList()
		{
			GUILayout.Label(string.Format("{0} ({1})", UILocale.Get("外部选项行"), _externalOptions.Count), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _externalOptions.Count; i++)
			{
				NativeOption nativeOption = _externalOptions[i];
				if (nativeOption != null && !((Object)(object)nativeOption.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("选项 {0}: {1} 当前={2}"), i, nativeOption.GetLabel(), nativeOption.GetCurrentValue()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeOption;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawExternalArrowsList()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(string.Format("{0} ({1})", UILocale.Get("外部箭头"), _externalArrows.Count), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _externalArrows.Count; i++)
			{
				NativeArrow nativeArrow = _externalArrows[i];
				if (nativeArrow != null && !((Object)(object)nativeArrow.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("箭头 {0}: {1} 位置={2}"), i, nativeArrow.GetDirection(), nativeArrow.GetPosition()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeArrow;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawExternalInputsList()
		{
			GUILayout.Label(string.Format("{0} ({1})", UILocale.Get("外部输入框"), _externalInputs.Count), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _externalInputs.Count; i++)
			{
				NativeInput nativeInput = _externalInputs[i];
				if (nativeInput != null && !((Object)(object)nativeInput.gameObject == (Object)null) && GUILayout.Button(string.Format(UILocale.Get("输入框 {0}: {1}"), i, nativeInput.GetText()), Array.Empty<GUILayoutOption>()))
				{
					_selectedControl = nativeInput;
					UpdateEditFieldsFromControl();
				}
			}
		}

		private void DrawUnifiedEditor()
		{
			if (_selectedControl == null)
			{
				GUILayout.Label(_locNoSelection, Array.Empty<GUILayoutOption>());
				return;
			}
			GameObject val = null;
			if (_selectedControl is NativeButton nativeButton)
			{
				val = nativeButton.gameObject;
			}
			else if (_selectedControl is NativeLabel nativeLabel)
			{
				val = nativeLabel.gameObject;
			}
			else if (_selectedControl is NativeSlider nativeSlider)
			{
				val = nativeSlider.gameObject;
			}
			else if (_selectedControl is NativeOption nativeOption)
			{
				val = nativeOption.gameObject;
			}
			else if (_selectedControl is NativeArrow nativeArrow)
			{
				val = nativeArrow.gameObject;
			}
			else if (_selectedControl is NativeInput nativeInput)
			{
				val = nativeInput.gameObject;
			}
			if ((Object)(object)val == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.BeginVertical(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>());
			if (_selectedControl is NativeButton btn)
			{
				DrawButtonEditor(btn);
			}
			else if (_selectedControl is NativeLabel lbl)
			{
				DrawLabelEditor(lbl);
			}
			else if (_selectedControl is NativeSlider sld)
			{
				DrawSliderEditor(sld);
			}
			else if (_selectedControl is NativeOption opt)
			{
				DrawOptionEditor(opt);
			}
			else if (_selectedControl is NativeArrow arr)
			{
				DrawArrowEditor(arr);
			}
			else if (_selectedControl is NativeInput inp)
			{
				DrawInputEditor(inp);
			}
			GUILayout.Space(10f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(_locPinToPage, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				PinSelectedControlToTargetPage();
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
		}

		private void DrawButtonEditor(NativeButton btn)
		{
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			if (btn == null || (Object)(object)btn.gameObject == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.Label(string.Format(_locEditButton, btn.GetTitle()), Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locTitle, Array.Empty<GUILayoutOption>());
			_editTitle = GUILayout.TextField(_editTitle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locDesc, Array.Empty<GUILayoutOption>());
			_editDesc = GUILayout.TextField(_editDesc, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPosXY, Array.Empty<GUILayoutOption>());
			_strPosX = GUILayout.TextField(_strPosX, Array.Empty<GUILayoutOption>());
			_strPosY = GUILayout.TextField(_strPosY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strPosX, out _editPos.x);
			float.TryParse(_strPosY, out _editPos.y);
			GUILayout.Label(_locSizeWH, Array.Empty<GUILayoutOption>());
			_strSizeW = GUILayout.TextField(_strSizeW, Array.Empty<GUILayoutOption>());
			_strSizeH = GUILayout.TextField(_strSizeH, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSizeW, out _editSize.x);
			float.TryParse(_strSizeH, out _editSize.y);
			if (btn.HasIcon())
			{
				GUILayout.Label(_locIconOffset, Array.Empty<GUILayoutOption>());
				_strIconOffX = GUILayout.TextField(_strIconOffX, Array.Empty<GUILayoutOption>());
				_strIconOffY = GUILayout.TextField(_strIconOffY, Array.Empty<GUILayoutOption>());
				float.TryParse(_strIconOffX, out _editIconOffset.x);
				float.TryParse(_strIconOffY, out _editIconOffset.y);
				if (GUILayout.Button(_locApplyIcon, Array.Empty<GUILayoutOption>()))
				{
					btn.SetIconOffset(_editIconOffset);
				}
			}
			GUILayout.Label(_locTitleOffset, Array.Empty<GUILayoutOption>());
			_strTitleOffX = GUILayout.TextField(_strTitleOffX, Array.Empty<GUILayoutOption>());
			_strTitleOffY = GUILayout.TextField(_strTitleOffY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strTitleOffX, out _editTitleOffset.x);
			float.TryParse(_strTitleOffY, out _editTitleOffset.y);
			if (GUILayout.Button(_locApplyTitle, Array.Empty<GUILayoutOption>()))
			{
				btn.SetTitleOffset(_editTitleOffset);
			}
			GUILayout.Label(_locDescOffset, Array.Empty<GUILayoutOption>());
			_strDescOffX = GUILayout.TextField(_strDescOffX, Array.Empty<GUILayoutOption>());
			_strDescOffY = GUILayout.TextField(_strDescOffY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strDescOffX, out _editDescOffset.x);
			float.TryParse(_strDescOffY, out _editDescOffset.y);
			if (GUILayout.Button(_locApplyDesc, Array.Empty<GUILayoutOption>()))
			{
				btn.SetDescOffset(_editDescOffset);
			}
			bool flag = btn.IsDraggable();
			bool flag2 = GUILayout.Toggle(flag, _locDraggable, Array.Empty<GUILayoutOption>());
			if (flag2 != flag)
			{
				btn.SetDraggable(flag2);
			}
			GUILayout.Label(_locSetToggleTexts, Array.Empty<GUILayoutOption>());
			_editToggleTextsInput = GUILayout.TextField(_editToggleTextsInput, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(_locApplyToggle, Array.Empty<GUILayoutOption>()))
			{
				string[] array = (from s in _editToggleTextsInput.Split(new char[1] { ',' })
					select s.Trim()).ToArray();
				if (array.Length >= 2)
				{
					btn.SetToggleTexts(array);
					UpdateEditFieldsFromControl();
				}
				else if (array.Length == 1)
				{
					btn.SetTitle(array[0]);
					btn.SetDescription(array[0]);
					btn.SetToggleTexts(null);
				}
				else
				{
					btn.SetToggleTexts(null);
				}
			}
			if (GUILayout.Button(_locApplyChanges, Array.Empty<GUILayoutOption>()))
			{
				btn.SetTitle(_editTitle);
				btn.SetDescription(_editDesc);
				btn.SetPosition(_editPos);
				btn.SetSize(_editSize.x, _editSize.y);
				if (btn.HasIcon())
				{
					btn.SetIconOffset(_editIconOffset);
				}
				btn.SetTitleOffset(_editTitleOffset);
				btn.SetDescOffset(_editDescOffset);
			}
			if (GUILayout.Button(_locDeleteControl, Array.Empty<GUILayoutOption>()))
			{
				btn.Destroy();
				RemoveFromList(btn);
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
			}
		}

		private void DrawLabelEditor(NativeLabel lbl)
		{
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			if (lbl == null || (Object)(object)lbl.gameObject == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.Label(string.Format(_locEditLabel, lbl.GetText()), Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locText, Array.Empty<GUILayoutOption>());
			_editLabelText = GUILayout.TextField(_editLabelText, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPosXY, Array.Empty<GUILayoutOption>());
			_strPosX = GUILayout.TextField(_strPosX, Array.Empty<GUILayoutOption>());
			_strPosY = GUILayout.TextField(_strPosY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strPosX, out _editPos.x);
			float.TryParse(_strPosY, out _editPos.y);
			GUILayout.Label(_locSizeWH, Array.Empty<GUILayoutOption>());
			_strSizeW = GUILayout.TextField(_strSizeW, Array.Empty<GUILayoutOption>());
			_strSizeH = GUILayout.TextField(_strSizeH, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSizeW, out _editSize.x);
			float.TryParse(_strSizeH, out _editSize.y);
			GUILayout.Label(_locFontSize, Array.Empty<GUILayoutOption>());
			_strFontSize = GUILayout.TextField(_strFontSize, Array.Empty<GUILayoutOption>());
			int.TryParse(_strFontSize, out _editFontSize);
			GUILayout.Label(_locColorRGB, Array.Empty<GUILayoutOption>());
			_strColor = GUILayout.TextField(_strColor, Array.Empty<GUILayoutOption>());
			if (_strColor != _lastParsedColor)
			{
				_lastParsedColor = _strColor;
				string[] array = _strColor.Split(new char[1] { ',' });
				if (array.Length == 3 && float.TryParse(array[0], out var result) && float.TryParse(array[1], out var result2) && float.TryParse(array[2], out var result3))
				{
					_editColor = new Color(result, result2, result3, 1f);
				}
			}
			bool flag = lbl.IsDraggable();
			bool flag2 = GUILayout.Toggle(flag, _locDraggable, Array.Empty<GUILayoutOption>());
			if (flag2 != flag)
			{
				lbl.SetDraggable(flag2);
			}
			if (GUILayout.Button(_locApplyChanges, Array.Empty<GUILayoutOption>()))
			{
				lbl.SetText(_editLabelText);
				lbl.SetPosition(_editPos);
				lbl.SetSize(_editSize.x, _editSize.y);
				lbl.SetFontSize(_editFontSize);
				lbl.SetColor(_editColor);
			}
			if (GUILayout.Button(_locDeleteControl, Array.Empty<GUILayoutOption>()))
			{
				lbl.Destroy();
				RemoveFromList(lbl);
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
			}
		}

		private void DrawSliderEditor(NativeSlider sld)
		{
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			if (sld == null || (Object)(object)sld.gameObject == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.Label(string.Format(_locEditSlider, sld.GetLabel()), Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locLabel, Array.Empty<GUILayoutOption>());
			_editSliderLabel = GUILayout.TextField(_editSliderLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPosXY, Array.Empty<GUILayoutOption>());
			_strPosX = GUILayout.TextField(_strPosX, Array.Empty<GUILayoutOption>());
			_strPosY = GUILayout.TextField(_strPosY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strPosX, out _editPos.x);
			float.TryParse(_strPosY, out _editPos.y);
			GUILayout.Label(_locSizeWH, Array.Empty<GUILayoutOption>());
			_strSizeW = GUILayout.TextField(_strSizeW, Array.Empty<GUILayoutOption>());
			_strSizeH = GUILayout.TextField(_strSizeH, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSizeW, out _editSize.x);
			float.TryParse(_strSizeH, out _editSize.y);
			GUILayout.Label(_locSliderXOff, Array.Empty<GUILayoutOption>());
			_strSliderXOff = GUILayout.TextField(_strSliderXOff, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSliderXOff, out _editSliderXOffset);
			GUILayout.Label(_locSliderWidth, Array.Empty<GUILayoutOption>());
			_strSliderWidth = GUILayout.TextField(_strSliderWidth, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSliderWidth, out _editSliderWidth);
			GUILayout.Label(_locLabelXOff, Array.Empty<GUILayoutOption>());
			_strLabelXOff = GUILayout.TextField(_strLabelXOff, Array.Empty<GUILayoutOption>());
			float.TryParse(_strLabelXOff, out _editLabelXOffset);
			GUILayout.Label(_locValueXOff, Array.Empty<GUILayoutOption>());
			_strValueXOff = GUILayout.TextField(_strValueXOff, Array.Empty<GUILayoutOption>());
			float.TryParse(_strValueXOff, out _editValueXOffset);
			GUILayout.Label(string.Format(_locMin, _editSliderMin), Array.Empty<GUILayoutOption>());
			_strSliderMin = GUILayout.TextField(_strSliderMin, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSliderMin, out _editSliderMin);
			GUILayout.Label(string.Format(_locMax, _editSliderMax), Array.Empty<GUILayoutOption>());
			_strSliderMax = GUILayout.TextField(_strSliderMax, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSliderMax, out _editSliderMax);
			GUILayout.Label(string.Format(_locCurrentValue, _editSliderValue), Array.Empty<GUILayoutOption>());
			_strSliderValue = GUILayout.TextField(_strSliderValue, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSliderValue, out _editSliderValue);
			_editSliderWhole = GUILayout.Toggle(_editSliderWhole, _locIntStep, Array.Empty<GUILayoutOption>());
			bool flag = sld.IsDraggable();
			bool flag2 = GUILayout.Toggle(flag, _locDraggable, Array.Empty<GUILayoutOption>());
			if (flag2 != flag)
			{
				sld.SetDraggable(flag2);
			}
			if (GUILayout.Button(_locApplyChanges, Array.Empty<GUILayoutOption>()))
			{
				Vector2 position = sld.GetPosition();
				Vector2 size = sld.GetSize();
				sld.SetLabel(_editSliderLabel);
				sld.SetSliderXOffset(_editSliderXOffset);
				sld.SetSliderWidth(_editSliderWidth);
				sld.SetLabelXOffset(_editLabelXOffset);
				sld.SetValueXOffset(_editValueXOffset);
				sld.SetMinMax(_editSliderMin, _editSliderMax, _editSliderWhole);
				sld.Value = _editSliderValue;
				sld.SetPosition(position);
				sld.SetSize(size.x, size.y);
			}
			if (GUILayout.Button(_locDeleteControl, Array.Empty<GUILayoutOption>()))
			{
				sld.Destroy();
				RemoveFromList(sld);
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
			}
		}

		private void DrawOptionEditor(NativeOption opt)
		{
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			if (opt == null || (Object)(object)opt.gameObject == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.Label(string.Format(_locEditOption, opt.GetLabel()), Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locLabel, Array.Empty<GUILayoutOption>());
			_editOptionLabel = GUILayout.TextField(_editOptionLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locDesc, Array.Empty<GUILayoutOption>());
			_editOptionDesc = GUILayout.TextField(_editOptionDesc, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPosXY, Array.Empty<GUILayoutOption>());
			_strPosX = GUILayout.TextField(_strPosX, Array.Empty<GUILayoutOption>());
			_strPosY = GUILayout.TextField(_strPosY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strPosX, out _editPos.x);
			float.TryParse(_strPosY, out _editPos.y);
			GUILayout.Label(_locSizeWH, Array.Empty<GUILayoutOption>());
			_strSizeW = GUILayout.TextField(_strSizeW, Array.Empty<GUILayoutOption>());
			_strSizeH = GUILayout.TextField(_strSizeH, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSizeW, out _editSize.x);
			float.TryParse(_strSizeH, out _editSize.y);
			GUILayout.Label(_locOptions, Array.Empty<GUILayoutOption>());
			string text = ((_editOptionOptions != null) ? string.Join(",", _editOptionOptions) : "");
			string text2 = GUILayout.TextField(text, Array.Empty<GUILayoutOption>());
			if (text2 != text)
			{
				_editOptionOptions = (from s in text2.Split(new char[1] { ',' })
					select s.Trim()).ToArray();
			}
			if (_editOptionOptions != null && _editOptionOptions.Length != 0)
			{
				_editOptionIndex = Mathf.Clamp(_editOptionIndex, 0, _editOptionOptions.Length - 1);
				GUILayout.Label(string.Format(_locSelected, _editOptionOptions[_editOptionIndex], _editOptionIndex), Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(_locPrev, Array.Empty<GUILayoutOption>()))
				{
					_editOptionIndex = (_editOptionIndex - 1 + _editOptionOptions.Length) % _editOptionOptions.Length;
				}
				if (GUILayout.Button(_locNext, Array.Empty<GUILayoutOption>()))
				{
					_editOptionIndex = (_editOptionIndex + 1) % _editOptionOptions.Length;
				}
				GUILayout.EndHorizontal();
			}
			bool flag = opt.IsDraggable();
			bool flag2 = GUILayout.Toggle(flag, _locDraggable, Array.Empty<GUILayoutOption>());
			if (flag2 != flag)
			{
				opt.SetDraggable(flag2);
			}
			if (GUILayout.Button(_locApplyChanges, Array.Empty<GUILayoutOption>()))
			{
				opt.SetLabel(_editOptionLabel);
				opt.SetDescription(_editOptionDesc);
				opt.SetPosition(_editPos);
				opt.SetSize(_editSize.x, _editSize.y);
				if (_editOptionOptions != null && _editOptionOptions.Length != 0)
				{
					opt.SetOptions(_editOptionOptions, _editOptionIndex);
				}
			}
			if (GUILayout.Button(_locDeleteControl, Array.Empty<GUILayoutOption>()))
			{
				opt.Destroy();
				RemoveFromList(opt);
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
			}
		}

		private void DrawArrowEditor(NativeArrow arr)
		{
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			if (arr == null || (Object)(object)arr.gameObject == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.Label(string.Format(_locEditArrow, arr.GetDirection()), Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPosXY, Array.Empty<GUILayoutOption>());
			_strPosX = GUILayout.TextField(_strPosX, Array.Empty<GUILayoutOption>());
			_strPosY = GUILayout.TextField(_strPosY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strPosX, out _editPos.x);
			float.TryParse(_strPosY, out _editPos.y);
			GUILayout.Label(_locSizeWH, Array.Empty<GUILayoutOption>());
			_strSizeW = GUILayout.TextField(_strSizeW, Array.Empty<GUILayoutOption>());
			_strSizeH = GUILayout.TextField(_strSizeH, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSizeW, out _editSize.x);
			float.TryParse(_strSizeH, out _editSize.y);
			_editArrowClickable = GUILayout.Toggle(_editArrowClickable, _locClickable, Array.Empty<GUILayoutOption>());
			_editArrowDraggable = GUILayout.Toggle(_editArrowDraggable, _locDraggable, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(_locApplyChanges, Array.Empty<GUILayoutOption>()))
			{
				arr.SetPosition(_editPos);
				arr.SetSize(_editSize.x, _editSize.y);
				arr.SetClickable(_editArrowClickable, (UnityAction)delegate
				{
					Debug.Log((object)_locArrowClicked);
				});
				arr.SetDraggable(_editArrowDraggable);
			}
			if (GUILayout.Button(_locDeleteControl, Array.Empty<GUILayoutOption>()))
			{
				arr.Destroy();
				RemoveFromList(arr);
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
			}
		}

		private void DrawInputEditor(NativeInput inp)
		{
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			if (inp == null || (Object)(object)inp.gameObject == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				GUILayout.Label(_locDestroyed, Array.Empty<GUILayoutOption>());
				return;
			}
			GUILayout.Label(_locEditInput, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locTextContent, Array.Empty<GUILayoutOption>());
			_editInputText = GUILayout.TextField(_editInputText, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPlaceholder, Array.Empty<GUILayoutOption>());
			_editInputPlaceholder = GUILayout.TextField(_editInputPlaceholder, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_locPosXY, Array.Empty<GUILayoutOption>());
			_strPosX = GUILayout.TextField(_strPosX, Array.Empty<GUILayoutOption>());
			_strPosY = GUILayout.TextField(_strPosY, Array.Empty<GUILayoutOption>());
			float.TryParse(_strPosX, out _editPos.x);
			float.TryParse(_strPosY, out _editPos.y);
			GUILayout.Label(_locSizeWH, Array.Empty<GUILayoutOption>());
			_strSizeW = GUILayout.TextField(_strSizeW, Array.Empty<GUILayoutOption>());
			_strSizeH = GUILayout.TextField(_strSizeH, Array.Empty<GUILayoutOption>());
			float.TryParse(_strSizeW, out _editSize.x);
			float.TryParse(_strSizeH, out _editSize.y);
			bool flag = inp.IsDraggable();
			bool flag2 = GUILayout.Toggle(flag, _locDraggable, Array.Empty<GUILayoutOption>());
			if (flag2 != flag)
			{
				inp.SetDraggable(flag2);
			}
			if (GUILayout.Button(_locApplyChanges, Array.Empty<GUILayoutOption>()))
			{
				inp.SetText(_editInputText);
				Graphic placeholder = inp.inputField.placeholder;
				Text val = (Text)(object)((placeholder is Text) ? placeholder : null);
				if ((Object)(object)val != (Object)null)
				{
					val.text = _editInputPlaceholder;
				}
				inp.SetPosition(_editPos);
				inp.SetSize(_editSize.x, _editSize.y);
			}
			if (GUILayout.Button(_locDeleteControl, Array.Empty<GUILayoutOption>()))
			{
				inp.Destroy();
				RemoveFromList(inp);
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
			}
		}

		private void UpdateEditFieldsFromControl()
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: 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_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: 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_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			if (_tempDragEnabled)
			{
				_tempDragEnabled = false;
				_tempDragTarget = null;
				Debug.Log((object)"[DebugWindow] 由于选中新控件,临时拖拽模式已关闭");
			}
			if (_selectedControl == null)
			{
				CurrentlySelectedForDrag = null;
				return;
			}
			GameObject val = null;
			if (_selectedControl is NativeButton nativeButton)
			{
				val = nativeButton.gameObject;
			}
			else if (_selectedControl is NativeLabel nativeLabel)
			{
				val = nativeLabel.gameObject;
			}
			else if (_selectedControl is NativeSlider nativeSlider)
			{
				val = nativeSlider.gameObject;
			}
			else if (_selectedControl is NativeOption nativeOption)
			{
				val = nativeOption.gameObject;
			}
			else if (_selectedControl is NativeArrow nativeArrow)
			{
				val = nativeArrow.gameObject;
			}
			else if (_selectedControl is NativeInput nativeInput)
			{
				val = nativeInput.gameObject;
			}
			if ((Object)(object)val == (Object)null)
			{
				_selectedControl = null;
				CurrentlySelectedForDrag = null;
				return;
			}
			if (_selectedControl is NativeButton nativeButton2)
			{
				_editTitle = nativeButton2.GetTitle();
				_editDesc = nativeButton2.GetDescription();
				_editPos = nativeButton2.GetPosition();
				_editSize = nativeButton2.GetSize();
				_editIconOffset = nativeButton2.GetIconOffset();
				_editTitleOffset = nativeButton2.GetTitleOffset();
				_editDescOffset = nativeButton2.GetDescOffset();
				if (nativeButton2.toggleTexts != null && nativeButton2.toggleTexts.Length != 0)
				{
					_editToggleTextsInput = string.Join(",", nativeButton2.toggleTexts);
				}
				else
				{
					_editToggleTextsInput = "";
				}
			}
			else if (_selectedControl is NativeLabel nativeLabel2)
			{
				_editLabelText = nativeLabel2.GetText();
				_editPos = nativeLabel2.GetPosition();
				_editSize = nativeLabel2.GetSize();
				Text textComponent = nativeLabel2.textComponent;
				_editFontSize = ((textComponent != null) ? textComponent.fontSize : 30);
				Text textComponent2 = nativeLabel2.textComponent;
				_editColor = ((textComponent2 != null) ? ((Graphic)textComponent2).color : Color.white);
			}
			else if (_selectedControl is NativeSlider nativeSlider2)
			{
				_editSliderLabel = nativeSlider2.GetLabel();
				_editPos = nativeSlider2.GetPosition();
				_editSize = nativeSlider2.GetSize();
				Slider slider = nativeSlider2.slider;
				_editSliderMin = ((slider != null) ? slider.minValue : 0f);
				Slider slider2 = nativeSlider2.slider;
				_editSliderMax = ((slider2 != null) ? slider2.maxValue : 100f);
				_editSliderValue = nativeSlider2.Value;
				Slider slider3 = nativeSlider2.slider;
				_editSliderWhole = slider3 == null || slider3.wholeNumbers;
				_editSliderXOffset = nativeSlider2.GetSliderXOffset();
				_editSliderWidth = nativeSlider2.GetSliderWidth();
				_editLabelXOffset = nativeSlider2.GetLabelXOffset();
				_editValueXOffset = nativeSlider2.GetValueXOffset();
			}
			else if (_selectedControl is NativeOption nativeOption2)
			{
				_editOptionLabel = nativeOption2.GetLabel();
				_editOptionDesc = nativeOption2.GetDescription();
				_editPos = nativeOption2.GetPosition();
				_editSize = nativeOption2.GetSize();
				_editOptionOptions = nativeOption2.GetOptions();
				_editOptionIndex = nativeOption2.GetCurrentIndex();
			}
			else if (_selectedControl is NativeArrow nativeArrow2)
			{
				_editPos = nativeArrow2.GetPosition();
				_editSize = nativeArrow2.GetSize();
				_editArrowDirection = (int)nativeArrow2.GetDirection();
				_editArrowClickable = nativeArrow2.IsClickable();
				_editArrowDraggable = nativeArrow2.IsDraggable();
			}
			else if (_selectedControl is NativeInput nativeInput2)
			{
				_editInputText = nativeInput2.GetText();
				_editPos = nativeInput2.GetPosition();
				_editSize = nativeInput2.GetSize();
				Graphic placeholder = nativeInput2.inputField.placeholder;
				Text val2 = (Text)(object)((placeholder is Text) ? placeholder : null);
				_editInputPlaceholder = (((Object)(object)val2 != (Object)null) ? val2.text : UILocale.Get("输入..."));
			}
			_strPosX = _editPos.x.ToString("F0");
			_strPosY = _editPos.y.ToString("F0");
			_strSizeW = _editSize.x.ToString("F0");
			_strSizeH = _editSize.y.ToString("F0");
			_strIconOffX = _editIconOffset.x.ToString("F0");
			_strIconOffY = _editIconOffset.y.ToString("F0");
			_strTitleOffX = _editTitleOffset.x.ToString("F0");
			_strTitleOffY = _editTitleOffset.y.ToString("F0");
			_strDescOffX = _editDescOffset.x.ToString("F0");
			_strDescOffY = _editDescOffset.y.ToString("F0");
			_strFontSize = _editFontSize.ToString();
			_strColor = $"{_editColor.r:F2},{_editColor.g:F2},{_editColor.b:F2}";
			_lastParsedColor = _strColor;
			_strSliderMin = _editSliderMin.ToString("F1");
			_strSliderMax = _editSliderMax.ToString("F1");
			_strSliderValue = _editSliderValue.ToString("F1");
			_strSliderXOff = _editSliderXOffset.ToString("F1");
			_strSliderWidth = _editSliderWidth.ToString("F1");
			_strLabelXOff = _editLabelXOffset.ToString("F1");
			_strValueXOff = _editValueXOffset.ToString("F1");
			CurrentlySelectedForDrag = GetSelectedGameObject();
		}

		private void RemoveFromList(object control)
		{
			if (control is NativeButton item)
			{
				_allButtons.Remove(item);
			}
			else if (control is NativeLabel item2)
			{
				_allLabels.Remove(item2);
			}
			else if (control is NativeSlider item3)
			{
				_allSliders.Remove(item3);
			}
			else if (control is NativeOption item4)
			{
				_allOptions.Remove(item4);
			}
			else if (control is NativeArrow item5)
			{
				_allArrows.Remove(item5);
			}
			else if (control is NativeInput item6)
			{
				_externalInputs.Remove(item6);
				_allInputs.Remove(item6);
			}
		}

		private void DrawPageManagementTab()
		{
			List<NativePage> allInstances = NativePage.AllInstances;
			GUILayout.Label(UILocale.Get("可用页面:"), Array.Empty<GUILayoutOption>());
			for (int i = 0; i < allInstances.Count; i++)
			{
				NativePage nativePage = allInstances[i];
				if (nativePage != null && GUILayout.Button(string.Format(UILocale.Get("页面 {0}: {1}"), i, ((Object)nativePage.gameObject).name), Array.Empty<GUILayoutOption>()))
				{
					_selectedPage = nativePage;
					RefreshPageControlsCache();
				}
			}
			if (_selectedPage == null)
			{
				return;
			}
			GUILayout.Label(string.Format(UILocale.Get("当前页面: {0} 包含控件: {1}"), ((Object)_selectedPage.gameObject).name, _pageControlsCache.Count), Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(UILocale.Get("保存页面配置"), Array.Empty<GUILayoutOption>()))
			{
				SavePageConfig();
			}
			if (GUILayout.Button(UILocale.Get("加载页面配置"), Array.Empty<GUILayoutOption>()))
			{
				LoadPageConfig();
			}
			if (GUILayout.Button(UILocale.Get("刷新"), Array.Empty<GUILayoutOption>()))
			{
				RefreshPageControlsCache();
			}
			GUILayout.EndHorizontal();
			GUILayout.Label(UILocale.Get("页面内控件列表:"), Array.Empty<GUILayoutOption>());
			foreach (UIControlConfig item in _pageControlsCache)
			{
				GUILayout.Label(string.Format("  {0}: {1} - {2}({3:F0},{4:F0})", item.type, item.name, UILocale.Get("位置"), item.position.x, item.position.y), Array.Empty<GUILayoutOption>());
			}
		}

		private void RefreshPageControlsCache()
		{
			if (_selectedPage != null)
			{
				_pageControlsCache.Clear();
				AddIfChild<NativeButton>(NativeButton.AllInstances);
				AddIfChild<NativeLabel>(NativeLabel.AllInstances);
				AddIfChild<NativeSlider>(NativeSlider.AllInstances);
				AddIfChild<NativeOption>(NativeOption.AllInstances);
				AddIfChild<NativeArrow>(NativeArrow.AllInstances);
				AddIfChild<NativeInput>(NativeInput.AllInstances);
			}
			void AddIfChild<T>(List<T> instances) where T : class
			{
				foreach (T instance in instances)
				{
					GameObject val = null;
					if (instance is NativeButton nativeButton)
					{
						val = nativeButton.gameObject;
					}
					else if (instance is NativeLabel nativeLabel)
					{
						val = nativeLabel.gameObject;
					}
					else if (instance is NativeSlider nativeSlider)
					{
						val = nativeSlider.gameObject;
					}
					else if (instance is NativeOption nativeOption)
					{
						val = nativeOption.gameObject;
					}
					else if (instance is NativeArrow nativeArrow)
					{
						val = nativeArrow.gameObject;
					}
					else if (instance is NativeInput nativeInput)
					{
						val = nativeInput.gameObject;
					}
					if ((Object)(object)val != (Object)null && IsChildOf(val.transform, _selectedPage.gameObject.transform))
					{
						_pageControlsCache.Add(GetControlConfig(instance));
					}
				}
			}
		}

		private bool IsChildOf(Transform child, Transform parent)
		{
			while ((Object)(object)child != (Object)null)
			{
				if ((Object)(object)child == (Object)(object)parent)
				{
					return true;
				}
				child = child.parent;
			}
			return false;
		}

		private UIControlConfig GetControlConfig(object ctrl)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			UIControlConfig uIControlConfig = new UIControlConfig();
			if (ctrl is NativeButton nativeButton)
			{
				uIControlConfig.type = "Button";
				uIControlConfig.name = ((Object)nativeButton.gameObject).name;
				uIControlConfig.position = nativeButton.GetPosition();
				uIControlConfig.size = nativeButton.GetSize();
				uIControlConfig.title = nativeButton.GetTitle();
				uIControlConfig.description = nativeButton.GetDescription();
				uIControlConfig.draggable = nativeButton.IsDraggable();
				uIControlConfig.iconOffset = nativeButton.GetIconOffset();
				uIControlConfig.titleOffset = nativeButton.GetTitleOffset();
				uIControlConfig.descOffset = nativeButton.GetDescOffset();
				uIControlConfig.style = (int)nativeButton.Style;
				if (nativeButton.toggleTexts != null && nativeButton.toggleTexts.Length != 0)
				{
					uIControlConfig.toggleTexts = nativeButton.toggleTexts;
					uIControlConfig.toggleIndex = nativeButton.currentToggleIndex;
				}
			}
			else if (ctrl is NativeLabel nativeLabel)
			{
				uIControlConfig.type = "Label";
				uIControlConfig.name = ((Object)nativeLabel.gameObject).name;
				uIControlConfig.position = nativeLabel.GetPosition();
				uIControlConfig.size = nativeLabel.GetSize();
				uIControlConfig.labelText = nativeLabel.GetText();
				Text textComponent = nativeLabel.textComponent;
				uIControlConfig.fontSize = ((textComponent != null) ? textComponent.fontSize : 30);
				Text textComponent2 = nativeLabel.textComponent;
				uIControlConfig.color = ((textComponent2 != null) ? ((Graphic)textComponent2).color : Color.white);
				uIControlConfig.draggable = nativeLabel.IsDraggable();
			}
			else if (ctrl is NativeSlider nativeSlider)
			{
				uIControlConfig.type = "Slider";
				uIControlConfig.name = ((Object)nativeSlider.gameObject).name;
				uIControlConfig.position = nativeSlider.GetPosition();
				uIControlConfig.size = nativeSlider.GetSize();
				uIControlConfig.labelText = nativeSlider.GetLabel();
				Slider slider = nativeSlider.slider;
				uIControlConfig.minValue = ((slider != null) ? slider.minValue : 0f);
				Slider slider2 = nativeSlider.slider;
				uIControlConfig.maxValue = ((slider2 != null) ? slider2.maxValue : 100f);
				uIControlConfig.value = nativeSlider.Value;
				Slider slider3 = nativeSlider.slider;
				uIControlConfig.wholeNumbers = slider3 == null || slider3.wholeNumbers;
				uIControlConfig.draggable = nativeSlider.IsDraggable();
				uIControlConfig.sliderXOffset = nativeSlider.GetSliderXOffset();
				uIControlConfig.sliderWidth = nativeSlider.GetSliderWidth();
				uIControlConfig.labelXOffset = nativeSlider.GetLabelXOffset();
				uIControlConfig.valueXOffset = nativeSlider.GetValueXOffset();
			}
			else if (ctrl is NativeOption nativeOption)
			{
				uIControlConfig.type = "Option";
				uIControlConfig.name = ((Object)nativeOption.gameObject).name;
				uIControlConfig.position = nativeOption.GetPosition();
				uIControlConfig.size = nativeOption.GetSize();
				uIControlConfig.labelText = nativeOption.GetLabel();
				uIControlConfig.description = nativeOption.GetDescription();
				uIControlConfig.options = nativeOption.GetOptions();
				uIControlConfig.optionIndex = nativeOption.GetCurrentIndex();
				uIControlConfig.draggable = nativeOption.IsDraggable();
			}
			else if (ctrl is NativeArrow nativeArrow)
			{
				uIControlConfig.type = "Arrow";
				uIControlConfig.name = ((Object)nativeArrow.gameObject).name;
				uIControlConfig.position = nativeArrow.GetPosition();
				uIControlConfig.size = nativeArrow.GetSize();
				uIControlConfig.direction = (int)nativeArrow.GetDirection();
				uIControlConfig.clickable = nativeArrow.IsClickable();
				uIControlConfig.draggable = nativeArrow.IsDraggable();
			}
			else if (ctrl is NativeInput nativeInput)
			{
				uIControlConfig.type = "Input";
				uIControlConfig.name = ((Object)nativeInput.gameObject).name;
				uIControlConfig.position = nativeInput.GetPosition();
				uIControlConfig.size = nativeInput.rectTransform.sizeDelta;
				uIControlConfig.inputText = nativeInput.GetText();
				Graphic placeholder = nativeInput.inputField.placeholder;
				Text val = (Text)(object)((placeholder is Text) ? placeholder : null);
				uIControlConfig.placeholderText = (((Object)(object)val != (Object)null) ? val.text : "");
			}
			return uIControlConfig;
		}

		private void SavePageConfig()
		{
			if (_selectedPage != null)
			{
				RefreshPageControlsCache();
				ConfigData configData = new ConfigData
				{
					controls = _pageControlsCache
				};
				string text = ((Object)_selectedPage.gameObject).name.Replace(" ", "_");
				string text2 = Path.Combine(PluginDirectory, "PageConfigs");
				Directory.CreateDirectory(text2);
				string text3 = Path.Combine(text2, "PageConfig_" + text + ".json");
				File.WriteAllText(text3, JsonConvert.SerializeObject((object)configData, SlimJson.Settings));
				Debug.Log((object)("页面配置已保存至 " + text3));
			}
		}

		private void LoadPageConfig()
		{
			if (_selectedPage == null)
			{
				return;
			}
			string text = ((Object)_selectedPage.gameObject).name.Replace(" ", "_");
			string text2 = Path.Combine(Path.Combine(PluginDirectory, "PageConfigs"), "PageConfig_" + text + ".json");
			if (!File.Exists(text2))
			{
				return;
			}
			ConfigData configData = JsonConvert.DeserializeObject<ConfigData>(File.ReadAllText(text2));
			if (configData == null)
			{
				return;
			}
			foreach (UIControlConfig control in configData.controls)
			{
				ApplyConfigToControlInPage(control);
			}
			Canvas.ForceUpdateCanvases();
			Debug.Log((object)("已加载页面配置 " + text2));
		}

		private void ApplyConfigToControlInPage(UIControlConfig cfg)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Expected O, but got Unknown
			GameObject val = FindChildByName(_selectedPage.gameObject.transform, cfg.name);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (cfg.type == "Button")
			{
				NativeButton component = val.GetComponent<NativeButton>();
				if (component == null)
				{
					return;
				}
				if (component.Style != (ButtonStyle)cfg.style)
				{
					component.SetStyle((ButtonStyle)cfg.style);
				}
				component.SetPosition(cfg.position);
				component.SetSize(cfg.size.x, cfg.size.y);
				if (!string.IsNullOrEmpty(cfg.title))
				{
					component.SetTitle(cfg.title.Trim());
				}
				if (!string.IsNullOrEmpty(cfg.description))
				{
					component.SetDescription(cfg.description.Trim());
				}
				component.SetDraggable(cfg.draggable);
				component.SetIconOffset(cfg.iconOffset);
				component.SetTitleOffset(cfg.titleOffset);
				component.SetDescOffset(cfg.descOffset);
				if (cfg.toggleTexts != null && cfg.toggleTexts.Length != 0)
				{
					component.SetToggleTexts(cfg.toggleTexts);
					if (cfg.toggleIndex >= 0 && cfg.toggleIndex < cfg.toggleTexts.Length)
					{
						component.SetToggleIndex(cfg.toggleIndex);
					}
				}
			}
			else if (cfg.type == "Label")
			{
				NativeLabel component2 = val.GetComponent<NativeLabel>();
				if (component2 != null)
				{
					component2.SetPosition(cfg.position);
					component2.SetSize(cfg.size.x, cfg.size.y);
					if (!string.IsNullOrEmpty(cfg.labelText))
					{
						component2.SetText(cfg.labelText.Trim());
					}
					if (cfg.fontSize > 0)
					{
						component2.SetFontSize(cfg.fontSize);
					}
					component2.SetColor(cfg.color);
					component2.SetDraggable(cfg.draggable);
				}
			}
			else if (cfg.type == "Slider")
			{
				NativeSlider component3 = val.GetComponent<NativeSlider>();
				if (component3 != null)
				{
					if (!string.IsNullOrEmpty(cfg.labelText))
					{
						component3.SetLabel(cfg.labelText.Trim());
					}
					component3.SetMinMax(cfg.minValue, cfg.maxValue, cfg.wholeNumbers);
					component3.SetValueWithoutNotify(cfg.value);
					component3.SetDraggable(cfg.draggable);
					component3.SetSliderXOffset(cfg.sliderXOffset);
					component3.SetSliderWidth(cfg.sliderWidth);
					component3.SetLabelXOffset(cfg.labelXOffset);
					component3.SetValueXOffset(cfg.valueXOffset);
					component3.SetPosition(cfg.position);
					component3.SetSize(cfg.size.x, cfg.size.y);
				}
			}
			else if (cfg.type == "Option")
			{
				NativeOption component4 = val.GetComponent<NativeOption>();
				if (component4 != null)
				{
					component4.SetPosition(cfg.position);
					component4.SetSize(cfg.size.x, cfg.size.y);
					if (!string.IsNullOrEmpty(cfg.labelText))
					{
						component4.SetLabel(cfg.labelText.Trim());
					}
					if (!string.IsNullOrEmpty(cfg.description))
					{
						component4.SetDescription(cfg.description.Trim());
					}
					if (cfg.options != null && cfg.options.Length != 0)
					{
						component4.SetOptions(cfg.options, cfg.optionIndex);
					}
					component4.SetDraggable(cfg.draggable);
				}
			}
			else if (cfg.type == "Arrow")
			{
				NativeArrow component5 = val.GetComponent<NativeArrow>();
				if (component5 == null)
				{
					return;
				}
				component5.SetPosition(cfg.position);
				component5.SetSize(cfg.size.x, cfg.size.y);
				bool clickable = cfg.clickable;
				object obj = <>c.<>9__248_0;
				if (obj == null)
				{
					UnityAction val2 = delegate
					{
						Debug.Log((object)UILocale.Get("箭头被点击"));
					};
					<>c.<>9__248_0 = val2;
					obj = (object)val2;
				}
				component5.SetClickable(clickable, (UnityAction)obj);
				component5.SetDraggable(cfg.draggable);
			}
			else
			{
				if (!(cfg.type == "Input"))
				{
					return;
				}
				NativeInput component6 = val.GetComponent<NativeInput>();
				if (component6 != null)
				{
					component6.SetPosition(cfg.position);
					component6.SetSize(cfg.size.x, cfg.size.y);
					component6.SetText(cfg.inputText);
					Graphic placeholder = component6.inputField.placeholder;
					Text val3 = (Text)(object)((placeholder is Text) ? placeholder : null);
					if ((Object)(object)val3 != (Object)null)
					{
						val3.text = cfg.placeholderText;
					}
				}
			}
		}

		private GameObject FindChildByName(Transform parent, string name)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (((Object)parent).name == name)
			{
				return ((Component)parent).gameObject;
			}
			foreach (Transform item in parent)
			{
				Transform parent2 = item;
				GameObject val = FindChildByName(parent2, name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private void CleanInvalidControls()
		{
			_externalButtons.RemoveAll((NativeButton b) => b == null || (Object)(object)b.gameObject == (Object)null);
			_externalLabels.RemoveAll((NativeLabel l) => l == null || (Object)(object)l.gameObject == (Object)null);
			_externalSliders.RemoveAll((NativeSlider s) => s == null || (Object)(object)s.gameObject == (Object)null);
			_externalOptions.RemoveAll((NativeOption o) => o == null || (Object)(object)o.gameObject == (Object)null);
			_externalArrows.RemoveAll((NativeArrow a) => a == null || (Object)(object)a.gameObject == (Object)null);
			_externalInputs.RemoveAll((NativeInput i) => i == null || (Object)(object)i.gameObject == (Object)null);
		}

		private void EnsureUniqueNames()
		{
			EnsureUniqueNamesInList(_externalButtons);
			EnsureUniqueNamesInList(_externalLabels);
			EnsureUniqueNamesInList(_externalSliders);
			EnsureUniqueNamesInList(_externalOptions);
			EnsureUniqueNamesInList(_externalArrows);
			EnsureUniqueNamesInList(_externalInputs);
		}

		private void EnsureUniqueNamesInList<T>(List<T> list) where T : class
		{
			if (list == null)
			{
				return;
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			List<GameObject> list2 = new List<GameObject>();
			foreach (T item in list)
			{
				GameObject val = null;
				if (item is NativeButton nativeButton)
				{
					val = nativeButton.gameObject;
				}
				else if (item is NativeLabel nativeLabel)
				{
					val = nativeLabel.gameObject;
				}
				else if (item is NativeSlider nativeSlider)
				{
					val = nativeSlider.gameObject;
				}
				else if (item is NativeOption nativeOption)
				{
					val = nativeOption.gameObject;
				}
				else if (item is NativeArrow nativeArrow)
				{
					val = nativeArrow.gameObject;
				}
				else if (item is NativeInput nativeInput)
				{
					val = nativeInput.gameObject;
				}
				if ((Object)(object)val != (Object)null)
				{
					list2.Add(val);
				}
			}
			foreach (GameObject item2 in list2)
			{
				string name = ((Object)item2).name;
				if (dictionary.ContainsKey(name))
				{
					dictionary[name]++;
				}
				else
				{
					dictionary[name] = 1;
				}
			}
			Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
			foreach (GameObject item3 in list2)
			{
				string name2 = ((Object)item3).name;
				if (dictionary[name2] > 1)
				{
					if (!dictionary2.ContainsKey(name2))
					{
						dictionary2[name2] = 1;
					}
					else
					{
						dictionary2[name2]++;
					}
					if (dictionary2[name2] > 1)
					{
						string text = (((Object)item3).name = $"{name2}_{dictionary2[name2]}");
						Debug.Log((object)("[DebugWindow] 为避免重名,已将控件 " + name2 + " 重命名为 " + text));
					}
				}
			}
		}

		private void SaveConfigToFile()
		{
			CleanInvalidControls();
			_externalButtons.RemoveAll((NativeButton btn) => NativeArrow.AllInstances.Any((NativeArrow arr) => arr != null && (Object)(object)arr.gameObject == (Object)(object)btn.gameObject));
			EnsureUniqueNames();
			string text = Path.Combine(PluginDirectory, "NativeUIMaker_Config.json");
			ConfigData configData = new ConfigData();
			CollectControls(_allButtons, "Button", configData);
			CollectControls(_allLabels, "Label", configData);
			CollectControls(_allSliders, "Slider", configData);
			CollectControls(_allOptions, "Option", configData);
			CollectControls(_allArrows, "Arrow", configData);
			CollectControls(_allInputs, "Input", configData);
			CollectControls(_externalButtons, "Button", configData);
			CollectControls(_externalLabels, "Label", configData);
			CollectControls(_externalSliders, "Slider", configData);
			CollectControls(_externalOptions, "Option", configData);
			CollectControls(_externalArrows, "Arrow", configData);
			CollectControls(_externalInputs, "Input", configData);
			File.WriteAllText(text, JsonConvert.SerializeObject((object)configData, SlimJson.Settings));
			Debug.Log((object)$"配置已保存至 {text},共 {configData.controls.Count} 项");
		}

		private string GetPageNameForControl(GameObject go)
		{
			Transform val = go.transform;
			while ((Object)(object)val != (Object)null)
			{
				foreach (NativePage allInstance in NativePage.AllInstances)
				{
					if ((Object)(object)allInstance.gameObject == (Object)(object)((Component)val).gameObject)
					{
						return ((Object)allInstance.gameObject).name;
					}
				}
				val = val.parent;
			}
			return null;
		}

		private void CollectControls<T>(List<T> list, string typeName, ConfigData data) where T : class
		{
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: 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_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: 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_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might 

BepInEx/plugins/Newtonsoft.Json.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;
using System.Xml.Linq;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq.JsonPath;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]
[assembly: AssemblyCompany("Newtonsoft")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © James Newton-King 2008")]
[assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")]
[assembly: AssemblyFileVersion("13.0.4.30916")]
[assembly: AssemblyInformationalVersion("13.0.4+4e13299d4b0ec96bd4df9954ef646bd2d1b5bf2a")]
[assembly: AssemblyProduct("Json.NET")]
[assembly: AssemblyTitle("Json.NET .NET 4.0")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("13.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
	internal sealed class DynamicallyAccessedMembersAttribute : Attribute
	{
		public DynamicallyAccessedMemberTypes MemberTypes { get; }

		public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
		{
			MemberTypes = memberTypes;
		}
	}
	[Flags]
	internal enum DynamicallyAccessedMemberTypes
	{
		None = 0,
		PublicParameterlessConstructor = 1,
		PublicConstructors = 3,
		NonPublicConstructors = 4,
		PublicMethods = 8,
		NonPublicMethods = 0x10,
		PublicFields = 0x20,
		NonPublicFields = 0x40,
		PublicNestedTypes = 0x80,
		NonPublicNestedTypes = 0x100,
		PublicProperties = 0x200,
		NonPublicProperties = 0x400,
		PublicEvents = 0x800,
		NonPublicEvents = 0x1000,
		Interfaces = 0x2000,
		All = -1
	}
	[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	internal sealed class FeatureGuardAttribute : Attribute
	{
		public Type FeatureType { get; }

		public FeatureGuardAttribute(Type featureType)
		{
			FeatureType = featureType;
		}
	}
	[AttributeUsage(AttributeTargets.Property, Inherited = false)]
	internal sealed class FeatureSwitchDefinitionAttribute : Attribute
	{
		public string SwitchName { get; }

		public FeatureSwitchDefinitionAttribute(string switchName)
		{
			SwitchName = switchName;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
	internal sealed class NotNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
	internal sealed class NotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public NotNullWhenAttribute(bool returnValue)
		{
			ReturnValue = returnValue;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
	internal sealed class MaybeNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
	internal sealed class AllowNullAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	internal class DoesNotReturnIfAttribute : Attribute
	{
		public bool ParameterValue { get; }

		public DoesNotReturnIfAttribute(bool parameterValue)
		{
			ParameterValue = parameterValue;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
	internal sealed class RequiresDynamicCodeAttribute : Attribute
	{
		public string Message { get; }

		public string? Url { get; set; }

		public RequiresDynamicCodeAttribute(string message)
		{
			Message = message;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
	internal sealed class RequiresUnreferencedCodeAttribute : Attribute
	{
		public string Message { get; }

		public string? Url { get; set; }

		public RequiresUnreferencedCodeAttribute(string message)
		{
			Message = message;
		}
	}
	[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
	internal sealed class UnconditionalSuppressMessageAttribute : Attribute
	{
		public string Category { get; }

		public string CheckId { get; }

		public string? Scope { get; set; }

		public string? Target { get; set; }

		public string? MessageId { get; set; }

		public string? Justification { get; set; }

		public UnconditionalSuppressMessageAttribute(string category, string checkId)
		{
			Category = category;
			CheckId = checkId;
		}
	}
}
namespace Newtonsoft.Json
{
	public enum ConstructorHandling
	{
		Default,
		AllowNonPublicDefaultConstructor
	}
	public enum DateFormatHandling
	{
		IsoDateFormat,
		MicrosoftDateFormat
	}
	public enum DateParseHandling
	{
		None,
		DateTime,
		DateTimeOffset
	}
	public enum DateTimeZoneHandling
	{
		Local,
		Utc,
		Unspecified,
		RoundtripKind
	}
	public class DefaultJsonNameTable : JsonNameTable
	{
		private class Entry
		{
			internal readonly string Value;

			internal readonly int HashCode;

			internal Entry Next;

			internal Entry(string value, int hashCode, Entry next)
			{
				Value = value;
				HashCode = hashCode;
				Next = next;
			}
		}

		private static readonly int HashCodeRandomizer;

		private int _count;

		private Entry[] _entries;

		private int _mask = 31;

		static DefaultJsonNameTable()
		{
			HashCodeRandomizer = Environment.TickCount;
		}

		public DefaultJsonNameTable()
		{
			_entries = new Entry[_mask + 1];
		}

		public override string? Get(char[] key, int start, int length)
		{
			if (length == 0)
			{
				return string.Empty;
			}
			int num = length + HashCodeRandomizer;
			num += (num << 7) ^ key[start];
			int num2 = start + length;
			for (int i = start + 1; i < num2; i++)
			{
				num += (num << 7) ^ key[i];
			}
			num -= num >> 17;
			num -= num >> 11;
			num -= num >> 5;
			int num3 = Thread.VolatileRead(ref _mask);
			int num4 = num & num3;
			for (Entry entry = _entries[num4]; entry != null; entry = entry.Next)
			{
				if (entry.HashCode == num && TextEquals(entry.Value, key, start, length))
				{
					return entry.Value;
				}
			}
			return null;
		}

		public string Add(string key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			int length = key.Length;
			if (length == 0)
			{
				return string.Empty;
			}
			int num = length + HashCodeRandomizer;
			for (int i = 0; i < key.Length; i++)
			{
				num += (num << 7) ^ key[i];
			}
			num -= num >> 17;
			num -= num >> 11;
			num -= num >> 5;
			for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next)
			{
				if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal))
				{
					return entry.Value;
				}
			}
			return AddEntry(key, num);
		}

		private string AddEntry(string str, int hashCode)
		{
			int num = hashCode & _mask;
			Entry entry = new Entry(str, hashCode, _entries[num]);
			_entries[num] = entry;
			if (_count++ == _mask)
			{
				Grow();
			}
			return entry.Value;
		}

		private void Grow()
		{
			Entry[] entries = _entries;
			int num = _mask * 2 + 1;
			Entry[] array = new Entry[num + 1];
			for (int i = 0; i < entries.Length; i++)
			{
				Entry entry = entries[i];
				while (entry != null)
				{
					int num2 = entry.HashCode & num;
					Entry next = entry.Next;
					entry.Next = array[num2];
					array[num2] = entry;
					entry = next;
				}
			}
			_entries = array;
			Thread.VolatileWrite(ref _mask, num);
		}

		private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length)
		{
			if (str1.Length != str2Length)
			{
				return false;
			}
			for (int i = 0; i < str1.Length; i++)
			{
				if (str1[i] != str2[str2Start + i])
				{
					return false;
				}
			}
			return true;
		}
	}
	[Flags]
	public enum DefaultValueHandling
	{
		Include = 0,
		Ignore = 1,
		Populate = 2,
		IgnoreAndPopulate = 3
	}
	public enum FloatFormatHandling
	{
		String,
		Symbol,
		DefaultValue
	}
	public enum FloatParseHandling
	{
		Double,
		Decimal
	}
	public enum Formatting
	{
		None,
		Indented
	}
	public interface IArrayPool<T>
	{
		T[] Rent(int minimumLength);

		void Return(T[]? array);
	}
	public interface IJsonLineInfo
	{
		int LineNumber { get; }

		int LinePosition { get; }

		bool HasLineInfo();
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonArrayAttribute : JsonContainerAttribute
	{
		private bool _allowNullItems;

		public bool AllowNullItems
		{
			get
			{
				return _allowNullItems;
			}
			set
			{
				_allowNullItems = value;
			}
		}

		public JsonArrayAttribute()
		{
		}

		public JsonArrayAttribute(bool allowNullItems)
		{
			_allowNullItems = allowNullItems;
		}

		public JsonArrayAttribute(string id)
			: base(id)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)]
	public sealed class JsonConstructorAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public abstract class JsonContainerAttribute : Attribute
	{
		internal bool? _isReference;

		internal bool? _itemIsReference;

		internal ReferenceLoopHandling? _itemReferenceLoopHandling;

		internal TypeNameHandling? _itemTypeNameHandling;

		private Type? _namingStrategyType;

		private object[]? _namingStrategyParameters;

		public string? Id { get; set; }

		public string? Title { get; set; }

		public string? Description { get; set; }

		public Type? ItemConverterType { get; set; }

		public object[]? ItemConverterParameters { get; set; }

		public Type? NamingStrategyType
		{
			get
			{
				return _namingStrategyType;
			}
			set
			{
				_namingStrategyType = value;
				NamingStrategyInstance = null;
			}
		}

		public object[]? NamingStrategyParameters
		{
			get
			{
				return _namingStrategyParameters;
			}
			set
			{
				_namingStrategyParameters = value;
				NamingStrategyInstance = null;
			}
		}

		internal NamingStrategy? NamingStrategyInstance { get; set; }

		public bool IsReference
		{
			get
			{
				return _isReference == true;
			}
			set
			{
				_isReference = value;
			}
		}

		public bool ItemIsReference
		{
			get
			{
				return _itemIsReference == true;
			}
			set
			{
				_itemIsReference = value;
			}
		}

		public ReferenceLoopHandling ItemReferenceLoopHandling
		{
			get
			{
				return _itemReferenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_itemReferenceLoopHandling = value;
			}
		}

		public TypeNameHandling ItemTypeNameHandling
		{
			get
			{
				return _itemTypeNameHandling.GetValueOrDefault();
			}
			set
			{
				_itemTypeNameHandling = value;
			}
		}

		protected JsonContainerAttribute()
		{
		}

		protected JsonContainerAttribute(string id)
		{
			Id = id;
		}
	}
	public static class JsonConvert
	{
		public static readonly string True = "true";

		public static readonly string False = "false";

		public static readonly string Null = "null";

		public static readonly string Undefined = "undefined";

		public static readonly string PositiveInfinity = "Infinity";

		public static readonly string NegativeInfinity = "-Infinity";

		public static readonly string NaN = "NaN";

		public static Func<JsonSerializerSettings>? DefaultSettings { get; set; }

		public static string ToString(DateTime value)
		{
			return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
		}

		public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
		{
			DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
			using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
			stringWriter.Write('"');
			DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture);
			stringWriter.Write('"');
			return stringWriter.ToString();
		}

		public static string ToString(DateTimeOffset value)
		{
			return ToString(value, DateFormatHandling.IsoDateFormat);
		}

		public static string ToString(DateTimeOffset value, DateFormatHandling format)
		{
			using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
			stringWriter.Write('"');
			DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture);
			stringWriter.Write('"');
			return stringWriter.ToString();
		}

		public static string ToString(bool value)
		{
			if (!value)
			{
				return False;
			}
			return True;
		}

		public static string ToString(char value)
		{
			return ToString(char.ToString(value));
		}

		public static string ToString(Enum value)
		{
			return value.ToString("D");
		}

		public static string ToString(int value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(short value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(ushort value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(uint value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(long value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		private static string ToStringInternal(BigInteger value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(ulong value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(float value)
		{
			return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
		}

		private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value)))
			{
				return text;
			}
			if (floatFormatHandling == FloatFormatHandling.DefaultValue)
			{
				if (nullable)
				{
					return Null;
				}
				return "0.0";
			}
			return quoteChar + text + quoteChar;
		}

		public static string ToString(double value)
		{
			return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
		{
			return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
		}

		private static string EnsureDecimalPlace(double value, string text)
		{
			if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		private static string EnsureDecimalPlace(string text)
		{
			if (StringUtils.IndexOf(text, '.') != -1)
			{
				return text;
			}
			return text + ".0";
		}

		public static string ToString(byte value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		[CLSCompliant(false)]
		public static string ToString(sbyte value)
		{
			return value.ToString(null, CultureInfo.InvariantCulture);
		}

		public static string ToString(decimal value)
		{
			return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
		}

		public static string ToString(Guid value)
		{
			return ToString(value, '"');
		}

		internal static string ToString(Guid value, char quoteChar)
		{
			string text = value.ToString("D", CultureInfo.InvariantCulture);
			string text2 = quoteChar.ToString(CultureInfo.InvariantCulture);
			return text2 + text + text2;
		}

		public static string ToString(TimeSpan value)
		{
			return ToString(value, '"');
		}

		internal static string ToString(TimeSpan value, char quoteChar)
		{
			return ToString(value.ToString(), quoteChar);
		}

		public static string ToString(Uri? value)
		{
			if (value == null)
			{
				return Null;
			}
			return ToString(value, '"');
		}

		internal static string ToString(Uri value, char quoteChar)
		{
			return ToString(value.OriginalString, quoteChar);
		}

		public static string ToString(string? value)
		{
			return ToString(value, '"');
		}

		public static string ToString(string? value, char delimiter)
		{
			return ToString(value, delimiter, StringEscapeHandling.Default);
		}

		public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling)
		{
			if (delimiter != '"' && delimiter != '\'')
			{
				throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter");
			}
			return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling);
		}

		public static string ToString(object? value)
		{
			if (value == null)
			{
				return Null;
			}
			return ConvertUtils.GetTypeCode(value.GetType()) switch
			{
				PrimitiveTypeCode.String => ToString((string)value), 
				PrimitiveTypeCode.Char => ToString((char)value), 
				PrimitiveTypeCode.Boolean => ToString((bool)value), 
				PrimitiveTypeCode.SByte => ToString((sbyte)value), 
				PrimitiveTypeCode.Int16 => ToString((short)value), 
				PrimitiveTypeCode.UInt16 => ToString((ushort)value), 
				PrimitiveTypeCode.Int32 => ToString((int)value), 
				PrimitiveTypeCode.Byte => ToString((byte)value), 
				PrimitiveTypeCode.UInt32 => ToString((uint)value), 
				PrimitiveTypeCode.Int64 => ToString((long)value), 
				PrimitiveTypeCode.UInt64 => ToString((ulong)value), 
				PrimitiveTypeCode.Single => ToString((float)value), 
				PrimitiveTypeCode.Double => ToString((double)value), 
				PrimitiveTypeCode.DateTime => ToString((DateTime)value), 
				PrimitiveTypeCode.Decimal => ToString((decimal)value), 
				PrimitiveTypeCode.DBNull => Null, 
				PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), 
				PrimitiveTypeCode.Guid => ToString((Guid)value), 
				PrimitiveTypeCode.Uri => ToString((Uri)value), 
				PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), 
				PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), 
				_ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), 
			};
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value)
		{
			return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, Formatting formatting)
		{
			return SerializeObject(value, formatting, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return SerializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return SerializeObject(value, null, formatting, settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, JsonSerializerSettings? settings)
		{
			return SerializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			return SerializeObjectInternal(value, type, jsonSerializer);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings)
		{
			return SerializeObject(value, null, formatting, settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			jsonSerializer.Formatting = formatting;
			return SerializeObjectInternal(value, type, jsonSerializer);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer)
		{
			StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture);
			using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
			{
				jsonTextWriter.Formatting = jsonSerializer.Formatting;
				jsonSerializer.Serialize(jsonTextWriter, value, type);
			}
			return stringWriter.ToString();
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static object? DeserializeObject(string value)
		{
			return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static object? DeserializeObject(string value, JsonSerializerSettings settings)
		{
			return DeserializeObject(value, null, settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static object? DeserializeObject(string value, Type type)
		{
			return DeserializeObject(value, type, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static T? DeserializeObject<T>(string value)
		{
			return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
		{
			return DeserializeObject<T>(value);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
		{
			return DeserializeObject<T>(value, settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static T? DeserializeObject<T>(string value, params JsonConverter[] converters)
		{
			return (T)DeserializeObject(value, typeof(T), converters);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings)
		{
			return (T)DeserializeObject(value, typeof(T), settings);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters)
		{
			JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
			{
				Converters = converters
			} : null);
			return DeserializeObject(value, type, settings);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings)
		{
			ValidationUtils.ArgumentNotNull(value, "value");
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			if (!jsonSerializer.IsCheckAdditionalContentSet())
			{
				jsonSerializer.CheckAdditionalContent = true;
			}
			using JsonTextReader reader = new JsonTextReader(new StringReader(value));
			return jsonSerializer.Deserialize(reader, type);
		}

		[DebuggerStepThrough]
		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static void PopulateObject(string value, object target)
		{
			PopulateObject(value, target, null);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static void PopulateObject(string value, object target, JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
			using JsonReader jsonReader = new JsonTextReader(new StringReader(value));
			jsonSerializer.Populate(jsonReader, target);
			if (settings == null || !settings.CheckAdditionalContent)
			{
				return;
			}
			while (jsonReader.Read())
			{
				if (jsonReader.TokenType != JsonToken.Comment)
				{
					throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object.");
				}
			}
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeXmlNode(XmlNode? node)
		{
			return SerializeXmlNode(node, Formatting.None);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeXmlNode(XmlNode? node, Formatting formatting)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
			return SerializeObject(node, formatting, xmlNodeConverter);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter
			{
				OmitRootObject = omitRootObject
			};
			return SerializeObject(node, formatting, xmlNodeConverter);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XmlDocument? DeserializeXmlNode(string value)
		{
			return DeserializeXmlNode(value, null);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName)
		{
			return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute)
		{
			return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
			xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName;
			xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute;
			xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters;
			return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeXNode(XObject? node)
		{
			return SerializeXNode(node, Formatting.None);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeXNode(XObject? node, Formatting formatting)
		{
			return SerializeXNode(node, formatting, omitRootObject: false);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject)
		{
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter
			{
				OmitRootObject = omitRootObject
			};
			return SerializeObject(node, formatting, xmlNodeConverter);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XDocument? DeserializeXNode(string value)
		{
			return DeserializeXNode(value, null);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName)
		{
			return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute)
		{
			return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false);
		}

		[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
		[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
		public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
			xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName;
			xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute;
			xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters;
			return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter);
		}
	}
	public abstract class JsonConverter
	{
		public virtual bool CanRead => true;

		public virtual bool CanWrite => true;

		public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer);

		public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer);

		public abstract bool CanConvert(Type objectType);
	}
	public abstract class JsonConverter<T> : JsonConverter
	{
		public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
		{
			if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T))))
			{
				throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
			}
			WriteJson(writer, (T)value, serializer);
		}

		public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer);

		public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
		{
			bool flag = existingValue == null;
			if (!flag && !(existingValue is T))
			{
				throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
			}
			return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer);
		}

		public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer);

		public sealed override bool CanConvert(Type objectType)
		{
			return typeof(T).IsAssignableFrom(objectType);
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)]
	public sealed class JsonConverterAttribute : Attribute
	{
		private readonly Type _converterType;

		public Type ConverterType => _converterType;

		public object[]? ConverterParameters { get; }

		public JsonConverterAttribute(Type converterType)
		{
			if (converterType == null)
			{
				throw new ArgumentNullException("converterType");
			}
			_converterType = converterType;
		}

		public JsonConverterAttribute(Type converterType, params object[] converterParameters)
			: this(converterType)
		{
			ConverterParameters = converterParameters;
		}
	}
	public class JsonConverterCollection : Collection<JsonConverter>
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonDictionaryAttribute : JsonContainerAttribute
	{
		public JsonDictionaryAttribute()
		{
		}

		public JsonDictionaryAttribute(string id)
			: base(id)
		{
		}
	}
	[Serializable]
	public class JsonException : Exception
	{
		public JsonException()
		{
		}

		public JsonException(string message)
			: base(message)
		{
		}

		public JsonException(string message, Exception? innerException)
			: base(message, innerException)
		{
		}

		public JsonException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			return new JsonException(message);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public class JsonExtensionDataAttribute : Attribute
	{
		public bool WriteData { get; set; }

		public bool ReadData { get; set; }

		public JsonExtensionDataAttribute()
		{
			WriteData = true;
			ReadData = true;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class JsonIgnoreAttribute : Attribute
	{
	}
	public abstract class JsonNameTable
	{
		public abstract string? Get(char[] key, int start, int length);
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)]
	public sealed class JsonObjectAttribute : JsonContainerAttribute
	{
		private MemberSerialization _memberSerialization;

		internal MissingMemberHandling? _missingMemberHandling;

		internal Required? _itemRequired;

		internal NullValueHandling? _itemNullValueHandling;

		public MemberSerialization MemberSerialization
		{
			get
			{
				return _memberSerialization;
			}
			set
			{
				_memberSerialization = value;
			}
		}

		public MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling.GetValueOrDefault();
			}
			set
			{
				_missingMemberHandling = value;
			}
		}

		public NullValueHandling ItemNullValueHandling
		{
			get
			{
				return _itemNullValueHandling.GetValueOrDefault();
			}
			set
			{
				_itemNullValueHandling = value;
			}
		}

		public Required ItemRequired
		{
			get
			{
				return _itemRequired.GetValueOrDefault();
			}
			set
			{
				_itemRequired = value;
			}
		}

		public JsonObjectAttribute()
		{
		}

		public JsonObjectAttribute(MemberSerialization memberSerialization)
		{
			MemberSerialization = memberSerialization;
		}

		public JsonObjectAttribute(string id)
			: base(id)
		{
		}
	}
	internal enum JsonContainerType
	{
		None,
		Object,
		Array,
		Constructor
	}
	internal struct JsonPosition
	{
		private static readonly char[] SpecialCharacters = new char[18]
		{
			'.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t',
			'\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029'
		};

		internal JsonContainerType Type;

		internal int Position;

		internal string? PropertyName;

		internal bool HasIndex;

		public JsonPosition(JsonContainerType type)
		{
			Type = type;
			HasIndex = TypeHasIndex(type);
			Position = -1;
			PropertyName = null;
		}

		internal int CalculateLength()
		{
			switch (Type)
			{
			case JsonContainerType.Object:
				return PropertyName.Length + 5;
			case JsonContainerType.Array:
			case JsonContainerType.Constructor:
				return MathUtils.IntLength((ulong)Position) + 2;
			default:
				throw new ArgumentOutOfRangeException("Type");
			}
		}

		internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer)
		{
			switch (Type)
			{
			case JsonContainerType.Object:
			{
				string propertyName = PropertyName;
				if (propertyName.IndexOfAny(SpecialCharacters) != -1)
				{
					sb.Append("['");
					if (writer == null)
					{
						writer = new StringWriter(sb);
					}
					JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer);
					sb.Append("']");
				}
				else
				{
					if (sb.Length > 0)
					{
						sb.Append('.');
					}
					sb.Append(propertyName);
				}
				break;
			}
			case JsonContainerType.Array:
			case JsonContainerType.Constructor:
				sb.Append('[');
				sb.Append(Position);
				sb.Append(']');
				break;
			}
		}

		internal static bool TypeHasIndex(JsonContainerType type)
		{
			if (type != JsonContainerType.Array)
			{
				return type == JsonContainerType.Constructor;
			}
			return true;
		}

		internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition)
		{
			int num = 0;
			if (positions != null)
			{
				for (int i = 0; i < positions.Count; i++)
				{
					num += positions[i].CalculateLength();
				}
			}
			if (currentPosition.HasValue)
			{
				num += currentPosition.GetValueOrDefault().CalculateLength();
			}
			StringBuilder stringBuilder = new StringBuilder(num);
			StringWriter writer = null;
			char[] buffer = null;
			if (positions != null)
			{
				foreach (JsonPosition position in positions)
				{
					position.WriteTo(stringBuilder, ref writer, ref buffer);
				}
			}
			currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer);
			return stringBuilder.ToString();
		}

		internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message)
		{
			if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal))
			{
				message = message.Trim();
				if (!StringUtils.EndsWith(message, '.'))
				{
					message += ".";
				}
				message += " ";
			}
			message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path);
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition);
			}
			message += ".";
			return message;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
	public sealed class JsonPropertyAttribute : Attribute
	{
		internal NullValueHandling? _nullValueHandling;

		internal DefaultValueHandling? _defaultValueHandling;

		internal ReferenceLoopHandling? _referenceLoopHandling;

		internal ObjectCreationHandling? _objectCreationHandling;

		internal TypeNameHandling? _typeNameHandling;

		internal bool? _isReference;

		internal int? _order;

		internal Required? _required;

		internal bool? _itemIsReference;

		internal ReferenceLoopHandling? _itemReferenceLoopHandling;

		internal TypeNameHandling? _itemTypeNameHandling;

		public Type? ItemConverterType { get; set; }

		public object[]? ItemConverterParameters { get; set; }

		public Type? NamingStrategyType { get; set; }

		public object[]? NamingStrategyParameters { get; set; }

		public NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling.GetValueOrDefault();
			}
			set
			{
				_nullValueHandling = value;
			}
		}

		public DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling.GetValueOrDefault();
			}
			set
			{
				_defaultValueHandling = value;
			}
		}

		public ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_referenceLoopHandling = value;
			}
		}

		public ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling.GetValueOrDefault();
			}
			set
			{
				_objectCreationHandling = value;
			}
		}

		public TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling.GetValueOrDefault();
			}
			set
			{
				_typeNameHandling = value;
			}
		}

		public bool IsReference
		{
			get
			{
				return _isReference == true;
			}
			set
			{
				_isReference = value;
			}
		}

		public int Order
		{
			get
			{
				return _order.GetValueOrDefault();
			}
			set
			{
				_order = value;
			}
		}

		public Required Required
		{
			get
			{
				return _required.GetValueOrDefault();
			}
			set
			{
				_required = value;
			}
		}

		public string? PropertyName { get; set; }

		public ReferenceLoopHandling ItemReferenceLoopHandling
		{
			get
			{
				return _itemReferenceLoopHandling.GetValueOrDefault();
			}
			set
			{
				_itemReferenceLoopHandling = value;
			}
		}

		public TypeNameHandling ItemTypeNameHandling
		{
			get
			{
				return _itemTypeNameHandling.GetValueOrDefault();
			}
			set
			{
				_itemTypeNameHandling = value;
			}
		}

		public bool ItemIsReference
		{
			get
			{
				return _itemIsReference == true;
			}
			set
			{
				_itemIsReference = value;
			}
		}

		public JsonPropertyAttribute()
		{
		}

		public JsonPropertyAttribute(string propertyName)
		{
			PropertyName = propertyName;
		}
	}
	public abstract class JsonReader : IDisposable
	{
		protected internal enum State
		{
			Start,
			Complete,
			Property,
			ObjectStart,
			Object,
			ArrayStart,
			Array,
			Closed,
			PostValue,
			ConstructorStart,
			Constructor,
			Error,
			Finished
		}

		private JsonToken _tokenType;

		private object? _value;

		internal char _quoteChar;

		internal State _currentState;

		private JsonPosition _currentPosition;

		private CultureInfo? _culture;

		private DateTimeZoneHandling _dateTimeZoneHandling;

		private int? _maxDepth;

		private bool _hasExceededMaxDepth;

		internal DateParseHandling _dateParseHandling;

		internal FloatParseHandling _floatParseHandling;

		private string? _dateFormatString;

		private List<JsonPosition>? _stack;

		protected State CurrentState => _currentState;

		public bool CloseInput { get; set; }

		public bool SupportMultipleContent { get; set; }

		public virtual char QuoteChar
		{
			get
			{
				return _quoteChar;
			}
			protected internal set
			{
				_quoteChar = value;
			}
		}

		public DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling;
			}
			set
			{
				if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_dateTimeZoneHandling = value;
			}
		}

		public DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling;
			}
			set
			{
				if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_dateParseHandling = value;
			}
		}

		public FloatParseHandling FloatParseHandling
		{
			get
			{
				return _floatParseHandling;
			}
			set
			{
				if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_floatParseHandling = value;
			}
		}

		public string? DateFormatString
		{
			get
			{
				return _dateFormatString;
			}
			set
			{
				_dateFormatString = value;
			}
		}

		public int? MaxDepth
		{
			get
			{
				return _maxDepth;
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
			}
		}

		public virtual JsonToken TokenType => _tokenType;

		public virtual object? Value => _value;

		public virtual Type? ValueType => _value?.GetType();

		public virtual int Depth
		{
			get
			{
				int num = _stack?.Count ?? 0;
				if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
				{
					return num;
				}
				return num + 1;
			}
		}

		public virtual string Path
		{
			get
			{
				if (_currentPosition.Type == JsonContainerType.None)
				{
					return string.Empty;
				}
				JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : ((JsonPosition?)null));
				return JsonPosition.BuildPath(_stack, currentPosition);
			}
		}

		public CultureInfo Culture
		{
			get
			{
				return _culture ?? CultureInfo.InvariantCulture;
			}
			set
			{
				_culture = value;
			}
		}

		internal JsonPosition GetPosition(int depth)
		{
			if (_stack != null && depth < _stack.Count)
			{
				return _stack[depth];
			}
			return _currentPosition;
		}

		protected JsonReader()
		{
			_currentState = State.Start;
			_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
			_dateParseHandling = DateParseHandling.DateTime;
			_floatParseHandling = FloatParseHandling.Double;
			_maxDepth = 64;
			CloseInput = true;
		}

		private void Push(JsonContainerType value)
		{
			UpdateScopeWithFinishedValue();
			if (_currentPosition.Type == JsonContainerType.None)
			{
				_currentPosition = new JsonPosition(value);
				return;
			}
			if (_stack == null)
			{
				_stack = new List<JsonPosition>();
			}
			_stack.Add(_currentPosition);
			_currentPosition = new JsonPosition(value);
			if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth)
			{
				return;
			}
			_hasExceededMaxDepth = true;
			throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
		}

		private JsonContainerType Pop()
		{
			JsonPosition currentPosition;
			if (_stack != null && _stack.Count > 0)
			{
				currentPosition = _currentPosition;
				_currentPosition = _stack[_stack.Count - 1];
				_stack.RemoveAt(_stack.Count - 1);
			}
			else
			{
				currentPosition = _currentPosition;
				_currentPosition = default(JsonPosition);
			}
			if (_maxDepth.HasValue && Depth <= _maxDepth)
			{
				_hasExceededMaxDepth = false;
			}
			return currentPosition.Type;
		}

		private JsonContainerType Peek()
		{
			return _currentPosition.Type;
		}

		public abstract bool Read();

		public virtual int? ReadAsInt32()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is int)
				{
					return (int)value;
				}
				int num;
				if (value is BigInteger bigInteger)
				{
					num = (int)bigInteger;
				}
				else
				{
					try
					{
						num = Convert.ToInt32(value, CultureInfo.InvariantCulture);
					}
					catch (Exception ex)
					{
						throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
					}
				}
				SetToken(JsonToken.Integer, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
			{
				string s = (string)Value;
				return ReadInt32String(s);
			}
			default:
				throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal int? ReadInt32String(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (int.TryParse(s, NumberStyles.Integer, Culture, out var result))
			{
				SetToken(JsonToken.Integer, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual string? ReadAsString()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.String:
				return (string)Value;
			default:
				if (JsonTokenUtils.IsPrimitiveToken(contentToken))
				{
					object value = Value;
					if (value != null)
					{
						string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture));
						SetToken(JsonToken.String, text, updateIndex: false);
						return text;
					}
				}
				throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		public virtual byte[]? ReadAsBytes()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.StartObject:
			{
				ReadIntoWrappedTypeObject();
				byte[] array2 = ReadAsBytes();
				ReaderReadAndAssert();
				if (TokenType != JsonToken.EndObject)
				{
					throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
				}
				SetToken(JsonToken.Bytes, array2, updateIndex: false);
				return array2;
			}
			case JsonToken.String:
			{
				string text = (string)Value;
				Guid g;
				byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray()));
				SetToken(JsonToken.Bytes, array3, updateIndex: false);
				return array3;
			}
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Bytes:
				if (Value is Guid guid)
				{
					byte[] array = guid.ToByteArray();
					SetToken(JsonToken.Bytes, array, updateIndex: false);
					return array;
				}
				return (byte[])Value;
			case JsonToken.StartArray:
				return ReadArrayIntoByteArray();
			default:
				throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal byte[] ReadArrayIntoByteArray()
		{
			List<byte> list = new List<byte>();
			do
			{
				if (!Read())
				{
					SetToken(JsonToken.None);
				}
			}
			while (!ReadArrayElementIntoByteArrayReportDone(list));
			byte[] array = list.ToArray();
			SetToken(JsonToken.Bytes, array, updateIndex: false);
			return array;
		}

		private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer)
		{
			switch (TokenType)
			{
			case JsonToken.None:
				throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
			case JsonToken.Integer:
				buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
				return false;
			case JsonToken.EndArray:
				return true;
			case JsonToken.Comment:
				return false;
			default:
				throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
			}
		}

		public virtual double? ReadAsDouble()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is double)
				{
					return (double)value;
				}
				double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger));
				SetToken(JsonToken.Float, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
				return ReadDoubleString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal double? ReadDoubleString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result))
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual bool? ReadAsBoolean()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L));
				SetToken(JsonToken.Boolean, flag, updateIndex: false);
				return flag;
			}
			case JsonToken.String:
				return ReadBooleanString((string)Value);
			case JsonToken.Boolean:
				return (bool)Value;
			default:
				throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal bool? ReadBooleanString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (bool.TryParse(s, out var result))
			{
				SetToken(JsonToken.Boolean, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual decimal? ReadAsDecimal()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Integer:
			case JsonToken.Float:
			{
				object value = Value;
				if (value is decimal)
				{
					return (decimal)value;
				}
				decimal num;
				if (value is BigInteger bigInteger)
				{
					num = (decimal)bigInteger;
				}
				else
				{
					try
					{
						num = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
					}
					catch (Exception ex)
					{
						throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
					}
				}
				SetToken(JsonToken.Float, num, updateIndex: false);
				return num;
			}
			case JsonToken.String:
				return ReadDecimalString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal decimal? ReadDecimalString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result))
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success)
			{
				SetToken(JsonToken.Float, result, updateIndex: false);
				return result;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual DateTime? ReadAsDateTime()
		{
			switch (GetContentToken())
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Date:
				if (Value is DateTimeOffset dateTimeOffset)
				{
					SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false);
				}
				return (DateTime)Value;
			case JsonToken.String:
				return ReadDateTimeString((string)Value);
			default:
				throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
			}
		}

		internal DateTime? ReadDateTimeString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt))
			{
				dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
			{
				dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		public virtual DateTimeOffset? ReadAsDateTimeOffset()
		{
			JsonToken contentToken = GetContentToken();
			switch (contentToken)
			{
			case JsonToken.None:
			case JsonToken.Null:
			case JsonToken.EndArray:
				return null;
			case JsonToken.Date:
				if (Value is DateTime dateTime)
				{
					SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false);
				}
				return (DateTimeOffset)Value;
			case JsonToken.String:
			{
				string s = (string)Value;
				return ReadDateTimeOffsetString(s);
			}
			default:
				throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
			}
		}

		internal DateTimeOffset? ReadDateTimeOffsetString(string? s)
		{
			if (StringUtils.IsNullOrEmpty(s))
			{
				SetToken(JsonToken.Null, null, updateIndex: false);
				return null;
			}
			if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt))
			{
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
			{
				SetToken(JsonToken.Date, dt, updateIndex: false);
				return dt;
			}
			SetToken(JsonToken.String, s, updateIndex: false);
			throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
		}

		internal void ReaderReadAndAssert()
		{
			if (!Read())
			{
				throw CreateUnexpectedEndException();
			}
		}

		internal JsonReaderException CreateUnexpectedEndException()
		{
			return JsonReaderException.Create(this, "Unexpected end when reading JSON.");
		}

		internal void ReadIntoWrappedTypeObject()
		{
			ReaderReadAndAssert();
			if (Value != null && Value.ToString() == "$type")
			{
				ReaderReadAndAssert();
				if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal))
				{
					ReaderReadAndAssert();
					if (Value.ToString() == "$value")
					{
						return;
					}
				}
			}
			throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
		}

		public void Skip()
		{
			if (TokenType == JsonToken.PropertyName)
			{
				Read();
			}
			if (JsonTokenUtils.IsStartToken(TokenType))
			{
				int depth = Depth;
				while (Read() && depth < Depth)
				{
				}
			}
		}

		protected void SetToken(JsonToken newToken)
		{
			SetToken(newToken, null, updateIndex: true);
		}

		protected void SetToken(JsonToken newToken, object? value)
		{
			SetToken(newToken, value, updateIndex: true);
		}

		protected void SetToken(JsonToken newToken, object? value, bool updateIndex)
		{
			_tokenType = newToken;
			_value = value;
			switch (newToken)
			{
			case JsonToken.StartObject:
				_currentState = State.ObjectStart;
				Push(JsonContainerType.Object);
				break;
			case JsonToken.StartArray:
				_currentState = State.ArrayStart;
				Push(JsonContainerType.Array);
				break;
			case JsonToken.StartConstructor:
				_currentState = State.ConstructorStart;
				Push(JsonContainerType.Constructor);
				break;
			case JsonToken.EndObject:
				ValidateEnd(JsonToken.EndObject);
				break;
			case JsonToken.EndArray:
				ValidateEnd(JsonToken.EndArray);
				break;
			case JsonToken.EndConstructor:
				ValidateEnd(JsonToken.EndConstructor);
				break;
			case JsonToken.PropertyName:
				_currentState = State.Property;
				_currentPosition.PropertyName = (string)value;
				break;
			case JsonToken.Raw:
			case JsonToken.Integer:
			case JsonToken.Float:
			case JsonToken.String:
			case JsonToken.Boolean:
			case JsonToken.Null:
			case JsonToken.Undefined:
			case JsonToken.Date:
			case JsonToken.Bytes:
				SetPostValueState(updateIndex);
				break;
			case JsonToken.Comment:
				break;
			}
		}

		internal void SetPostValueState(bool updateIndex)
		{
			if (Peek() != JsonContainerType.None || SupportMultipleContent)
			{
				_currentState = State.PostValue;
			}
			else
			{
				SetFinished();
			}
			if (updateIndex)
			{
				UpdateScopeWithFinishedValue();
			}
		}

		private void UpdateScopeWithFinishedValue()
		{
			if (_currentPosition.HasIndex)
			{
				_currentPosition.Position++;
			}
		}

		private void ValidateEnd(JsonToken endToken)
		{
			JsonContainerType jsonContainerType = Pop();
			if (GetTypeForCloseToken(endToken) != jsonContainerType)
			{
				throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType));
			}
			if (Peek() != JsonContainerType.None || SupportMultipleContent)
			{
				_currentState = State.PostValue;
			}
			else
			{
				SetFinished();
			}
		}

		protected void SetStateBasedOnCurrent()
		{
			JsonContainerType jsonContainerType = Peek();
			switch (jsonContainerType)
			{
			case JsonContainerType.Object:
				_currentState = State.Object;
				break;
			case JsonContainerType.Array:
				_currentState = State.Array;
				break;
			case JsonContainerType.Constructor:
				_currentState = State.Constructor;
				break;
			case JsonContainerType.None:
				SetFinished();
				break;
			default:
				throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType));
			}
		}

		private void SetFinished()
		{
			_currentState = ((!SupportMultipleContent) ? State.Finished : State.Start);
		}

		private JsonContainerType GetTypeForCloseToken(JsonToken token)
		{
			return token switch
			{
				JsonToken.EndObject => JsonContainerType.Object, 
				JsonToken.EndArray => JsonContainerType.Array, 
				JsonToken.EndConstructor => JsonContainerType.Constructor, 
				_ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), 
			};
		}

		void IDisposable.Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (_currentState != State.Closed && disposing)
			{
				Close();
			}
		}

		public virtual void Close()
		{
			_currentState = State.Closed;
			_tokenType = JsonToken.None;
			_value = null;
		}

		internal void ReadAndAssert()
		{
			if (!Read())
			{
				throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
			}
		}

		internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter)
		{
			if (!ReadForType(contract, hasConverter))
			{
				throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
			}
		}

		internal bool ReadForType(JsonContract? contract, bool hasConverter)
		{
			if (hasConverter)
			{
				return Read();
			}
			switch (contract?.InternalReadType ?? ReadType.Read)
			{
			case ReadType.Read:
				return ReadAndMoveToContent();
			case ReadType.ReadAsInt32:
				ReadAsInt32();
				break;
			case ReadType.ReadAsInt64:
			{
				bool result = ReadAndMoveToContent();
				if (TokenType == JsonToken.Undefined)
				{
					throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long)));
				}
				return result;
			}
			case ReadType.ReadAsDecimal:
				ReadAsDecimal();
				break;
			case ReadType.ReadAsDouble:
				ReadAsDouble();
				break;
			case ReadType.ReadAsBytes:
				ReadAsBytes();
				break;
			case ReadType.ReadAsBoolean:
				ReadAsBoolean();
				break;
			case ReadType.ReadAsString:
				ReadAsString();
				break;
			case ReadType.ReadAsDateTime:
				ReadAsDateTime();
				break;
			case ReadType.ReadAsDateTimeOffset:
				ReadAsDateTimeOffset();
				break;
			default:
				throw new ArgumentOutOfRangeException();
			}
			return TokenType != JsonToken.None;
		}

		internal bool ReadAndMoveToContent()
		{
			if (Read())
			{
				return MoveToContent();
			}
			return false;
		}

		internal bool MoveToContent()
		{
			JsonToken tokenType = TokenType;
			while (tokenType == JsonToken.None || tokenType == JsonToken.Comment)
			{
				if (!Read())
				{
					return false;
				}
				tokenType = TokenType;
			}
			return true;
		}

		private JsonToken GetContentToken()
		{
			JsonToken tokenType;
			do
			{
				if (!Read())
				{
					SetToken(JsonToken.None);
					return JsonToken.None;
				}
				tokenType = TokenType;
			}
			while (tokenType == JsonToken.Comment);
			return tokenType;
		}
	}
	[Serializable]
	public class JsonReaderException : JsonException
	{
		public int LineNumber { get; }

		public int LinePosition { get; }

		public string? Path { get; }

		public JsonReaderException()
		{
		}

		public JsonReaderException(string message)
			: base(message)
		{
		}

		public JsonReaderException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public JsonReaderException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
			: base(message, innerException)
		{
			Path = path;
			LineNumber = lineNumber;
			LinePosition = linePosition;
		}

		internal static JsonReaderException Create(JsonReader reader, string message)
		{
			return Create(reader, message, null);
		}

		internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex)
		{
			return Create(reader as IJsonLineInfo, reader.Path, message, ex);
		}

		internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			int lineNumber;
			int linePosition;
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				lineNumber = lineInfo.LineNumber;
				linePosition = lineInfo.LinePosition;
			}
			else
			{
				lineNumber = 0;
				linePosition = 0;
			}
			return new JsonReaderException(message, path, lineNumber, linePosition, ex);
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
	public sealed class JsonRequiredAttribute : Attribute
	{
	}
	[Serializable]
	public class JsonSerializationException : JsonException
	{
		public int LineNumber { get; }

		public int LinePosition { get; }

		public string? Path { get; }

		public JsonSerializationException()
		{
		}

		public JsonSerializationException(string message)
			: base(message)
		{
		}

		public JsonSerializationException(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public JsonSerializationException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
			: base(message, innerException)
		{
			Path = path;
			LineNumber = lineNumber;
			LinePosition = linePosition;
		}

		internal static JsonSerializationException Create(JsonReader reader, string message)
		{
			return Create(reader, message, null);
		}

		internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex)
		{
			return Create(reader as IJsonLineInfo, reader.Path, message, ex);
		}

		internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
		{
			message = JsonPosition.FormatMessage(lineInfo, path, message);
			int lineNumber;
			int linePosition;
			if (lineInfo != null && lineInfo.HasLineInfo())
			{
				lineNumber = lineInfo.LineNumber;
				linePosition = lineInfo.LinePosition;
			}
			else
			{
				lineNumber = 0;
				linePosition = 0;
			}
			return new JsonSerializationException(message, path, lineNumber, linePosition, ex);
		}
	}
	[RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")]
	[RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")]
	public class JsonSerializer
	{
		internal TypeNameHandling _typeNameHandling;

		internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling;

		internal PreserveReferencesHandling _preserveReferencesHandling;

		internal ReferenceLoopHandling _referenceLoopHandling;

		internal MissingMemberHandling _missingMemberHandling;

		internal ObjectCreationHandling _objectCreationHandling;

		internal NullValueHandling _nullValueHandling;

		internal DefaultValueHandling _defaultValueHandling;

		internal ConstructorHandling _constructorHandling;

		internal MetadataPropertyHandling _metadataPropertyHandling;

		internal JsonConverterCollection? _converters;

		internal IContractResolver _contractResolver;

		internal ITraceWriter? _traceWriter;

		internal IEqualityComparer? _equalityComparer;

		internal ISerializationBinder _serializationBinder;

		internal StreamingContext _context;

		private IReferenceResolver? _referenceResolver;

		private Formatting? _formatting;

		private DateFormatHandling? _dateFormatHandling;

		private DateTimeZoneHandling? _dateTimeZoneHandling;

		private DateParseHandling? _dateParseHandling;

		private FloatFormatHandling? _floatFormatHandling;

		private FloatParseHandling? _floatParseHandling;

		private StringEscapeHandling? _stringEscapeHandling;

		private CultureInfo _culture;

		private int? _maxDepth;

		private bool _maxDepthSet;

		private bool? _checkAdditionalContent;

		private string? _dateFormatString;

		private bool _dateFormatStringSet;

		public virtual IReferenceResolver? ReferenceResolver
		{
			get
			{
				return GetReferenceResolver();
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Reference resolver cannot be null.");
				}
				_referenceResolver = value;
			}
		}

		[Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
		public virtual SerializationBinder Binder
		{
			get
			{
				if (_serializationBinder is SerializationBinder result)
				{
					return result;
				}
				if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter)
				{
					return serializationBinderAdapter.SerializationBinder;
				}
				throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Serialization binder cannot be null.");
				}
				_serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value);
			}
		}

		public virtual ISerializationBinder SerializationBinder
		{
			get
			{
				return _serializationBinder;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("value", "Serialization binder cannot be null.");
				}
				_serializationBinder = value;
			}
		}

		public virtual ITraceWriter? TraceWriter
		{
			get
			{
				return _traceWriter;
			}
			set
			{
				_traceWriter = value;
			}
		}

		public virtual IEqualityComparer? EqualityComparer
		{
			get
			{
				return _equalityComparer;
			}
			set
			{
				_equalityComparer = value;
			}
		}

		public virtual TypeNameHandling TypeNameHandling
		{
			get
			{
				return _typeNameHandling;
			}
			set
			{
				if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameHandling = value;
			}
		}

		[Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")]
		public virtual FormatterAssemblyStyle TypeNameAssemblyFormat
		{
			get
			{
				return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling;
			}
			set
			{
				if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value;
			}
		}

		public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling
		{
			get
			{
				return _typeNameAssemblyFormatHandling;
			}
			set
			{
				if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_typeNameAssemblyFormatHandling = value;
			}
		}

		public virtual PreserveReferencesHandling PreserveReferencesHandling
		{
			get
			{
				return _preserveReferencesHandling;
			}
			set
			{
				if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_preserveReferencesHandling = value;
			}
		}

		public virtual ReferenceLoopHandling ReferenceLoopHandling
		{
			get
			{
				return _referenceLoopHandling;
			}
			set
			{
				if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_referenceLoopHandling = value;
			}
		}

		public virtual MissingMemberHandling MissingMemberHandling
		{
			get
			{
				return _missingMemberHandling;
			}
			set
			{
				if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_missingMemberHandling = value;
			}
		}

		public virtual NullValueHandling NullValueHandling
		{
			get
			{
				return _nullValueHandling;
			}
			set
			{
				if (value < NullValueHandling.Include || value > NullValueHandling.Ignore)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_nullValueHandling = value;
			}
		}

		public virtual DefaultValueHandling DefaultValueHandling
		{
			get
			{
				return _defaultValueHandling;
			}
			set
			{
				if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_defaultValueHandling = value;
			}
		}

		public virtual ObjectCreationHandling ObjectCreationHandling
		{
			get
			{
				return _objectCreationHandling;
			}
			set
			{
				if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_objectCreationHandling = value;
			}
		}

		public virtual ConstructorHandling ConstructorHandling
		{
			get
			{
				return _constructorHandling;
			}
			set
			{
				if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_constructorHandling = value;
			}
		}

		public virtual MetadataPropertyHandling MetadataPropertyHandling
		{
			get
			{
				return _metadataPropertyHandling;
			}
			set
			{
				if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore)
				{
					throw new ArgumentOutOfRangeException("value");
				}
				_metadataPropertyHandling = value;
			}
		}

		public virtual JsonConverterCollection Converters
		{
			get
			{
				if (_converters == null)
				{
					_converters = new JsonConverterCollection();
				}
				return _converters;
			}
		}

		public virtual IContractResolver ContractResolver
		{
			get
			{
				return _contractResolver;
			}
			set
			{
				_contractResolver = value ?? DefaultContractResolver.Instance;
			}
		}

		public virtual StreamingContext Context
		{
			get
			{
				return _context;
			}
			set
			{
				_context = value;
			}
		}

		public virtual Formatting Formatting
		{
			get
			{
				return _formatting.GetValueOrDefault();
			}
			set
			{
				_formatting = value;
			}
		}

		public virtual DateFormatHandling DateFormatHandling
		{
			get
			{
				return _dateFormatHandling.GetValueOrDefault();
			}
			set
			{
				_dateFormatHandling = value;
			}
		}

		public virtual DateTimeZoneHandling DateTimeZoneHandling
		{
			get
			{
				return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind;
			}
			set
			{
				_dateTimeZoneHandling = value;
			}
		}

		public virtual DateParseHandling DateParseHandling
		{
			get
			{
				return _dateParseHandling ?? DateParseHandling.DateTime;
			}
			set
			{
				_dateParseHandling = value;
			}
		}

		public virtual FloatParseHandling FloatParseHandling
		{
			get
			{
				return _floatParseHandling.GetValueOrDefault();
			}
			set
			{
				_floatParseHandling = value;
			}
		}

		public virtual FloatFormatHandling FloatFormatHandling
		{
			get
			{
				return _floatFormatHandling.GetValueOrDefault();
			}
			set
			{
				_floatFormatHandling = value;
			}
		}

		public virtual StringEscapeHandling StringEscapeHandling
		{
			get
			{
				return _stringEscapeHandling.GetValueOrDefault();
			}
			set
			{
				_stringEscapeHandling = value;
			}
		}

		public virtual string DateFormatString
		{
			get
			{
				return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
			}
			set
			{
				_dateFormatString = value;
				_dateFormatStringSet = true;
			}
		}

		public virtual CultureInfo Culture
		{
			get
			{
				return _culture ?? JsonSerializerSettings.DefaultCulture;
			}
			set
			{
				_culture = value;
			}
		}

		public virtual int? MaxDepth
		{
			get
			{
				return _maxDepth;
			}
			set
			{
				if (value <= 0)
				{
					throw new ArgumentException("Value must be positive.", "value");
				}
				_maxDepth = value;
				_maxDepthSet = true;
			}
		}

		public virtual bool CheckAdditionalContent
		{
			get
			{
				return _checkAdditionalContent == true;
			}
			set
			{
				_checkAdditionalContent = value;
			}
		}

		public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error;

		internal bool IsCheckAdditionalContentSet()
		{
			return _checkAdditionalContent.HasValue;
		}

		public JsonSerializer()
		{
			_referenceLoopHandling = ReferenceLoopHandling.Error;
			_missingMemberHandling = MissingMemberHandling.Ignore;
			_nullValueHandling = NullValueHandling.Include;
			_defaultValueHandling = DefaultValueHandling.Include;
			_objectCreationHandling = ObjectCreationHandling.Auto;
			_preserveReferencesHandling = PreserveReferencesHandling.None;
			_constructorHandling = ConstructorHandling.Default;
			_typeNameHandling = TypeNameHandling.None;
			_metadataPropertyHandling = MetadataPropertyHandling.Default;
			_context = JsonSerializerSettings.DefaultContext;
			_serializationBinder = DefaultSerializationBinder.Instance;
			_culture = JsonSerializerSettings.DefaultCulture;
			_contractResolver = DefaultContractResolver.Instance;
		}

		public static JsonSerializer Create()
		{
			return new JsonSerializer();
		}

		public static JsonSerializer Create(JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = Create();
			if (settings != null)
			{
				ApplySerializerSettings(jsonSerializer, settings);
			}
			return jsonSerializer;
		}

		public static JsonSerializer CreateDefault()
		{
			return Create(JsonConvert.DefaultSettings?.Invoke());
		}

		public static JsonSerializer CreateDefault(JsonSerializerSettings? settings)
		{
			JsonSerializer jsonSerializer = CreateDefault();
			if (settings != null)
			{
				ApplySerializerSettings(jsonSerializer, settings);
			}
			return jsonSerializer;
		}

		private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
		{
			if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
			{
				for (int i = 0; i < settings.Converters.Count; i++)
				{
					serializer.Converters.Insert(i, settings.Converters[i]);
				}
			}
			if (settings._typeNameHandling.HasValue)
			{
				serializer.TypeNameHandling = settings.TypeNameHandling;
			}
			if (settings._metadataPropertyHandling.HasValue)
			{
				serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling;
			}
			if (settings._typeNameAssemblyFormatHandling.HasValue)
			{
				serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling;
			}
			if (settings._preserveReferencesHandling.HasValue)
			{
				serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling;
			}
			if (settings._referenceLoopHandling.HasValue)
			{
				serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling;
			}
			if (settings._missingMemberHandling.HasValue)
			{
				serializer.MissingMemberHandling = settings.MissingMemberHandling;
			}
			if (settings._objectCreationHandling.HasValue)
			{
				serializer.ObjectCreationHandling = settings.ObjectCreationHandling;
			}
			if (settings._nullValueHandling.HasValue)
			{
				serializer.NullValueHandling = settings.NullValueHandling;
			}
			if (settings._defaultValueHandling.HasValue)
			{
				serializer.DefaultValueHandling = settings.DefaultValueHandling;
			}
			if (settings._constructorHandling.HasValue)
			{
				serializer.ConstructorHandling = settings.ConstructorHandling;
			}
			if (settings._context.HasValue)
			{
				serializer.Context = settings.Context;
			}
			if (settings._checkAdditionalContent.HasValue)
			{
				serializer._checkAdditionalContent = settings._checkAdditionalContent;
			}
			if (settings.Error != null)
			{
				serializer.Error += settings.Error;
			}
			if (settings.ContractResolver != null)
			{
				serializer.ContractResolver = settings.ContractResolver;
			}
			if (settings.ReferenceResolverProvider != null)
			{
				serializer.ReferenceResolver = settings.ReferenceResolverProvider();
			}
			if (settings.TraceWriter != null)
			{
				serializer.TraceWriter = settings.TraceWriter;
			}
			if (settings.EqualityComparer != null)
			{
				serializer.EqualityComparer = settings.EqualityComparer;
			}
			if (settings.SerializationBinder != null)
			{
				serializer.SerializationBinder = settings.SerializationBinder;
			}
			if (settings._formatting.HasValue)
			{
				serializer._formatting = settings._formatting;
			}
			if (settings._dateFormatHandling.HasValue)
			{
				serializer._dateFormatHandling = settings._dateFormatHandling;
			}
			if (settings._dateTimeZoneHandling.HasValue)
			{
				serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
			}
			if (settings._dateParseHandling.HasValue)
			{
				serializer._dateParseHandling = settings._dateParseHandling;
			}
			if (settings._dateFormatStringSet)
			{
				serializer._dateFormatString = settings._dateFormatString;
				serializer._dateFormatStringSet = settings._dateFormatStringSet;
			}
			if (settings._floatFormatHandling.HasValue)
			{
				serializer._floatFormatHandling = settings._floatFormatHandling;
			}
			if (settings._floatParseHandling.HasValue)
			{
				serializer._floatParseHandling = settings._floatParseHandling;
			}
			if (settings._stringEscapeHandling.HasValue)
			{
				serializer._stringEscapeHandling = settings._stringEscapeHandling;
			}
			if (settings._culture != null)
			{
				serializer._culture = settings._culture;
			}
			if (settings._maxDepthSet)
			{
				serializer._maxDepth = settings._maxDepth;
				serializer._maxDepthSet = settings._maxDepthSet;
			}
		}

		[DebuggerStepThrough]
		public void Populate(TextReader reader, object target)
		{
			Populate(new JsonTextReader(reader), target);
		}

		[DebuggerStepThrough]
		public void Populate(JsonReader reader, object target)
		{
			PopulateInternal(reader, target);
		}

		internal virtual void PopulateInternal(JsonReader reader, object target)
		{
			ValidationUtils.ArgumentNotNull(reader, "reader");
			ValidationUtils.ArgumentNotNull(target, "target");
			SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
			TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
			new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target);
			if (traceJsonReader != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
			}
			ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
		}

		[DebuggerStepThrough]
		public object? Deserialize(JsonReader reader)
		{
			return Deserialize(reader, null);
		}

		[DebuggerStepThrough]
		public object? Deserialize(TextReader reader, Type objectType)
		{
			return Deserialize(new JsonTextReader(reader), objectType);
		}

		[DebuggerStepThrough]
		public T? Deserialize<T>(JsonReader reader)
		{
			return (T)Deserialize(reader, typeof(T));
		}

		[DebuggerStepThrough]
		public object? Deserialize(JsonReader reader, Type? objectType)
		{
			return DeserializeInternal(reader, objectType);
		}

		internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType)
		{
			ValidationUtils.ArgumentNotNull(reader, "reader");
			SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
			TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
			object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
			if (traceJsonReader != null)
			{
				TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
			}
			ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
			return result;
		}

		internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString)
		{
			if (_culture != null && !_culture.Equals(reader.Culture))
			{
				previousCulture = reader.Culture;
				reader.Culture = _culture;
			}
			else
			{
				previousCulture = null;
			}
			if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
			{
				previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
				reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
			}
			else
			{
				previousDateTimeZoneHandling = null;
			}
			if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling)
			{
				previousDateParseHandling = reader.DateParseHandling;
				reader.DateParseHandling = _dateParseHandling.GetValueOrDefault();
			}
			else
			{
				previousDateParseHandling = null;
			}
			if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling)
			{
				previousFloatParseHandling = reader.FloatParseHandling;
				reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault();
			}
			else
			{
				previousFloatParseHandling = null;
			}
			if (_maxDepthSet && reader.MaxDepth != _maxDepth)
			{
				previousMaxDepth = reader.MaxDepth;
				reader.MaxDepth = _maxDepth;
			}
			else
			{
				previousMaxDepth = null;
			}
			if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
			{
				previousDateFormatString = reader.DateFormatString;
				reader.DateFormatString = _dateFormatString;
			}
			else
			{
				previousDateFormatString = null;
			}
			if (reader is JsonTextReader { PropertyNameTable: null } jsonTextReader && _contractResolver is DefaultContractResolver defaultContractResolver)
			{
				jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable();
			}
		}

		private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString)
		{
			if (previousCulture != null)
			{
				reader.Culture = previousCulture;
			}
			if (previousDateTimeZoneHandling.HasValue)
			{
				reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault();
			}
			if (previousDateParseHandling.HasValue)
			{
				reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault();
			}
			if (previousFloatParseHandling.HasValue)
			{
				reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault();
			}
			if (_maxDepthSet)
			{
				reader.MaxDepth = previousMaxDepth;
			}
			if (_dateFormatStringSet)
			{
				reader.DateFormatString = previousDateFormatString;
			}
			if (reader is JsonTextReader { PropertyNameTable: not null } jsonTextReader && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable())
			{
				jsonTextReader.PropertyNameTable = null;
			}
		}

		public void Serialize(TextWriter textWriter, object? value)
		{
			Serialize(new JsonTextWriter(textWriter), value);
		}

		public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType)
		{
			SerializeInternal(jsonWriter, value, objectType);
		}

		public void Serialize(TextWriter textWriter, object? value, Type objectType)
		{
			Serialize(new JsonTextWriter(textWriter), value, objectType);
		}

		public void Serialize(JsonWriter jsonWriter, object? value)
		{
			SerializeInternal(jsonWriter, value, null);
		}

		private TraceJsonReader CreateTraceJsonReader(JsonReader reader)
		{
			TraceJsonReader traceJsonReader = new TraceJsonReader(reader);
			if (reader.TokenType != JsonToken.None)
			{
				traceJsonReader.WriteCurrentToken();
			}
			return traceJsonReader;
		}

		internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType)
		{
			ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
			Formatting? formatting = null;
			if (_formatting.HasValue && jsonWriter.Formatting != _formatting)
			{
				formatting = jsonWriter.Formatting;
				jsonWriter.Formatting = _formatting.GetValueOrDefault();
			}
			DateFormatHandling? dateFormatHandling = null;
			if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling)
			{
				dateFormatHandling = jsonWriter.DateFormatHandling;
				jsonWriter.DateFormatHandling = _date

BepInEx/plugins/PharloomCore.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Text;
using Microsoft.CodeAnalysis;
using PharloomCore.Data;
using PharloomCore.Logic;
using PharloomCore.Model;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("PharloomCore")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c907a5441a34f4759975824f4eedc9f306ab5a89")]
[assembly: AssemblyProduct("PharloomCore")]
[assembly: AssemblyTitle("PharloomCore")]
[assembly: AssemblyVersion("1.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;
		}
	}
}
namespace PharloomCore
{
	public class PharloomCore
	{
		private readonly string[] _nativeConnLines;

		private readonly RoomGraph _roomGraphTemplate;

		private readonly Func<RoomGraph, PlacementSimulator> _placementFactory;

		private RoomGraph _roomGraph;

		public Region[] Regions { get; }

		public PlacementSimulator Placement { get; private set; }

		public DeadSeedDetector Detector { get; private set; }

		public SceneGraphBuilder SceneGraph { get; }

		public PrefixResolver Resolver { get; }

		public RoomGraph RoomGraph => _roomGraph;

		public RoomGapSet RoomGaps { get; private set; }

		public bool RoomPrecision => _roomGraph != null;

		public IReadOnlyDictionary<string, string> PointScenes { get; }

		public PharloomCore(string sceneConnectionPath, string checkpointsPath = null, string pointConditionsPath = null, bool roomPrecision = true)
		{
			PharloomCore pharloomCore = this;
			_nativeConnLines = File.ReadAllLines(sceneConnectionPath);
			Regions = RegionsData.All;
			SceneGraph = new SceneGraphBuilder(Regions);
			SceneGraph.Build(_nativeConnLines);
			Resolver = new PrefixResolver(Regions);
			_roomGraphTemplate = RoomGraphBuilder.Build(_nativeConnLines, Resolver, Regions);
			Dictionary<string, Gate> conditions = PointConditionLoader.LoadFile(pointConditionsPath);
			PointScenes = PointConditionLoader.LoadSceneMapFile(pointConditionsPath);
			string path = checkpointsPath;
			_placementFactory = (RoomGraph rg) => new PlacementSimulator(pharloomCore.Regions, path, 0, conditions, rg);
			_roomGraph = (roomPrecision ? _roomGraphTemplate : null);
			Attach();
		}

		public PharloomCore(bool roomPrecision = true)
		{
			PharloomCore pharloomCore = this;
			_nativeConnLines = ReadEmbeddedLines("PharloomCore.Data.场景连接.txt").ToArray();
			Regions = RegionsData.All;
			SceneGraph = new SceneGraphBuilder(Regions);
			SceneGraph.Build(_nativeConnLines);
			Resolver = new PrefixResolver(Regions);
			_roomGraphTemplate = RoomGraphBuilder.Build(_nativeConnLines, Resolver, Regions);
			Dictionary<string, Gate> conditions = PointConditionLoader.LoadLines(ReadEmbeddedLines("PharloomCore.Data.point_conditions.json"));
			PointScenes = PointConditionLoader.LoadSceneMapLines(ReadEmbeddedLines("PharloomCore.Data.point_conditions.json"));
			IEnumerable<string> lines = ReadEmbeddedLines("PharloomCore.Data.check_points.txt");
			_placementFactory = (RoomGraph rg) => new PlacementSimulator(pharloomCore.Regions, lines, 0, conditions, rg);
			_roomGraph = (roomPrecision ? _roomGraphTemplate : null);
			Attach();
		}

		private void Attach()
		{
			Placement = _placementFactory(_roomGraph);
			Detector = new DeadSeedDetector(Regions, _roomGraph);
			RoomGaps = ((_roomGraph != null) ? RoomGapSet.Compute(_roomGraph, Regions, Placement.BuildAllSlots()) : null);
			if (RoomGaps != null)
			{
				RoomGapReport.WarnOnce(RoomGaps);
			}
		}

		public void SetRoomPrecision(bool enabled)
		{
			RoomGraph roomGraph = (enabled ? _roomGraphTemplate : null);
			if (roomGraph != _roomGraph)
			{
				_roomGraph = roomGraph;
				Attach();
			}
		}

		private static IEnumerable<string> ReadEmbeddedLines(string resourceName)
		{
			using Stream stream = typeof(PharloomCore).Assembly.GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				throw new InvalidOperationException("缺少嵌入资源: " + resourceName);
			}
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd().Split(new string[2] { "\r\n", "\n" }, StringSplitOptions.None);
		}

		public Gate FindPointGate(string key)
		{
			return Placement.FindPointGate(key);
		}

		public SeedVerdict TryGenerate(Random rng, int maxTries = 1000, bool fullRandomMode = false)
		{
			List<ItemSlot> slots = Placement.BuildAllSlots();
			List<Item> pool = Placement.BuildItemPool(fullRandomMode);
			for (int i = 0; i < maxTries; i++)
			{
				if (Placement.TryPlaceActive(rng, slots, pool, out var assignment, fullRandomMode))
				{
					SeedVerdict seedVerdict = Detector.Evaluate(assignment, fullRandomMode);
					if (!seedVerdict.IsDead)
					{
						return seedVerdict;
					}
				}
			}
			return new SeedVerdict
			{
				IsDead = true,
				Reason = "重试 " + maxTries + " 次仍未找到活种子"
			};
		}

		public bool IsSeedLive(int seed, bool fullRandomMode = false)
		{
			List<ItemSlot> slots = Placement.BuildAllSlots();
			List<Item> pool = Placement.BuildItemPool(fullRandomMode);
			if (!Placement.TryPlaceActive(new Random(seed), slots, pool, out var assignment, fullRandomMode))
			{
				return false;
			}
			return !Detector.Evaluate(assignment, fullRandomMode).IsDead;
		}

		public int ScoreSeed(int seed, bool fullRandomMode = false)
		{
			List<ItemSlot> slots = Placement.BuildAllSlots();
			List<Item> pool = Placement.BuildItemPool(fullRandomMode);
			Dictionary<ItemSlot, Item> assignment;
			bool flag = Placement.TryPlaceActive(new Random(seed), slots, pool, out assignment, fullRandomMode);
			SeedVerdict seedVerdict = Detector.Evaluate(assignment, fullRandomMode);
			if (!seedVerdict.IsDead && flag)
			{
				return 0;
			}
			int num = ((!flag) ? 1000000 : 0);
			if (seedVerdict.Reason != null && seedVerdict.Reason.StartsWith("固定点缺失"))
			{
				num += 1000000;
			}
			num += (seedVerdict.RoomMode ? seedVerdict.UnreachedRoomCount : seedVerdict.UnreachedRegions.Count) * 10000;
			return num + seedVerdict.BlockedSlotIds.Count * 100;
		}

		public int FindLiveSeed(Random rng, int maxTries = 1000, bool fullRandomMode = false)
		{
			for (int i = 0; i < maxTries; i++)
			{
				int num = rng.Next(1, int.MaxValue);
				if (IsSeedLive(num, fullRandomMode))
				{
					return num;
				}
			}
			return -1;
		}

		public void ReplaceSceneConnections(IEnumerable<string> sceneConnectionLines)
		{
			SceneGraph.Build(sceneConnectionLines);
		}

		public void RestoreNativeSceneConnections()
		{
			SceneGraph.Build(_nativeConnLines);
		}

		public void MergeSceneConnections(IEnumerable<string> randomLines)
		{
			SceneGraph.Build(MergeConnectionLines(_nativeConnLines, randomLines));
		}

		private static IEnumerable<string> MergeConnectionLines(IEnumerable<string> nativeLines, IEnumerable<string> randomLines)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			AddLines(dictionary, nativeLines);
			AddLines(dictionary, randomLines);
			return dictionary.Values;
		}

		private static void AddLines(Dictionary<string, string> map, IEnumerable<string> lines)
		{
			foreach (string line in lines)
			{
				string text = line.Trim();
				if (text.Length != 0 && !text.StartsWith("#"))
				{
					string[] array = text.Split(new char[1] { '|' });
					if (array.Length >= 4)
					{
						map[array[0].Trim() + "|" + array[1].Trim()] = text;
					}
				}
			}
		}
	}
}
namespace PharloomCore.Model
{
	public enum AbilityCategory
	{
		Movement,
		Combat,
		Spell,
		Music
	}
	public enum AbilityId
	{
		NeedleThrow,
		Dash,
		DoubleJump,
		Brolly,
		SuperJump,
		Walljump,
		HarpoonDash,
		SilkCharge,
		ThreadSphere,
		SilkBomb,
		SilkBossNeedle,
		ChargeSlash,
		Parry,
		Needolin,
		EvaHeal,
		NeedolinMemory,
		Teleport,
		SilkDash,
		AttackUp,
		AttackLeft,
		AttackRight,
		Heal,
		Swim,
		ShamanCrest,
		ArchitectChargeSlash,
		MelodyConductor,
		MelodyLibrarian,
		MelodyArchitect,
		SilkHeart,
		Journal
	}
	public class Ability
	{
		public AbilityId Id { get; set; }

		public string Key { get; set; }

		public string DisplayName { get; set; }

		public AbilityCategory Category { get; set; }

		public override string ToString()
		{
			return DisplayName ?? Key;
		}
	}
	public static class MusicAbilityIds
	{
		public static readonly HashSet<AbilityId> All = new HashSet<AbilityId>
		{
			AbilityId.Needolin,
			AbilityId.EvaHeal,
			AbilityId.NeedolinMemory,
			AbilityId.Teleport,
			AbilityId.MelodyConductor,
			AbilityId.MelodyLibrarian,
			AbilityId.MelodyArchitect
		};
	}
	public enum GateKind
	{
		Ability,
		Permission,
		AnyAbilityExcept,
		And,
		Or,
		Vertical,
		Horizontal,
		Cold,
		Item,
		Never
	}
	public class Gate
	{
		public GateKind Kind { get; set; }

		public AbilityId Ability { get; set; }

		public string PermissionId { get; set; }

		public PermissionSide PermissionSide { get; set; }

		public HashSet<AbilityId> ExcludedCategoriesOrIds { get; set; }

		public List<Gate> Children { get; set; }

		public int Level { get; set; }

		public string ItemName { get; set; }

		public static Gate AbilityGate(AbilityId id)
		{
			return new Gate
			{
				Kind = GateKind.Ability,
				Ability = id
			};
		}

		public static Gate PermissionGate(string id, PermissionSide side)
		{
			return new Gate
			{
				Kind = GateKind.Permission,
				PermissionId = id + "_" + SideMapping.EngineSuffix(side)
			};
		}

		public static Gate AnyAbilityExcept(params AbilityId[] excluded)
		{
			return new Gate
			{
				Kind = GateKind.AnyAbilityExcept,
				ExcludedCategoriesOrIds = new HashSet<AbilityId>(excluded)
			};
		}

		public static Gate VerticalGate(int level)
		{
			return new Gate
			{
				Kind = GateKind.Vertical,
				Level = level
			};
		}

		public static Gate HorizontalGate(int level, PermissionSide side)
		{
			return new Gate
			{
				Kind = GateKind.Horizontal,
				Level = level,
				PermissionSide = side
			};
		}

		public static Gate ColdGate()
		{
			return new Gate
			{
				Kind = GateKind.Cold
			};
		}

		public static Gate ItemGate(string itemName)
		{
			return new Gate
			{
				Kind = GateKind.Item,
				ItemName = itemName
			};
		}

		public static Gate NeverGate()
		{
			return new Gate
			{
				Kind = GateKind.Never
			};
		}

		public static Gate And(params Gate[] children)
		{
			return new Gate
			{
				Kind = GateKind.And,
				Children = new List<Gate>(children)
			};
		}

		public static Gate Or(params Gate[] children)
		{
			return new Gate
			{
				Kind = GateKind.Or,
				Children = new List<Gate>(children)
			};
		}
	}
	public enum PermissionSide
	{
		Left,
		Right
	}
	public static class SideMapping
	{
		public const bool InvertVisualToEngine = false;

		public static string EngineSuffix(PermissionSide visualSide)
		{
			if (visualSide != PermissionSide.Right)
			{
				return "L";
			}
			return "R";
		}

		public static PermissionSide FromEngineSuffix(string id)
		{
			if (!id.EndsWith("_R"))
			{
				return PermissionSide.Left;
			}
			return PermissionSide.Right;
		}
	}
	public class Permission
	{
		public string Id { get; set; }

		public AbilityId BoundAbility { get; set; }

		public PermissionSide Side { get; set; }

		public bool SidesSplit { get; set; }

		public override string ToString()
		{
			return Id;
		}
	}
	public static class PermissionIds
	{
		public const string Dash = "Dash";

		public const string HarpoonDash = "HarpoonDash";

		public const string Brolly = "Brolly";

		public const string Walljump = "Walljump";

		public const string SuperJump = "SuperJump";
	}
	public class PlayerState
	{
		public HashSet<AbilityId> Abilities { get; } = new HashSet<AbilityId>();

		public HashSet<string> Permissions { get; } = new HashSet<string>();

		public HashSet<string> OwnedItems { get; } = new HashSet<string>();

		public HashSet<Region> ReachableRegions { get; } = new HashSet<Region>();

		public HashSet<string> ReachableRooms { get; set; } = new HashSet<string>();

		public bool HasColdResistance { get; set; }

		public bool HasAbility(AbilityId id)
		{
			return Abilities.Contains(id);
		}

		public bool HasPermission(string id)
		{
			return Permissions.Contains(id);
		}

		public bool OwnsItem(string name)
		{
			return OwnedItems.Contains(name);
		}

		public static PlayerState WithStartingAbilities(bool fullRandomMode)
		{
			PlayerState playerState = new PlayerState();
			if (fullRandomMode)
			{
				return playerState;
			}
			playerState.Abilities.Add(AbilityId.AttackUp);
			playerState.Abilities.Add(AbilityId.AttackLeft);
			playerState.Abilities.Add(AbilityId.AttackRight);
			playerState.Abilities.Add(AbilityId.Heal);
			return playerState;
		}
	}
	public class Region
	{
		public string Id { get; set; }

		public string DisplayName { get; set; }

		public List<string> ScenePrefixes { get; set; }

		public List<string> AdjacentRegionIds { get; set; }

		public Gate EntryGate { get; set; }

		public Dictionary<string, Gate> Exits { get; set; }

		public List<ItemSlot> Slots { get; set; }

		public bool IsStart { get; set; }

		public bool IsDream { get; set; }

		public Region()
		{
			ScenePrefixes = new List<string>();
			AdjacentRegionIds = new List<string>();
			Exits = new Dictionary<string, Gate>();
			Slots = new List<ItemSlot>();
		}

		public override string ToString()
		{
			return DisplayName ?? Id;
		}
	}
	public enum ItemKind
	{
		Ability,
		Permission,
		NamedItem,
		Cold,
		Virtual
	}
	public class ItemSlot
	{
		public string Id { get; set; }

		public string SourceKey { get; set; }

		public Region Region { get; set; }

		public string RoomId { get; set; }

		public bool IsFixed { get; set; }

		public Gate AccessGate { get; set; }

		public override bool Equals(object obj)
		{
			if (obj is ItemSlot itemSlot)
			{
				return string.Equals(Id, itemSlot.Id);
			}
			return false;
		}

		public override int GetHashCode()
		{
			if (Id == null)
			{
				return 0;
			}
			return Id.GetHashCode();
		}

		public override string ToString()
		{
			return Id;
		}
	}
	public class Item
	{
		public ItemKind Kind { get; set; }

		public AbilityId AbilityId { get; set; }

		public string PermissionId { get; set; }

		public string ItemName { get; set; }

		public int Priority { get; set; } = 4;

		public override string ToString()
		{
			return Kind switch
			{
				ItemKind.Ability => AbilityId.ToString(), 
				ItemKind.Permission => PermissionId, 
				ItemKind.NamedItem => "Item:" + ItemName, 
				ItemKind.Cold => "ColdResistance", 
				ItemKind.Virtual => "Virt:" + ItemName, 
				_ => "?", 
			};
		}
	}
	public class RoomComponent
	{
		public List<string> Rooms { get; } = new List<string>();

		public bool IsMain { get; internal set; }

		public bool IsDreamSeeded { get; internal set; }

		public bool IsValid
		{
			get
			{
				if (!IsMain)
				{
					return IsDreamSeeded;
				}
				return true;
			}
		}

		public int Count => Rooms.Count;

		public bool Contains(string roomId)
		{
			if (roomId != null)
			{
				return Rooms.Contains(roomId);
			}
			return false;
		}
	}
	public class RoomGraph
	{
		public const string DefaultStartRoomId = "Tut_01";

		private readonly HashSet<string> _alwaysReachableRooms = new HashSet<string>(StringComparer.Ordinal);

		private List<RoomComponent> _components;

		private Dictionary<string, RoomComponent> _componentOfRoom;

		private RoomComponent _mainComponent;

		private List<string> _orphanRooms;

		private HashSet<string> _orphanRoomSet;

		public string StartRoomId { get; set; } = "Tut_01";

		public Dictionary<string, HashSet<string>> Adjacency { get; } = new Dictionary<string, HashSet<string>>();

		public Dictionary<string, string> RoomToRegion { get; } = new Dictionary<string, string>();

		public List<string> UnmappedScenes { get; } = new List<string>();

		public int RoomCount => Adjacency.Count;

		public IReadOnlyList<RoomComponent> Components
		{
			get
			{
				EnsureComponents();
				return _components;
			}
		}

		public RoomComponent MainComponent
		{
			get
			{
				EnsureComponents();
				return _mainComponent;
			}
		}

		public IReadOnlyList<string> OrphanRoomIds
		{
			get
			{
				if (_orphanRooms == null)
				{
					BuildOrphans();
				}
				return _orphanRooms;
			}
		}

		public IEnumerable<string> Neighbors(string roomId)
		{
			if (roomId != null && Adjacency.TryGetValue(roomId, out var value))
			{
				return value;
			}
			return Array.Empty<string>();
		}

		public void DeclareAlwaysReachableRooms(IEnumerable<string> roomIds)
		{
			_alwaysReachableRooms.Clear();
			if (roomIds != null)
			{
				foreach (string roomId in roomIds)
				{
					if (!string.IsNullOrEmpty(roomId))
					{
						_alwaysReachableRooms.Add(roomId);
					}
				}
			}
			InvalidateQueries();
		}

		public RoomComponent ComponentOf(string roomId)
		{
			EnsureComponents();
			if (roomId == null)
			{
				return null;
			}
			if (!_componentOfRoom.TryGetValue(roomId, out var value))
			{
				return null;
			}
			return value;
		}

		public bool IsOrphanRoom(string roomId)
		{
			if (_orphanRoomSet == null)
			{
				BuildOrphans();
			}
			if (roomId != null)
			{
				return _orphanRoomSet.Contains(roomId);
			}
			return false;
		}

		public static HashSet<string> DreamRegionRooms(Region[] regions, RoomGraph graph)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			if (regions == null || graph == null)
			{
				return hashSet;
			}
			HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal);
			foreach (Region region in regions)
			{
				if (region != null && region.IsDream)
				{
					hashSet2.Add(region.Id);
				}
			}
			if (hashSet2.Count == 0)
			{
				return hashSet;
			}
			foreach (KeyValuePair<string, string> item in graph.RoomToRegion)
			{
				if (hashSet2.Contains(item.Value))
				{
					hashSet.Add(item.Key);
				}
			}
			return hashSet;
		}

		private void InvalidateQueries()
		{
			_components = null;
			_componentOfRoom = null;
			_mainComponent = null;
			_orphanRooms = null;
			_orphanRoomSet = null;
		}

		private void EnsureComponents()
		{
			if (_components != null)
			{
				return;
			}
			List<RoomComponent> list = new List<RoomComponent>();
			Dictionary<string, RoomComponent> dictionary = new Dictionary<string, RoomComponent>(StringComparer.Ordinal);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			List<string> list2 = new List<string>(Adjacency.Keys);
			list2.Sort(StringComparer.Ordinal);
			foreach (string item in list2)
			{
				if (hashSet.Contains(item))
				{
					continue;
				}
				RoomComponent roomComponent = new RoomComponent();
				Queue<string> queue = new Queue<string>();
				queue.Enqueue(item);
				hashSet.Add(item);
				while (queue.Count > 0)
				{
					string text = queue.Dequeue();
					roomComponent.Rooms.Add(text);
					if (!Adjacency.TryGetValue(text, out var value))
					{
						continue;
					}
					foreach (string item2 in value)
					{
						if (item2 != null && Adjacency.ContainsKey(item2) && hashSet.Add(item2))
						{
							queue.Enqueue(item2);
						}
					}
				}
				roomComponent.Rooms.Sort(StringComparer.Ordinal);
				list.Add(roomComponent);
				foreach (string room in roomComponent.Rooms)
				{
					dictionary[room] = roomComponent;
				}
			}
			list.Sort((RoomComponent a, RoomComponent b) => (a.Count == b.Count) ? string.CompareOrdinal(a.Rooms[0], b.Rooms[0]) : b.Count.CompareTo(a.Count));
			if (!string.IsNullOrEmpty(StartRoomId) && dictionary.TryGetValue(StartRoomId, out var value2))
			{
				_mainComponent = value2;
			}
			else
			{
				_mainComponent = ((list.Count > 0) ? list[0] : null);
			}
			if (_mainComponent != null)
			{
				_mainComponent.IsMain = true;
			}
			foreach (RoomComponent item3 in list)
			{
				if (item3.IsMain)
				{
					continue;
				}
				foreach (string room2 in item3.Rooms)
				{
					if (_alwaysReachableRooms.Contains(room2))
					{
						item3.IsDreamSeeded = true;
						break;
					}
				}
			}
			_components = list;
			_componentOfRoom = dictionary;
		}

		private void BuildOrphans()
		{
			EnsureComponents();
			List<string> list = new List<string>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (RoomComponent component in _components)
			{
				if (component.IsValid)
				{
					continue;
				}
				foreach (string room in component.Rooms)
				{
					if (hashSet.Add(room))
					{
						list.Add(room);
					}
				}
			}
			list.Sort(StringComparer.Ordinal);
			_orphanRooms = list;
			_orphanRoomSet = hashSet;
		}
	}
}
namespace PharloomCore.Logic
{
	public class CheckpointSource
	{
		public const string ArboriumWalljumpId = "Arborium_Walljump";

		public const string ArboriumWalljumpLeftId = "Arborium_Walljump_L";

		public const string ArboriumWalljumpRightId = "Arborium_Walljump_R";

		private readonly PrefixResolver _resolver;

		private readonly IReadOnlyDictionary<string, Gate> _conditionsByKey;

		public CheckpointSource(Region[] regions, IReadOnlyDictionary<string, Gate> conditionsByKey = null)
		{
			_resolver = new PrefixResolver(regions);
			_conditionsByKey = conditionsByKey;
		}

		public List<ItemSlot> BuildSlots(string checkpointsPath, bool includeLore = true)
		{
			return BuildSlots(File.ReadAllLines(checkpointsPath), includeLore);
		}

		public List<ItemSlot> BuildSlots(IEnumerable<string> lines, bool includeLore = true)
		{
			List<ItemSlot> list = new List<ItemSlot>();
			int num = 0;
			foreach (string line in lines)
			{
				string text = line.Trim();
				if (text.Length == 0)
				{
					continue;
				}
				string[] array = text.Split(new char[1] { '|' });
				string text2 = array[0];
				if (array.Length < 2 || (text2 != "Pickup" && (!includeLore || !(text2 == "Lore"))))
				{
					continue;
				}
				string text3 = array[1].Trim();
				Region region = _resolver.Resolve(text3);
				if (region != null)
				{
					string text4 = ((array.Length > 5) ? array[5].Trim() : null);
					if (text2 == "Pickup" && array.Length > 7 && float.TryParse(array[6], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array[7], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
					{
						text4 = text3 + "_" + result.ToString("F2", CultureInfo.InvariantCulture) + "_" + result2.ToString("F2", CultureInfo.InvariantCulture) + "_0.00";
					}
					Gate accessGate = null;
					if (text4 != null && _conditionsByKey != null && _conditionsByKey.TryGetValue(text4, out var value))
					{
						accessGate = value;
					}
					list.Add(new ItemSlot
					{
						Id = text2 + "_" + num + "_" + text3,
						SourceKey = text4,
						Region = region,
						RoomId = text3,
						AccessGate = accessGate
					});
					num++;
				}
			}
			ClaimArboriumFixedSlots(list);
			return list;
		}

		private static void ClaimArboriumFixedSlots(List<ItemSlot> slots)
		{
			List<ItemSlot> list = new List<ItemSlot>();
			foreach (ItemSlot slot in slots)
			{
				if (slot.Region.Id == "Arborium")
				{
					list.Add(slot);
				}
			}
			if (list.Count >= 3)
			{
				list[0].Id = "Arborium_Walljump";
				list[0].IsFixed = true;
				list[1].Id = "Arborium_Walljump_L";
				list[1].IsFixed = true;
				list[2].Id = "Arborium_Walljump_R";
				list[2].IsFixed = true;
			}
		}
	}
	public class SeedVerdict
	{
		public bool IsDead { get; set; }

		public int ReachedCount { get; set; }

		public int TotalCount { get; set; }

		public List<string> UnreachedRegions { get; } = new List<string>();

		public List<string> ReachedRegions { get; } = new List<string>();

		public List<string> BlockedSlotIds { get; } = new List<string>();

		public string Reason { get; set; }

		public List<string> UnreachedRooms { get; } = new List<string>();

		public List<string> ReachedRooms { get; } = new List<string>();

		public List<string> ExemptRooms { get; } = new List<string>();

		public IReadOnlyList<string> GapRoomIds { get; set; }

		public bool HasGapExemption => ExemptRooms.Count > 0;

		public bool RoomMode { get; set; }

		public string ScopeLabel
		{
			get
			{
				if (!RoomMode)
				{
					return "区域";
				}
				return "房间";
			}
		}

		public int UnreachedRoomCount => UnreachedRooms.Count;

		private string ExemptNote
		{
			get
			{
				if (ExemptRooms.Count <= 0)
				{
					return string.Empty;
				}
				return "(另有 " + ExemptRooms.Count + " 个数据缺口房间豁免,不计死种)";
			}
		}

		public override string ToString()
		{
			if (!IsDead)
			{
				return "活种子: 全部 " + ReachedCount + " " + ScopeLabel + "可达" + ExemptNote;
			}
			return "死种子: " + (string.IsNullOrEmpty(Reason) ? string.Join(", ", UnreachedRegions) : Reason);
		}
	}
	public class DeadSeedDetector
	{
		private readonly ReachabilityAnalyzer _analyzer;

		private readonly RoomGapSet _gaps;

		public bool RoomPrecision => _analyzer.RoomPrecision;

		public RoomGapSet Gaps => _gaps;

		public DeadSeedDetector(Region[] regions, RoomGraph roomGraph = null)
		{
			_analyzer = new ReachabilityAnalyzer(regions, roomGraph);
			_gaps = RoomGapSet.Compute(roomGraph, regions, null);
		}

		public SeedVerdict Evaluate(IReadOnlyDictionary<ItemSlot, Item> assignment, bool fullRandomMode = false)
		{
			SeedVerdict seedVerdict = new SeedVerdict
			{
				RoomMode = _analyzer.RoomPrecision
			};
			if (assignment == null)
			{
				seedVerdict.IsDead = true;
				seedVerdict.Reason = "分配为空(放置失败)";
				return seedVerdict;
			}
			ReachabilityResult reachabilityResult = _analyzer.Compute(assignment, fullRandomMode);
			seedVerdict.ReachedCount = (RoomPrecision ? reachabilityResult.ReachedRoomIds.Count : reachabilityResult.ReachedRegionIds.Count);
			seedVerdict.TotalCount = ((!RoomPrecision) ? _analyzer.Regions.Length : ((_analyzer.RoomGraph != null) ? _analyzer.RoomGraph.RoomCount : 0));
			seedVerdict.ReachedRegions.AddRange(reachabilityResult.ReachedRegionIds);
			seedVerdict.UnreachedRegions.AddRange(reachabilityResult.UnreachedRegionIds);
			seedVerdict.ReachedRooms.AddRange(reachabilityResult.ReachedRoomIds);
			seedVerdict.BlockedSlotIds.AddRange(reachabilityResult.BlockedSlotIds);
			if (RoomPrecision)
			{
				seedVerdict.GapRoomIds = ((_gaps != null) ? _gaps.GapRoomIds : null);
				foreach (string unreachedRoomId in reachabilityResult.UnreachedRoomIds)
				{
					if (_gaps != null && _gaps.IsGapRoom(unreachedRoomId))
					{
						seedVerdict.ExemptRooms.Add(unreachedRoomId);
					}
					else
					{
						seedVerdict.UnreachedRooms.Add(unreachedRoomId);
					}
				}
			}
			else
			{
				seedVerdict.UnreachedRooms.AddRange(reachabilityResult.UnreachedRoomIds);
			}
			string text = FindFixedViolation(assignment);
			if (text != null)
			{
				seedVerdict.IsDead = true;
				seedVerdict.Reason = "固定点缺失: " + text;
				return seedVerdict;
			}
			if (RoomPrecision ? (seedVerdict.UnreachedRooms.Count > 0) : (!reachabilityResult.AllReached))
			{
				seedVerdict.IsDead = true;
				if (RoomPrecision)
				{
					seedVerdict.Reason = "房间不可达 (" + seedVerdict.UnreachedRooms.Count + "): " + string.Join(", ", seedVerdict.UnreachedRooms) + ExemptSuffix(seedVerdict);
				}
				else
				{
					seedVerdict.Reason = "区域不可达: " + string.Join(", ", reachabilityResult.UnreachedRegionIds);
				}
				return seedVerdict;
			}
			if (!reachabilityResult.AllPointsAccessible)
			{
				seedVerdict.IsDead = true;
				seedVerdict.Reason = "点位条件不可达 (" + reachabilityResult.BlockedSlotIds.Count + "): " + string.Join(", ", reachabilityResult.BlockedSlotIds);
				return seedVerdict;
			}
			seedVerdict.IsDead = false;
			return seedVerdict;
		}

		private static string ExemptSuffix(SeedVerdict verdict)
		{
			if (verdict.ExemptRooms.Count <= 0)
			{
				return string.Empty;
			}
			return ";另有 " + verdict.ExemptRooms.Count + " 个数据缺口房间豁免(不计死种): " + string.Join(", ", verdict.ExemptRooms);
		}

		private static string FindFixedViolation(IReadOnlyDictionary<ItemSlot, Item> assignment)
		{
			foreach (KeyValuePair<ItemSlot, Item> item in assignment)
			{
				if (item.Key.IsFixed && !MatchesFixed(item.Key, item.Value))
				{
					return item.Key.Id + " 固定物品被篡改";
				}
			}
			return null;
		}

		private static bool MatchesFixed(ItemSlot slot, Item item)
		{
			if (slot.Id == "Arborium_Walljump")
			{
				if (item.Kind == ItemKind.Ability)
				{
					return item.AbilityId == AbilityId.Walljump;
				}
				return false;
			}
			if (slot.Id == "Arborium_Walljump_L")
			{
				if (item.Kind == ItemKind.Permission && item.PermissionId == "Walljump_" + SideMapping.EngineSuffix(PermissionSide.Left))
				{
					return item.AbilityId == AbilityId.Walljump;
				}
				return false;
			}
			if (slot.Id == "Arborium_Walljump_R")
			{
				if (item.Kind == ItemKind.Permission && item.PermissionId == "Walljump_" + SideMapping.EngineSuffix(PermissionSide.Right))
				{
					return item.AbilityId == AbilityId.Walljump;
				}
				return false;
			}
			return false;
		}
	}
	public class FixedAssignments
	{
		public const string ArboriumWalljumpSlot = "Arborium_Walljump";

		public const string ArboriumWalljumpLeftSlot = "Arborium_Walljump_L";

		public const string ArboriumWalljumpRightSlot = "Arborium_Walljump_R";

		public Dictionary<ItemSlot, Item> All { get; }

		public FixedAssignments(Region[] regions)
		{
			All = new Dictionary<ItemSlot, Item>();
			Region region = FindRegion(regions, "Arborium");
			if (region != null)
			{
				Add("Arborium_Walljump", region, new Item
				{
					Kind = ItemKind.Ability,
					AbilityId = AbilityId.Walljump
				});
				Add("Arborium_Walljump_L", region, new Item
				{
					Kind = ItemKind.Permission,
					PermissionId = "Walljump_" + SideMapping.EngineSuffix(PermissionSide.Left),
					AbilityId = AbilityId.Walljump
				});
				Add("Arborium_Walljump_R", region, new Item
				{
					Kind = ItemKind.Permission,
					PermissionId = "Walljump_" + SideMapping.EngineSuffix(PermissionSide.Right),
					AbilityId = AbilityId.Walljump
				});
			}
		}

		private void Add(string id, Region region, Item item)
		{
			All[new ItemSlot
			{
				Id = id,
				Region = region,
				IsFixed = true
			}] = item;
		}

		private static Region FindRegion(Region[] regions, string id)
		{
			foreach (Region region in regions)
			{
				if (region.Id == id)
				{
					return region;
				}
			}
			return null;
		}
	}
	public static class GateEvaluator
	{
		public static bool Satisfied(Gate gate, PlayerState state)
		{
			switch (gate.Kind)
			{
			case GateKind.Ability:
				return state.HasAbility(gate.Ability);
			case GateKind.Permission:
				return state.HasPermission(gate.PermissionId);
			case GateKind.And:
				foreach (Gate child in gate.Children)
				{
					if (!Satisfied(child, state))
					{
						return false;
					}
				}
				return true;
			case GateKind.Or:
				foreach (Gate child2 in gate.Children)
				{
					if (Satisfied(child2, state))
					{
						return true;
					}
				}
				return false;
			case GateKind.AnyAbilityExcept:
				foreach (AbilityId ability in state.Abilities)
				{
					if (!gate.ExcludedCategoriesOrIds.Contains(ability))
					{
						return true;
					}
				}
				return false;
			case GateKind.Vertical:
				return VerticalSatisfied(gate.Level, state);
			case GateKind.Horizontal:
				return HorizontalSatisfied(gate.Level, state);
			case GateKind.Cold:
				return state.HasColdResistance;
			case GateKind.Item:
				return state.OwnsItem(gate.ItemName);
			case GateKind.Never:
				return false;
			default:
				return false;
			}
		}

		public static bool VerticalSatisfied(int level, PlayerState state)
		{
			switch (level)
			{
			case 3:
				return state.HasAbility(AbilityId.SuperJump);
			case 2:
				if (!state.HasAbility(AbilityId.SuperJump))
				{
					return state.HasAbility(AbilityId.Walljump);
				}
				return true;
			default:
				if (!state.HasAbility(AbilityId.SuperJump) && !state.HasAbility(AbilityId.Walljump))
				{
					return state.HasAbility(AbilityId.DoubleJump);
				}
				return true;
			}
		}

		public static bool HorizontalSatisfied(int level, PlayerState state)
		{
			if (level >= 3)
			{
				if (!state.HasAbility(AbilityId.SuperJump))
				{
					return state.HasAbility(AbilityId.HarpoonDash);
				}
				return true;
			}
			if (!state.HasAbility(AbilityId.SuperJump) && !state.HasAbility(AbilityId.HarpoonDash) && !state.HasAbility(AbilityId.Dash) && !state.HasAbility(AbilityId.Brolly))
			{
				return state.HasAbility(AbilityId.SilkDash);
			}
			return true;
		}
	}
	public static class KeyItemAlignment
	{
		public class Row
		{
			public string SirId;

			public string Name;

			public int SirLimit;

			public string Engine;

			public int PoolCount;

			public bool Covered;

			public bool FixedOnly;

			public string Note;
		}

		private const string ColdKind = "@COLD";

		private static readonly HashSet<string> DirectionSkills = new HashSet<string> { "hasDash", "hasHarpoonDash", "hasBrolly", "hasWalljump", "HasSeenEvaHeal" };

		private static readonly (string id, string eng, string name, bool dirSkill)[] AllAbilities = new(string, string, string, bool)[24]
		{
			("hasNeedleThrow", AbilityId.NeedleThrow.ToString(), "丝之矛", false),
			("hasThreadSphere", AbilityId.ThreadSphere.ToString(), "灵丝风暴", false),
			("hasSilkCharge", AbilityId.SilkCharge.ToString(), "丝刃标", false),
			("hasSilkBomb", AbilityId.SilkBomb.ToString(), "符文之怒", false),
			("hasSilkBossNeedle", AbilityId.SilkBossNeedle.ToString(), "苍白之爪", false),
			("hasParry", AbilityId.Parry.ToString(), "格挡", false),
			("hasHarpoonDash", AbilityId.HarpoonDash.ToString(), "飞针(方向技能)", true),
			("hasNeedolin", AbilityId.Needolin.ToString(), "丝忆弦针", false),
			("hasDash", AbilityId.Dash.ToString(), "疾风步(方向技能)", true),
			("hasBrolly", AbilityId.Brolly.ToString(), "流浪者披风(方向技能)", true),
			("hasDoubleJump", AbilityId.DoubleJump.ToString(), "雪绒披风(二段跳)", false),
			("hasChargeSlash", AbilityId.ChargeSlash.ToString(), "蓄力斩", false),
			("hasSuperJump", AbilityId.SuperJump.ToString(), "灵丝升腾", false),
			("hasWalljump", AbilityId.Walljump.ToString(), "蛛攀术(方向技能)", true),
			("HasSeenEvaHeal", AbilityId.EvaHeal.ToString(), "风铃摇·回血(方向技能)", true),
			("hasNeedolinMemoryPowerup", AbilityId.NeedolinMemory.ToString(), "深邃挽歌", false),
			("hasFastTravelTeleport", AbilityId.Teleport.ToString(), "幻兽歌", false),
			("HasMelodyConductor", AbilityId.MelodyConductor.ToString(), "旋律·指挥", false),
			("HasMelodyLibrarian", AbilityId.MelodyLibrarian.ToString(), "旋律·司书", false),
			("HasMelodyArchitect", AbilityId.MelodyArchitect.ToString(), "旋律·建筑师", false),
			("SilkHeart", AbilityId.SilkHeart.ToString(), "丝之心", false),
			("Journal", AbilityId.Journal.ToString(), "猎人日志", false),
			("ColdResist", "@COLD", "寒冷抗性", false),
			("Swim", AbilityId.Swim.ToString(), "游泳", false)
		};

		public static List<Row> Build(List<Item> pool, bool fullRandomMode)
		{
			List<Row> list = new List<Row>();
			(string, string, string, bool)[] allAbilities = AllAbilities;
			for (int i = 0; i < allAbilities.Length; i++)
			{
				var (text, eng, name, _) = allAbilities[i];
				if (!fullRandomMode || !DirectionSkills.Contains(text))
				{
					bool flag = text == "hasWalljump";
					int num = ((eng == "@COLD") ? pool.Count((Item item) => item.Kind == ItemKind.Cold) : pool.Count((Item item) => item.Kind == ItemKind.Ability && item.AbilityId.ToString() == eng));
					list.Add(new Row
					{
						SirId = text,
						Name = name,
						SirLimit = ((text == "SilkHeart") ? 3 : 2),
						Engine = ((eng == "@COLD") ? "ItemKind.Cold" : ("能力 " + eng)),
						PoolCount = num,
						Covered = (flag || num > 0),
						FixedOnly = flag
					});
				}
			}
			if (fullRandomMode)
			{
				AddDirectionPerms(list, pool);
			}
			list.Add(Named("virt:UnlockCrestSlot", "纹章槽位解锁器", 2, "CrestSocketUnlocker", pool));
			list.Add(Named("Simple Key", "简单钥匙", 4, "SimpleKey", pool));
			list.Add(Named("virt:SlabKeyA", "怠惰之钥", 1, "SlabKeyA", pool));
			list.Add(Named("virt:SlabKeyB", "异端之钥", 1, "SlabKeyB", pool));
			list.Add(Named("virt:SlabKeyC", "叛教之钥", 1, "SlabKeyC", pool));
			return list;
		}

		private static void AddDirectionPerms(List<Row> rows, List<Item> pool)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (Item item8 in pool)
			{
				if (item8.Kind == ItemKind.Permission && PermissionsData.All.TryGetValue(item8.PermissionId, out var value))
				{
					string key = value.BoundAbility.ToString() + "_" + value.Side;
					dictionary[key] = ((!dictionary.TryGetValue(key, out var value2)) ? 1 : (value2 + 1));
				}
			}
			(string, string, AbilityId, PermissionSide, bool)[] array = new(string, string, AbilityId, PermissionSide, bool)[8]
			{
				("perm:hasDash_L", "冲刺左", AbilityId.Dash, PermissionSide.Left, false),
				("perm:hasDash_R", "冲刺右", AbilityId.Dash, PermissionSide.Right, false),
				("perm:hasHarpoonDash_L", "飞针左", AbilityId.HarpoonDash, PermissionSide.Left, false),
				("perm:hasHarpoonDash_R", "飞针右", AbilityId.HarpoonDash, PermissionSide.Right, false),
				("perm:hasBrolly_L", "漂浮左", AbilityId.Brolly, PermissionSide.Left, false),
				("perm:hasBrolly_R", "漂浮右", AbilityId.Brolly, PermissionSide.Right, false),
				("perm:hasWalljump_L", "壁跳左", AbilityId.Walljump, PermissionSide.Left, true),
				("perm:hasWalljump_R", "壁跳右", AbilityId.Walljump, PermissionSide.Right, true)
			};
			for (int i = 0; i < array.Length; i++)
			{
				(string, string, AbilityId, PermissionSide, bool) tuple = array[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				AbilityId item3 = tuple.Item3;
				PermissionSide item4 = tuple.Item4;
				bool item5 = tuple.Item5;
				string key2 = item3.ToString() + "_" + item4;
				int value3;
				int num = (dictionary.TryGetValue(key2, out value3) ? value3 : 0);
				rows.Add(new Row
				{
					SirId = item,
					Name = item2,
					SirLimit = 1,
					Engine = "权限 " + item3.ToString() + "_" + item4,
					PoolCount = num,
					Covered = (item5 || num > 0),
					FixedOnly = item5
				});
			}
			(string, string, AbilityId)[] array2 = new(string, string, AbilityId)[4]
			{
				("perm:upward", "上劈权限", AbilityId.AttackUp),
				("perm:left", "左劈权限", AbilityId.AttackLeft),
				("perm:right", "右劈权限", AbilityId.AttackRight),
				("perm:heal", "回血权限", AbilityId.Heal)
			};
			for (int i = 0; i < array2.Length; i++)
			{
				(string, string, AbilityId) tuple2 = array2[i];
				string item6 = tuple2.Item1;
				string item7 = tuple2.Item2;
				AbilityId ability = tuple2.Item3;
				int num2 = pool.Count((Item item8) => item8.Kind == ItemKind.Ability && item8.AbilityId == ability);
				rows.Add(new Row
				{
					SirId = item6,
					Name = item7,
					SirLimit = 2,
					Engine = "能力 " + ability,
					PoolCount = num2,
					Covered = (num2 > 0),
					Note = "无方向,引擎以能力建模"
				});
			}
		}

		private static Row Named(string sirId, string name, int limit, string itemName, List<Item> pool)
		{
			return new Row
			{
				SirId = sirId,
				Name = name,
				SirLimit = limit,
				Engine = "NamedItem " + itemName,
				PoolCount = pool.Count((Item i) => i.Kind == ItemKind.NamedItem && i.ItemName == itemName),
				Covered = pool.Any((Item i) => i.Kind == ItemKind.NamedItem && i.ItemName == itemName)
			};
		}
	}
	public class PlacementSimulator
	{
		private readonly Region[] _regions;

		private readonly string _checkpointsPath;

		private readonly IEnumerable<string> _checkpointLines;

		private readonly IReadOnlyDictionary<string, Gate> _conditionsByKey;

		private readonly int _randomSlotCount;

		private readonly RoomGraph _roomGraph;

		private List<ItemSlot> _cachedSlots;

		private List<Item> _cachedPool;

		private bool _cachedPoolFullRandom;

		private Dictionary<ItemSlot, Item> _cachedFixed;

		public bool RoomPrecision => _roomGraph != null;

		public PlacementSimulator(Region[] regions, string checkpointsPath, int randomSlotCount = 0, IReadOnlyDictionary<string, Gate> conditionsByKey = null, RoomGraph roomGraph = null)
		{
			_regions = regions;
			_checkpointsPath = checkpointsPath;
			_randomSlotCount = randomSlotCount;
			_conditionsByKey = conditionsByKey;
			_roomGraph = roomGraph;
		}

		public PlacementSimulator(Region[] regions, IEnumerable<string> checkpointLines, int randomSlotCount = 0, IReadOnlyDictionary<string, Gate> conditionsByKey = null, RoomGraph roomGraph = null)
		{
			_regions = regions;
			_checkpointLines = checkpointLines;
			_randomSlotCount = randomSlotCount;
			_conditionsByKey = conditionsByKey;
			_roomGraph = roomGraph;
		}

		public List<ItemSlot> BuildAllSlots()
		{
			if (_cachedSlots != null)
			{
				return _cachedSlots;
			}
			return _cachedSlots = ((_checkpointLines != null) ? new CheckpointSource(_regions, _conditionsByKey).BuildSlots(_checkpointLines) : ((_checkpointsPath != null) ? new CheckpointSource(_regions, _conditionsByKey).BuildSlots(_checkpointsPath) : BuildSyntheticSlots()));
		}

		public Gate FindPointGate(string key)
		{
			if (key == null || _conditionsByKey == null)
			{
				return null;
			}
			if (!_conditionsByKey.TryGetValue(key.Trim(), out var value))
			{
				return null;
			}
			return value;
		}

		public Dictionary<ItemSlot, Item> BuildFixedAssignments()
		{
			if (_cachedFixed != null)
			{
				return new Dictionary<ItemSlot, Item>(_cachedFixed);
			}
			_cachedFixed = new FixedAssignments(_regions).All;
			return new Dictionary<ItemSlot, Item>(_cachedFixed);
		}

		public List<Item> BuildItemPool(bool fullRandomMode = false)
		{
			if (_cachedPool != null && _cachedPoolFullRandom == fullRandomMode)
			{
				return _cachedPool;
			}
			HashSet<AbilityId> hashSet = new HashSet<AbilityId>
			{
				AbilityId.Dash,
				AbilityId.HarpoonDash,
				AbilityId.Brolly,
				AbilityId.Walljump,
				AbilityId.EvaHeal
			};
			HashSet<AbilityId> hashSet2 = new HashSet<AbilityId>
			{
				AbilityId.AttackUp,
				AbilityId.AttackLeft,
				AbilityId.AttackRight,
				AbilityId.Heal
			};
			List<Item> list = new List<Item>();
			foreach (Ability value in AbilitiesData.All.Values)
			{
				if (value.Id != AbilityId.Walljump && (!fullRandomMode || !hashSet.Contains(value.Id)) && (fullRandomMode || !hashSet2.Contains(value.Id)))
				{
					list.Add(new Item
					{
						Kind = ItemKind.Ability,
						AbilityId = value.Id,
						Priority = ItemTiers.Resolve(new Item
						{
							Kind = ItemKind.Ability,
							AbilityId = value.Id
						})
					});
					list.Add(new Item
					{
						Kind = ItemKind.Ability,
						AbilityId = value.Id,
						Priority = ItemTiers.Resolve(new Item
						{
							Kind = ItemKind.Ability,
							AbilityId = value.Id
						})
					});
					if (value.Id == AbilityId.SilkHeart)
					{
						list.Add(new Item
						{
							Kind = ItemKind.Ability,
							AbilityId = value.Id,
							Priority = ItemTiers.Resolve(new Item
							{
								Kind = ItemKind.Ability,
								AbilityId = value.Id
							})
						});
					}
				}
			}
			list.Add(new Item
			{
				Kind = ItemKind.Cold,
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.Cold
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.Cold,
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.Cold
				})
			});
			if (fullRandomMode)
			{
				foreach (Permission value2 in PermissionsData.All.Values)
				{
					if (!(value2.Id == "Walljump_L") && !(value2.Id == "Walljump_R"))
					{
						list.Add(new Item
						{
							Kind = ItemKind.Permission,
							PermissionId = value2.Id,
							AbilityId = value2.BoundAbility,
							Priority = ItemTiers.Resolve(new Item
							{
								Kind = ItemKind.Permission,
								PermissionId = value2.Id,
								AbilityId = value2.BoundAbility
							})
						});
					}
				}
			}
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SlabKeyA",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SlabKeyA"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SlabKeyB",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SlabKeyB"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SlabKeyC",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SlabKeyC"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "CrestSocketUnlocker",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "CrestSocketUnlocker"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "CrestSocketUnlocker",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "CrestSocketUnlocker"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SimpleKey",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SimpleKey"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SimpleKey",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SimpleKey"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SimpleKey",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SimpleKey"
				})
			});
			list.Add(new Item
			{
				Kind = ItemKind.NamedItem,
				ItemName = "SimpleKey",
				Priority = ItemTiers.Resolve(new Item
				{
					Kind = ItemKind.NamedItem,
					ItemName = "SimpleKey"
				})
			});
			_cachedPool = list;
			_cachedPoolFullRandom = fullRandomMode;
			return list;
		}

		public Dictionary<ItemSlot, Item> Randomize(Random rng, List<ItemSlot> slots, List<Item> pool)
		{
			Dictionary<ItemSlot, Item> dictionary = new Dictionary<ItemSlot, Item>();
			foreach (KeyValuePair<ItemSlot, Item> item in BuildFixedAssignments())
			{
				dictionary[MatchFixedSlot(slots, item.Key) ?? item.Key] = item.Value;
			}
			List<Item> list = new List<Item>(pool);
			Shuffle(rng, list);
			List<ItemSlot> list2 = new List<ItemSlot>();
			foreach (ItemSlot slot in slots)
			{
				if (!slot.IsFixed)
				{
					list2.Add(slot);
				}
			}
			Shuffle(rng, list2);
			for (int i = 0; i < list.Count && i < list2.Count; i++)
			{
				dictionary[list2[i]] = list[i];
			}
			return dictionary;
		}

		public bool TryPlaceActive(Random rng, List<ItemSlot> slots, List<Item> pool, out Dictionary<ItemSlot, Item> assignment, bool fullRandomMode = false)
		{
			return new SpherePlacement(_regions, _roomGraph).TryPlace(slots, pool, out assignment, fullRandomMode, rng);
		}

		public Dictionary<ItemSlot, Item> BuildAssignment(int seed, bool fullRandomMode = false)
		{
			if (!TryPlaceActive(new Random(seed), BuildAllSlots(), BuildItemPool(fullRandomMode), out var assignment, fullRandomMode))
			{
				return null;
			}
			return assignment;
		}

		public Dictionary<ItemSlot, Item> TryPlaceLive(Random rng, List<ItemSlot> slots, List<Item> pool, int maxAttempts = 200, bool fullRandomMode = false)
		{
			DeadSeedDetector deadSeedDetector = new DeadSeedDetector(_regions, _roomGraph);
			for (int i = 0; i < maxAttempts; i++)
			{
				if (TryPlaceActive(rng, slots, pool, out var assignment, fullRandomMode) && !deadSeedDetector.Evaluate(assignment, fullRandomMode).IsDead)
				{
					return assignment;
				}
			}
			return null;
		}

		internal static ItemSlot MatchFixedSlot(List<ItemSlot> slots, ItemSlot fixedSlot)
		{
			foreach (ItemSlot slot in slots)
			{
				if (slot.IsFixed && string.Equals(slot.Id, fixedSlot.Id, StringComparison.Ordinal))
				{
					return slot;
				}
			}
			return null;
		}

		private List<ItemSlot> BuildSyntheticSlots()
		{
			List<ItemSlot> list = new List<ItemSlot>();
			Random random = new Random(1);
			for (int i = 0; i < _randomSlotCount; i++)
			{
				list.Add(new ItemSlot
				{
					Id = "Slot_" + i,
					Region = _regions[random.Next(_regions.Length)]
				});
			}
			foreach (KeyValuePair<ItemSlot, Item> item in BuildFixedAssignments())
			{
				list.Add(item.Key);
			}
			return list;
		}

		private static void Shuffle<T>(Random rng, IList<T> list)
		{
			for (int num = list.Count - 1; num > 0; num--)
			{
				int index = rng.Next(num + 1);
				T value = list[num];
				list[num] = list[index];
				list[index] = value;
			}
		}

		internal static List<T> Shuffled<T>(Random rng, IList<T> source)
		{
			List<T> list = new List<T>(source);
			Shuffle(rng, list);
			return list;
		}
	}
	public class PrefixResolver
	{
		private readonly Dictionary<string, Region> _byPrefix = new Dictionary<string, Region>();

		private string[] _prefixesByLengthDesc;

		public PrefixResolver(Region[] regions)
		{
			foreach (Region region in regions)
			{
				foreach (string scenePrefix in region.ScenePrefixes)
				{
					_byPrefix[scenePrefix] = region;
				}
			}
		}

		public Region Resolve(string sceneName)
		{
			if (string.IsNullOrEmpty(sceneName))
			{
				return null;
			}
			string text = sceneName.ToLowerInvariant();
			string[] array = PrefixesByLengthDesc();
			foreach (string text2 in array)
			{
				string text3 = text2.ToLowerInvariant();
				if (text.StartsWith(text3 + "_") || text == text3)
				{
					return _byPrefix[text2];
				}
			}
			return null;
		}

		private string[] PrefixesByLengthDesc()
		{
			if (_prefixesByLengthDesc != null)
			{
				return _prefixesByLengthDesc;
			}
			List<string> list = new List<string>(_byPrefix.Keys);
			list.Sort((string a, string b) => b.Length.CompareTo(a.Length));
			_prefixesByLengthDesc = list.ToArray();
			return _prefixesByLengthDesc;
		}
	}
	public class ReachabilityResult
	{
		public PlayerState State { get; set; }

		public List<string> ReachedRegionIds { get; } = new List<string>();

		public List<string> UnreachedRegionIds { get; } = new List<string>();

		public List<string> BlockedSlotIds { get; } = new List<string>();

		public List<string> ReachedRoomIds { get; } = new List<string>();

		public List<string> UnreachedRoomIds { get; } = new List<string>();

		public bool RoomMode { get; set; }

		public bool AllReached
		{
			get
			{
				if (!RoomMode)
				{
					return UnreachedRegionIds.Count == 0;
				}
				return UnreachedRoomIds.Count == 0;
			}
		}

		public bool AllPointsAccessible => BlockedSlotIds.Count == 0;

		public int StepCount { get; set; }

		public int Steps
		{
			get
			{
				return StepCount;
			}
			set
			{
				StepCount = value;
			}
		}
	}
	public class ReachabilityAnalyzer
	{
		private readonly Region[] _regions;

		private readonly Dictionary<string, Region> _byId = new Dictionary<string, Region>();

		private readonly RoomGraph _roomGraph;

		public Region[] Regions => _regions;

		public bool RoomPrecision => _roomGraph != null;

		public RoomGraph RoomGraph => _roomGraph;

		public List<ItemSlot> AllSlots { get; set; }

		public ReachabilityAnalyzer(Region[] regions, RoomGraph roomGraph = null)
		{
			_regions = regions;
			_roomGraph = roomGraph;
			foreach (Region region in regions)
			{
				_byId[region.Id] = region;
			}
		}

		public ReachabilityResult Compute(IReadOnlyDictionary<ItemSlot, Item> assignment, bool fullRandomMode = false, IReadOnlyList<Item> grants = null)
		{
			if (_roomGraph != null)
			{
				return RoomReachability.Compute(assignment, AllSlots, _roomGraph, _regions, fullRandomMode, grants);
			}
			return ComputeRegion(assignment, fullRandomMode, grants);
		}

		private ReachabilityResult ComputeRegion(IReadOnlyDictionary<ItemSlot, Item> assignment, bool fullRandomMode, IReadOnlyList<Item> grants = null)
		{
			PlayerState playerState = PlayerState.WithStartingAbilities(fullRandomMode);
			Region region = FindStart();
			if (region == null)
			{
				return new ReachabilityResult
				{
					State = playerState
				};
			}
			ReachabilityResult reachabilityResult = new ReachabilityResult
			{
				State = playerState
			};
			playerState.ReachableRegions.Add(region);
			Region[] regions = _regions;
			foreach (Region region2 in regions)
			{
				if (region2.IsDream)
				{
					playerState.ReachableRegions.Add(region2);
				}
			}
			HashSet<Region> hashSet = new HashSet<Region>();
			HashSet<ItemSlot> hashSet2 = new HashSet<ItemSlot>();
			HashSet<Region> hashSet3 = new HashSet<Region>();
			Queue<Region> queue = new Queue<Region>();
			queue.Enqueue(region);
			regions = _regions;
			foreach (Region region3 in regions)
			{
				if (region3.IsDream)
				{
					queue.Enqueue(region3);
				}
			}
			AddFrontier(region, hashSet3, playerState);
			regions = _regions;
			foreach (Region region4 in regions)
			{
				if (region4.IsDream)
				{
					AddFrontier(region4, hashSet3, playerState);
				}
			}
			if (grants != null)
			{
				foreach (Item grant in grants)
				{
					ApplyItem(playerState, grant);
				}
			}
			int num = 0;
			do
			{
				bool flag = false;
				while (queue.Count > 0)
				{
					Region item = queue.Dequeue();
					if (hashSet.Add(item))
					{
						flag = true;
					}
				}
				foreach (KeyValuePair<ItemSlot, Item> item2 in assignment)
				{
					ItemSlot key = item2.Key;
					if (!hashSet2.Contains(key) && playerState.ReachableRegions.Contains(key.Region) && (key.AccessGate == null || GateEvaluator.Satisfied(key.AccessGate, playerState)))
					{
						hashSet2.Add(key);
						ApplyItem(playerState, item2.Value);
						flag = true;
					}
				}
				if (!flag)
				{
					break;
				}
				List<Region> list = new List<Region>();
				foreach (Region item3 in hashSet3)
				{
					if (!playerState.ReachableRegions.Contains(item3) && (item3.EntryGate == null || GateEvaluator.Satisfied(item3.EntryGate, playerState)))
					{
						list.Add(item3);
					}
				}
				foreach (Region item4 in list)
				{
					playerState.ReachableRegions.Add(item4);
					hashSet3.Remove(item4);
					queue.Enqueue(item4);
					AddFrontier(item4, hashSet3, playerState);
				}
				if (list.Count == 0)
				{
					break;
				}
				num++;
			}
			while (num <= 1000);
			regions = _regions;
			foreach (Region region5 in regions)
			{
				if (playerState.ReachableRegions.Contains(region5))
				{
					reachabilityResult.ReachedRegionIds.Add(region5.Id);
				}
				else
				{
					reachabilityResult.UnreachedRegionIds.Add(region5.Id);
				}
			}
			foreach (KeyValuePair<ItemSlot, Item> item5 in assignment)
			{
				ItemSlot key2 = item5.Key;
				if (key2.AccessGate != null && playerState.ReachableRegions.Contains(key2.Region) && !GateEvaluator.Satisfied(key2.AccessGate, playerState))
				{
					reachabilityResult.BlockedSlotIds.Add(key2.Id ?? key2.SourceKey ?? "?");
				}
			}
			reachabilityResult.StepCount = num;
			return reachabilityResult;
		}

		internal static void ApplyItem(PlayerState state, Item item)
		{
			switch (item.Kind)
			{
			case ItemKind.Ability:
				state.Abilities.Add(item.AbilityId);
				{
					foreach (Permission value in PermissionsData.All.Values)
					{
						if (value.BoundAbility == item.AbilityId)
						{
							state.Permissions.Add(value.Id);
						}
					}
					break;
				}
			case ItemKind.Permission:
				state.Permissions.Add(item.PermissionId);
				state.Abilities.Add(item.AbilityId);
				break;
			case ItemKind.NamedItem:
				if (!string.IsNullOrEmpty(item.ItemName))
				{
					state.OwnedItems.Add(item.ItemName);
				}
				break;
			case ItemKind.Cold:
				state.HasColdResistance = true;
				break;
			case ItemKind.Virtual:
				if (!string.IsNullOrEmpty(item.ItemName))
				{
					state.OwnedItems.Add(item.ItemName);
				}
				break;
			}
		}

		private void AddFrontier(Region region, HashSet<Region> frontier, PlayerState state)
		{
			foreach (string adjacentRegionId in region.AdjacentRegionIds)
			{
				Region item = _byId[adjacentRegionId];
				if (!state.ReachableRegions.Contains(item))
				{
					frontier.Add(item);
				}
			}
		}

		private Region FindStart()
		{
			Region[] regions = _regions;
			foreach (Region region in regions)
			{
				if (region.IsStart)
				{
					return region;
				}
			}
			return null;
		}
	}
	public class RoomGapComponent
	{
		public List<string> Rooms { get; } = new List<string>();

		public List<string> RegionIds { get; } = new List<string>();

		public int SlotCount { get; set; }

		public int Count => Rooms.Count;
	}
	public class RoomGapSet
	{
		private static readonly string[] EmptyRooms = new string[0];

		public RoomGraph RoomGraph { get; }

		public IReadOnlyList<RoomGapComponent> OrphanComponents { get; }

		public IReadOnlyList<string> OrphanRoomIds { get; }

		public IReadOnlyList<string> OmittedRoomIds { get; }

		public IReadOnlyList<string> GapRoomIds { get; }

		public IReadOnlyDictionary<string, int> RoomSlotCounts { get; }

		public int OrphanRoomCount => OrphanRoomIds.Count;

		public int OmittedRoomCount => OmittedRoomIds.Count;

		public int ExemptRoomCount => GapRoomIds.Count;

		public int OrphanSlotCount { get; }

		public int OmittedSlotCount { get; }

		public int ExemptSlotCount { get; }

		public bool IsEmpty => GapRoomIds.Count == 0;

		private RoomGapSet(RoomGraph graph, IReadOnlyList<RoomGapComponent> orphanComponents, IReadOnlyList<string> orphanRooms, IReadOnlyList<string> omittedRooms, IReadOnlyDictionary<string, int> slotCounts, int orphanSlotCount, int omittedSlotCount)
		{
			RoomGraph = graph;
			OrphanComponents = orphanComponents;
			OrphanRoomIds = orphanRooms;
			OmittedRoomIds = omittedRooms;
			RoomSlotCounts = slotCounts;
			List<string> list = new List<string>(orphanRooms);
			HashSet<string> hashSet = new HashSet<string>(orphanRooms, StringComparer.Ordinal);
			foreach (string omittedRoom in omittedRooms)
			{
				if (hashSet.Add(omittedRoom))
				{
					list.Add(omittedRoom);
				}
			}
			list.Sort(StringComparer.Ordinal);
			GapRoomIds = list;
			OrphanSlotCount = orphanSlotCount;
			OmittedSlotCount = omittedSlotCount;
			ExemptSlotCount = orphanSlotCount + omittedSlotCount;
		}

		public bool IsGapRoom(string roomId)
		{
			if (roomId == null || GapRoomIds.Count == 0)
			{
				return false;
			}
			int num = 0;
			int num2 = GapRoomIds.Count - 1;
			while (num <= num2)
			{
				int num3 = num + (num2 - num) / 2;
				int num4 = string.CompareOrdinal(roomId, GapRoomIds[num3]);
				if (num4 == 0)
				{
					return true;
				}
				if (num4 < 0)
				{
					num2 = num3 - 1;
				}
				else
				{
					num = num3 + 1;
				}
			}
			return false;
		}

		public int SlotCountOf(string roomId)
		{
			if (roomId == null || !RoomSlotCounts.TryGetValue(roomId, out var value))
			{
				return 0;
			}
			return value;
		}

		public static RoomGapSet Compute(RoomGraph graph, Region[] regions, IReadOnlyCollection<ItemSlot> slots)
		{
			if (graph == null)
			{
				return null;
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			if (slots != null)
			{
				foreach (ItemSlot slot in slots)
				{
					if (slot != null && !string.IsNullOrEmpty(slot.RoomId))
					{
						hashSet.Add(slot.RoomId);
						dictionary.TryGetValue(slot.RoomId, out var value);
						dictionary[slot.RoomId] = value + 1;
					}
				}
			}
			List<RoomGapComponent> list = new List<RoomGapComponent>();
			int num = 0;
			IReadOnlyList<string> orphanRoomIds = graph.OrphanRoomIds;
			foreach (RoomComponent component in graph.Components)
			{
				if (component.IsValid)
				{
					continue;
				}
				RoomGapComponent roomGapComponent = new RoomGapComponent();
				HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal);
				foreach (string room in component.Rooms)
				{
					roomGapComponent.Rooms.Add(room);
					if (dictionary.TryGetValue(room, out var value2))
					{
						roomGapComponent.SlotCount += value2;
					}
					if (graph.RoomToRegion.TryGetValue(room, out var value3))
					{
						hashSet2.Add(value3);
					}
				}
				roomGapComponent.RegionIds.AddRange(hashSet2);
				roomGapComponent.RegionIds.Sort(StringComparer.Ordinal);
				num += roomGapComponent.SlotCount;
				list.Add(roomGapComponent);
			}
			List<string> list2 = new List<string>();
			int num2 = 0;
			if (slots != null && hashSet.Count > 0)
			{
				HashSet<string> hashSet3 = new HashSet<string>(StringComparer.Ordinal);
				if (!string.IsNullOrEmpty(graph.StartRoomId))
				{
					hashSet3.Add(graph.StartRoomId);
				}
				foreach (string item in RoomGraph.DreamRegionRooms(regions, graph))
				{
					hashSet3.Add(item);
				}
				foreach (string item2 in hashSet)
				{
					if (!graph.Adjacency.ContainsKey(item2) && !hashSet3.Contains(item2))
					{
						list2.Add(item2);
						if (dictionary.TryGetValue(item2, out var value4))
						{
							num2 += value4;
						}
					}
				}
				list2.Sort(StringComparer.Ordinal);
			}
			HashSet<string> hashSet4 = new HashSet<string>(orphanRoomIds, StringComparer.Ordinal);
			foreach (string item3 in list2)
			{
				hashSet4.Add(item3);
			}
			Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.Ordinal);
			foreach (KeyValuePair<string, int> item4 in dictionary)
			{
				if (hashSet4.Contains(item4.Key))
				{
					dictionary2[item4.Key] = item4.Value;
				}
			}
			IReadOnlyList<string> omittedRooms;
			if (list2.Count <= 0)
			{
				IReadOnlyList<string> emptyRooms = EmptyRooms;
				omittedRooms = emptyRooms;
			}
			else
			{
				IReadOnlyList<string> emptyRooms = list2;
				omittedRooms = emptyRooms;
			}
			return new RoomGapSet(graph, list, orphanRoomIds, omittedRooms, dictionary2, num, num2);
		}
	}
	public static class RoomGapReport
	{
		private static bool _warned;

		public static bool Warned => _warned;

		public static void Reset()
		{
			_warned = false;
		}

		public static void WarnOnce(RoomGapSet gaps)
		{
			if (gaps == null || _warned)
			{
				return;
			}
			_warned = true;
			if (gaps.IsEmpty)
			{
				Console.WriteLine("[RoomPrecision] 数据缺口核验:无缺口房间,房间精度按全房间严格判定。");
				return;
			}
			Console.WriteLine("[RoomPrecision] 数据缺口豁免:孤儿分量 " + gaps.OrphanComponents.Count + " 组/共 " + gaps.OrphanRoomCount + " 房;缺节点 " + gaps.OmittedRoomCount + " 房/" + gaps.OmittedSlotCount + " 点位;合计豁免 " + gaps.ExemptRoomCount + " 房/" + gaps.ExemptSlotCount + " 点位");
			for (int i = 0; i < gaps.OrphanComponents.Count; i++)
			{
				RoomGapComponent roomGapComponent = gaps.OrphanComponents[i];
				Console.WriteLine("[RoomPrecision]   孤儿分量 #" + (i + 1) + ":" + roomGapComponent.Count + " 房/" + roomGapComponent.SlotCount + " 点位,区域=[" + string.Join(",", roomGapComponent.RegionIds) + "]");
				Console.WriteLine("[RoomPrecision]     房间=" + Describe(gaps, roomGapComponent.Rooms));
			}
			Console.WriteLine("[RoomPrecision]   缺节点房间=" + Describe(gaps, gaps.OmittedRoomIds));
			Console.WriteLine("[RoomPrecision]   说明:以上房间在 场景连接.txt 中缺边/缺节点,房间精度下恒不可达;死种评定豁免(不计死种),但放置可达性不放宽——放置器照常不向这些房间的点位投放物品。");
		}

		private static string Describe(RoomGapSet gaps, IReadOnlyList<string> rooms)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < rooms.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(rooms[i]);
				int num = gaps.SlotCountOf(rooms[i]);
				if (num > 0)
				{
					stringBuilder.Append('(').Append(num).Append("点位)");
				}
			}
			return stringBuilder.ToString();
		}
	}
	public static class RoomGraphBuilder
	{
		private const string DynamicPlaceholder = "[dynamic]";

		internal const string StartRegionId = "Tut";

		public static RoomGraph Build(string[] lines, PrefixResolver resolver, Region[] regions = null)
		{
			return Build((IEnumerable<string>)lines, resolver, regions);
		}

		public static RoomGraph Build(IEnumerable<string> lines, PrefixResolver resolver, Region[] regions = null)
		{
			RoomGraph roomGraph = new RoomGraph();
			if (lines == null)
			{
				return roomGraph;
			}
			HashSet<string> seen = new HashSet<string>(StringComparer.Ordinal);
			foreach (string line in lines)
			{
				if (line == null)
				{
					continue;
				}
				string text = line.Trim();
				if (text.Length == 0 || text.StartsWith("#"))
				{
					continue;
				}
				string[] array = text.Split(new char[1] { '|' });
				if (array.Length < 3)
				{
					continue;
				}
				string text2 = array[0].Trim();
				string text3 = array[2].Trim();
				if (text2.Length != 0 && text3.Length != 0)
				{
					Map(roomGraph, seen, text2, resolver);
					Map(roomGraph, seen, text3, resolver);
					if (!(text2 == "[dynamic]") && !(text3 == "[dynamic]") && !(text2 == text3))
					{
						AddEdge(roomGraph, text2, text3);
						AddEdge(roomGraph, text3, text2);
					}
				}
			}
			ResolveStartRoom(roomGraph);
			roomGraph.DeclareAlwaysReachableRooms(RoomGraph.DreamRegionRooms(regions, roomGraph));
			return roomGraph;
		}

		private static void Map(RoomGraph graph, HashSet<string> seen, string scene, PrefixResolver resolver)
		{
			if (!seen.Add(scene))
			{
				return;
			}
			Region region = resolver?.Resolve(scene);
			if (region == null)
			{
				if (!graph.UnmappedScenes.Contains(scene))
				{
					graph.UnmappedScenes.Add(scene);
				}
			}
			else
			{
				graph.RoomToRegion[scene] = region.Id;
			}
		}

		private static void AddEdge(RoomGraph graph, string a, string b)
		{
			if (!graph.Adjacency.TryGetValue(a, out var value))
			{
				value = new HashSet<string>(StringComparer.Ordinal);
				graph.Adjacency[a] = value;
			}
			value.Add(b);
		}

		private static void ResolveStartRoom(RoomGraph graph)
		{
			if (!graph.Adjacency.ContainsKey(graph.StartRoomId))
			{
				string text = FirstRoomOfRegion(graph, "Tut");
				if (text == null)
				{
					Console.WriteLine("[RoomGraph] start-fallback failed: 图内无 Tut 区域房间,StartRoomId 保持 " + graph.StartRoomId);
					return;
				}
				Console.WriteLine("[RoomGraph] start-fallback: " + graph.StartRoomId + " 不在场景连接图中,回退到 Tut 区域房间 " + text);
				graph.StartRoomId = text;
			}
		}

		internal static string FirstRoomOfRegion(RoomGraph graph, string regionId)
		{
			string text = null;
			foreach (KeyValuePair<string, string> item in graph.RoomToRegion)
			{
				if (string.Equals(item.Value, regionId, StringComparison.Ordinal) && (text == null || string.CompareOrdinal(item.Key, text) < 0))
				{
					text = item.Key;
				}
			}
			return text;
		}
	}
	public static class RoomReachability
	{
		private const int MaxSteps = 1000;

		private static readonly ConditionalWeakTable<RoomGraph, RoomTopology> Cache = new ConditionalWeakTable<RoomGraph, RoomTopology>();

		public static ReachabilityResult Compute(IReadOnlyDictionary<ItemSlot, Item> assignment, List<ItemSlot> allSlots, RoomGraph roomGraph, Region[] regions, bool fullRandomMode, IReadOnlyList<Item> grants = null)
		{
			PlayerState playerState = PlayerState.WithStartingAbilities(fullRandomMode);
			ReachabilityResult reachabilityResult = new ReachabilityResult
			{
				State = playerState,
				RoomMode = true
			};
			if (roomGraph == null)
			{
				return reachabilityResult;
			}
			if (assignment == null)
			{
				assignment = new Dictionary<ItemSlot, Item>();
			}
			RoomTopology roomTopology = Topology(roomGraph, regions);
			playerState.ReachableRooms = roomTopology.ReachableRooms;
			playerState.ReachableRegions.UnionWith(roomTopology.ReachableRegionObjects);
			reachabilityResult.ReachedRoomIds.AddRange(roomTopology.ReachedRoomIds);
			reachabilityResult.UnreachedRoomIds.AddRange(roomTopology.UnreachedRoomIds);
			reachabilityResult.ReachedRegionIds.AddRange(roomTopology.ReachedRegionIds);
			reachabilityResult.UnreachedRegionIds.AddRange(roomTopology.UnreachedRegionIds);
			if (grants != null)
			{
				foreach (Item grant in grants)
				{
					ReachabilityAnalyzer.ApplyItem(playerState, grant);
				}
			}
			foreach (KeyValuePair<ItemSlot, Item> item in assignment)
			{
				ItemSlot key = item.Key;
				if (IsSlotReachable(key, roomGraph, roomTopology) && (key.AccessGate == null || GateEvaluator.Satisfied(key.AccessGate, playerState)))
				{
					ReachabilityAnalyzer.ApplyItem(playerState, item.Value);
				}
			}
			foreach (KeyValuePair<ItemSlot, Item> item2 in assignment)
			{
				ItemSlot key2 = item2.Key;
				if (key2.AccessGate != null && IsSlotReachable(key2, roomGraph, roomTopology) && !GateEvaluator.Satisfied(key2.AccessGate, playerState))
				{
					reachabilityResult.BlockedSlotIds.Add(key2.Id ?? key2.SourceKey ?? "?");
				}
			}
			reachabilityResult.StepCount = roomTopology.Steps;
			return reachabilityResult;
		}

		public static bool IsSlotReachable(ItemSlot slot, RoomGraph roomGraph, RoomTopology topo)
		{
			if (slot == null)
			{
				return false;
			}
			if (!string.IsNullOrEmpty(slot.RoomId))
			{
				return topo.ReachableRooms.Contains(slot.RoomId);
			}
			if (slot.Region == null)
			{
				return false;
			}
			return topo.ReachableRegionIds.Contains(slot.Region.Id);
		}

		public static RoomTopology Topology(RoomGraph roomGraph, Region[] regions)
		{
			return Cache.GetValue(roomGraph, (RoomGraph g) => BuildTopology(g, regions));
		}

		private static RoomTopology BuildTopology(RoomGraph roomGraph, Region[] regions)
		{
			HashSet<string> hashSet = SeedRooms(roomGraph, regions);
			List<string> list = new List<string>(hashSet);
			int num = 0;
			while (list.Count > 0 && num < 1000)
			{
				List<string> list2 = new List<string>();
				foreach (string item in list)
				{
					if (!roomGraph.Adjacency.TryGetValue(item, out var value))
					{
						continue;
					}
					foreach (string item2 in value)
					{
						if (hashSet.Add(item2))
						{
							list2.Add(item2);
						}
					}
				}
				list = list2;
				num++;
			}
			RoomTopology roomTopology = new RoomTopology
			{
				Steps = num
			};
			List<string> list3 = new List<string>(roomGraph.Adjacency.Keys);
			list3.Sort(StringComparer.Ordinal);
			foreach (string item3 in list3)
			{
				if (hashSet.Contains(item3))
				{
					roomTopology.ReachedRoomIds.Add(item3);
				}
				else
				{
					roomTopology.UnreachedRoomIds.Add(item3);
				}
			}
			foreach (string item4 in hashSet)
			{
				if (roomGraph.Adjacency.ContainsKey(item4))
				{
					roomTopology.ReachableRooms.Add(item4);
				}
			}
			HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal);
			foreach (string reachedRoomId in roomTopology.ReachedRoomIds)
			{
				if (roomGraph.RoomToRegion.TryGetValue(reachedRoomId, out var value2))
				{
					hashSet2.Add(value2);
				}
			}
			if (regions != null)
			{
				foreach (Region region in regions)
				{
					if (region != null)
					{
						if (hashSet2.Contains(region.Id))
						{
							roomTopology.ReachedRegionIds.Add(region.Id);
							roomTopology.ReachableRegionObjects.Add(region);
						}
						else
						{
							roomTopology.UnreachedRegionIds.Add(region.Id);
						}
					}
				}
			}
			else
			{
				List<string> list4 = new List<string>(hashSet2);
				list4.Sort(StringComparer.Ordinal);
				foreach (string item5 in list4)
				{
					roomTopology.ReachedRegionIds.Add(item5);
				}
			}
			foreach (string item6 in hashSet2)
			{
				roomTopology.ReachableRegionIds.Add(item6);
			}
			return roomTopology;
		}

		private static HashSet<string> SeedRooms(RoomGraph roomGraph, Region[] regions)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			if (!string.IsNullOrEmpty(roomGraph.StartRoomId))
			{
				hashSet.Add(roomGraph.StartRoomId);
			}
			HashSet<string> hashSet2 = new HashSet<string>(StringComparer.Ordinal);
			if (regions != null)
			{
				foreach (Region region in regions)
				{
					if (region != null && region.IsDream)
					{
						hashSet2.Add(region.Id);
					}
				}
			}
			if (hashSet2.Count == 0)
			{
				return hashSet;
			}
			foreach (KeyValuePair<string, string> item in roomGraph.RoomToRegion)
			{
				if (hashSet2.Contains(item.Value))
				{
					hashSet.Add(item.Key);
				}
			}
			return hashSet;
		}
	}
	public class RoomTopology
	{
		public int Steps { get; internal set; }

		public HashSet<string> ReachableRooms { get; } = new HashSet<string>(StringComparer.Ordinal);

		public HashSet<string> ReachableRegionIds { get; } = new HashSet<string>(StringComparer.Ordinal);

		public List<Region> ReachableRegionObjects { get; } = new List<Region>();

		public List<string> ReachedRoomIds { get; } = new List<string>();

		public List<string> UnreachedRoomIds { get; } = new List<string>();

		public List<string> ReachedRegionIds { get; } = new List<string>();

		public List<string> UnreachedRegionIds { get; } = new List<string>();
	}
	public class SceneGraphBuilder
	{
		private readonly Region[] _regions;

		private readonly PrefixResolver _resolver;

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

		public IReadOnlyDictionary<string, string> UnmappedScenes => _unmappedScenes;

		public SceneGraphBuilder(Region[] regions)
		{
			_regions = regions;
			_resolver = new PrefixResolver(regions);
		}

		public void Build(string sceneConnectionPath)
		{
			Build(File.ReadAllLines(sceneConnectionPath));
		}

		public void Build(IEnumerable<string> lines)
		{
			Region[] regions = _regions;
			for (int i = 0; i < regions.Length; i++)
			{
				regions[i].AdjacentRegionIds.Clear();
			}
			foreach (string line in lines)
			{
				string text = line.Trim();
				if (text.Length == 0 || text.StartsWith("#"))
				{
					continue;
				}
				string[] array = text.Split(new char[1] { '|' });
				if (array.Length < 4)
				{
					continue;
				}
				string text2 = array[0].Trim();
				string text3 = array[2].Trim();
				if (!(text2 == "[dynamic]") && !(text3 == "[dynamic]"))
				{
					Region region = Resolve(text2);
					Region region2 = Resolve(text3);
					if (region != null && region2 != null && region != region2)
					{
						AddEdge(region, region2);
						AddEdge(region2, region);
					}
				}
			}
		}

		private Region Resolve(string sceneName)
		{
			Region region = _resolver.Resolve(sceneName);
			if (region != null)
			{
				return region;
			}
			string key = SceneKey(sceneName);
			if (!_unmappedScenes.ContainsKey(key))
			{
				_unmappedScenes[key] = sceneName;
			}
			return null;
		}

		public static string SceneKey(string sceneName)
		{
			int num = sceneName.IndexOf('_');
			if (num >= 0)
			{
				return sceneName.Substring(0, num);
			}
			return sceneName;
		}

		private static void AddEdge(Region a, Region b)
		{
			if (!a.AdjacentRegionIds.Contains(b.Id))
			{
				a.AdjacentRegionIds.Add(b.Id);
			}
		}
	}
	public class SpherePlacement
	{
		private readonly Region[] _regions;

		private readonly ReachabilityAnalyzer _analyzer;

		public bool RoomPrecision => _analyzer.RoomPrecision;

		private string ScopeLabel
		{
			get
			{
				if (!RoomPrecision)
				{
					return "可达区域";
				}
				return "可达房间";
			}
		}

		private int ScopeTotal
		{
			get
			{
				if (!RoomPrecision)
				{
					return _regions.Length;
				}
				if (_analyzer.RoomGraph == null)
				{
					return 0;
				}
				return _analyzer.RoomGraph.RoomCount;
			}
		}

		public string LastFailureReason { get; private set; }

		public SpherePlacement(Region[] regions, RoomGraph roomGraph = null)
		{
			_regions = regions;
			_analyzer = new ReachabilityAnalyzer(regions, roomGraph);
		}

		public bool TryPlace(List<ItemSlot> slots, List<Item> pool, out Dictionary<ItemSlot, Item> assignment, bool fullRandomMode = false, Random rng = null)
		{
			LastFailureReason = null;
			if (slots == null || pool == null)
			{
				assignment = null;
				LastFailureReason = "槽位或物品池为空";
				return false;
			}
			if (rng == null)
			{
				rng = new Random();
			}
			_analyzer.AllSlots = slots;
			Dictionary<ItemSlot, Item> dictionary = new Dictionary<ItemSlot, Item>();
			foreach (KeyValuePair<ItemSlot, Item> item in new FixedAssignments(_regions).All)
			{
				dictionary[PlacementSimulator.MatchFixedSlot(slots, item.Key) ?? item.Key] = item.Value;
			}
			List<ItemSlot> list = new List<ItemSlot>();
			foreach (ItemSlot slot in slots)
			{
				if (!slot.IsFixed && !dictionary.ContainsKey(slot))
				{
					list.Add(slot);
				}
			}
			List<Item> list2 = new List<Item>(pool);
			int num = slots.Count * 2 + 1;
			while (list2.Count > 0)
			{
				if (--num < 0)
				{
					assignment = dictionary;
					LastFailureReason = "轮数上限,剩余物品 " + list2.Count;
					return false;
				}
				PlayerState state = _analyzer.Compute(dictionary, fullRandomMode).State;
				List<ItemSlot> list3 = AvailableSlots(list, dictionary, state, RoomPrecision);
				if (list3.Count == 0)
				{
					assignment = dictionary;
					LastFailureReason = "无可取槽,剩余物品 " + list2.Count + "," + ScopeLabel + " " + ReachabilityCount(state) + "/" + ScopeTotal;
					return false;
				}
				List<Item> list4 = PriorityOrder(list2, rng);
				List<Item> list5 = new List<Item>();
				bool flag = false;
				foreach (Item item2 in list4)
				{
					list5.Add(item2);
					if (GrantCount(list5, dictionary, list, fullRandomMode) > list3.Count)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					if (list2.Count > list3.Count)
					{
						assignment = dictionary;
						LastFailureReason = "收尾槽位不足:剩余 " + list2.Count + " > 可取 " + list3.Count;
						return false;
					}
					foreach (Item item3 in list2)
					{
						ItemSlot itemSlot = TakeSlot(list3, rng);
						dictionary[itemSlot] = item3;
						list.Remove(itemSlot);
					}
					list2.Clear();
					continue;
				}
				List<Item> list6 = new List<Item>();
				for (int num2 = list5.Count - 1; num2 >= 0; num2--)
				{
					List<Item> list7 = new List<Item>(list5.Take(num2));
					list7.AddRange(list6);
					if (GrantCount(list7, dictionary, list, fullRandomMode) < list3.Count + 1)
					{
						list6.Add(list5[num2]);
					}
				}
				list6.Reverse();
				if (list6.Count == 0)
				{
					list6.Add(list5[list5.Count - 1]);
				}
				PlayerState state2 = _analyzer.Compute(dictionary, fullRandomMode, list6).State;
				List<ItemSlot> list8 = AvailableSlots(list, dictionary, state2, RoomPrecision);
				HashSet<ItemSlot> baseSet = new HashSet<ItemSlot>(list3);
				List<ItemSlot> list9 = list8.Where((ItemSlot s) => !baseSet.Contains(s)).ToList();
				List<ItemSlot> list10 = ((list9.Count > 0) ? list9 : new List<ItemSlot>(list8));
				foreach (ItemSlot item4 in list3)
				{
					if (!list10.Contains(item4))
					{
						list10.Add(item4);
					}
				}
				Shuffle(rng, list6);
				foreach (Item item5 in list6)
				{
					List<Item> list11 = new List<Item>();
					foreach (Item item6 in list6)
					{
						if (item6 != item5)
						{
							list11.Add(item6);
						}
					}
					PlayerState state3 = _analyzer.Compute(dictionary, fullRandomMode, list11).State;
					List<ItemSlot> list12 = AvailableSlots(list, dictionary, state3, RoomPrecision);
					List<ItemSlot> list13 = new List<ItemSlot>();
					foreach (ItemSlot item7 in list10)
					{
						if (list12.Contains(item7))
						{
							list13.Add(item7);
						}
					}
					if (list13.Count == 0)
					{
						assignment = dictionary;
						LastFailureReason = "自锁无可落点:" + item5?.ToString() + "(其候选槽均需自身授权)";
						return false;
					}
					ItemSlot itemSlot2 = TakeSlot(list13, rng);
					dictionary[itemSlot2] = item5;
					list2.Remove(item5);
					list10.Remove(itemSlot2);
				}
			}
			assignment = dictionary;
			LastFailureReason = null;
			return true;
		}

		public static List<ItemSlot> AvailableSlots(List<ItemSlot> open, IReadOnlyDictionary<ItemSlot, Item> working, PlayerState state, bool roomPrecision = false)
		{
			List<ItemSlot> list = new List<ItemSlot>();
			foreach (ItemSlot item in open)
			{
				if (working.ContainsKey(item))
				{
					continue;
				}
				if (roomPrecision && !string.IsNullOrEmpty(item.RoomId))
				{
					if (!state.ReachableRooms.Contains(item.RoomId))
					{
						continue;
					}
				}
				else if (item.Region == null || !state.ReachableRegions.Contains(item.Region))
				{
					continue;
				}
				if (item.AccessGate == null || GateEvaluator.Satisfied(item.AccessGate, state))
				{
					list.Add(item);
				}
			}
			return list;
		}

		private int GrantCount(List<Item> grants, Dictionary<ItemSlot, Item> working, List<ItemSlot> open, bool fullRandomMode)
		{
			PlayerState state = _analyzer.Compute(working, fullRandomMode, grants).State;
			return AvailableSlots(open, working, state, RoomPrecision).Count;
		}

		private static List<Item> PriorityOrder(List<Item> unplaced, Random rng)
		{
			SortedList<int, List<Item>> sortedList = new SortedList<int, List<Item>>();
			foreach (Item item in unplaced)
			{
				if (!sortedList.TryGetValue(item.Priority, out var value))
				{
					value = new List<Item>();
					sortedList[item.Priority] = value;
				}
				value.Add(item);
			}
			List<Item> list = new List<Item>();
			foreach (KeyValuePair<int, List<Item>> item2 in sortedList)
			{
				list.AddRange(Shuffled(rng, item2.Value));
			}
			return list;
		}

		private static int ReachabilityCount(PlayerState state)
		{
			if (state.ReachableRooms.Count <= 0)
			{
				return state.ReachableRegions.Count;
			}
			return state.ReachableRooms.Count;
		}

		private static ItemSlot TakeSlot(List<ItemSlot> list, Random rng)
		{
			int index = rng.Next(list.Count);
			ItemSlot result = list[index];
			list.RemoveAt(index);
			return result;
		}

		internal static List<T> Shuffled<T>(Random rng, List<T> src)
		{
			List<T> list = new List<T>(src);
			for (int num = list.Count - 1; num > 0; num--)
			{
				int num2 = rng.Next(num + 1);
				List<T> list2 = list;
				int index = num;
				List<T> list3 = list;
				int index2 = num2;
				T value = list[num2];
				T value2 = list[num];
				list2[index] = value;
				list3[index2] = value2;
			}
			return list;
		}

		internal static void Shuffle<T>(Random rng, List<T> list)
		{
			for (int num = list.Count - 1; num > 0; num--)
			{
				int num2 = rng.Next(num + 1);
				int index = num;
				int index2 = num2;
				T value = list[num2];
				T value2 = list[num];
				list[index] = value;
				list[index2] = value2;
			}
		}
	}
}
namespace PharloomCore.Data
{
	public static class AbilitiesData
	{
		public static readonly Dictionary<AbilityId, Ability> All = Build();

		private static Dictionary<AbilityId, Ability> Build()
		{
			Dictionary<AbilityId, Ability> dictionary = new Dictionary<AbilityId, Ability>();
			Add(dictionary, AbilityId.NeedleThrow, "hasNeedleThrow", "丝之矛", AbilityCategory.Combat);
			Add(dictionary, AbilityId.Dash, "hasDash", "疾风步", AbilityCategory.Movement);
			Add(dictionary, AbilityId.DoubleJump, "hasDoubleJump", "雪绒披风(二段跳)", AbilityCategory.Movement);
			Add(dictionary, AbilityId.Brolly, "hasBrolly", "流浪者披风(斗篷)", AbilityCategory.Movement);
			Add(dictionary, AbilityId.SuperJump, "hasSuperJump", "灵丝升腾(上冲)", AbilityCategory.Movement);
			Add(dictionary, AbilityId.Walljump, "hasWalljump", "蛛攀术(爬墙)", AbilityCategory.Movement);
			Add(dictionary, AbilityId.HarpoonDash, "hasHarpoonDash", "飞针", AbilityCategory.Movement);
			Add(dictionary, AbilityId.SilkCharge, "hasSilkCharge", "丝刃标", AbilityCategory.Spell);
			Add(dictionary, AbilityId.ThreadSphere, "hasThreadSphere", "灵丝风暴", AbilityCategory.Spell);
			Add(dictionary, AbilityId.SilkBomb, "hasSilkBomb", "符文之怒", AbilityCategory.Spell);
			Add(dictionary, AbilityId.SilkBossNeedle, "hasSilkBossNeedle", "苍白之爪", AbilityCategory.Spell);
			Add(dictionary, AbilityId.ChargeSlash, "hasChargeSlash", "蓄力斩", AbilityCategory.Spell);
			Add(dictionary, AbilityId.Parry, "hasParry", "格挡", AbilityCategory.Combat);
			Add(dictionary, AbilityId.Needolin, "hasNeedolin", "丝忆弦针", AbilityCategory.Music);
			Add(dictionary, AbilityId.EvaHeal, "HasSeenEvaHeal", "风铃摇", AbilityCategory.Music);
			Add(dictionary, AbilityId.NeedolinMemory, "hasNeedolinMemoryPowerup", "深邃挽歌", AbilityCategory.Music);
			Add(dictionary, AbilityId.Teleport, "hasFastTravelTeleport", "幻兽歌", AbilityCategory.Music);
			Add(dictionary, AbilityId.MelodyConductor, "HasMelodyConductor", "旋律·指挥", AbilityCategory.Music);
			Add(dictionary, AbilityId.MelodyLibrarian, "HasMelodyLibrarian", "旋律·司书", AbilityCategory.Music);
			Add(dictionary, AbilityId.MelodyArchitect, "HasMelodyArchitect", "旋律·建筑师", AbilityCategory.Music);
			Add(dictionary, AbilityId.SilkHeart, "SilkHeart", "丝之心", AbilityCategory.Music);
			Add(dictionary, AbilityId.Journal, "Journal", "猎人日志", AbilityCategory.Combat);
			Add(dictionary, AbilityId.SilkDash, "hasSilkDash", "丝冲", AbilityCategory.Movement);
			Add(dictionary, AbilityId.AttackUp, "perm:upward", "上劈权限", AbilityCategory.Combat);
			Add(dictionary, AbilityId.AttackLeft, "perm:left", "左劈权限", AbilityCategory.Combat);
			Add(dictionary, AbilityId.AttackRight, "perm:right", "右劈权限", AbilityCategory.Combat);
			Add(dictionary, AbilityId.Heal, "perm:heal", "回血权限", AbilityCategory.Combat);
			Add(dictionary, AbilityId.Swim, "Swim", "游泳", AbilityCategory.Movement);
			Add(dictionary, AbilityId.ShamanCrest, "chapelClosed_shaman", "萨满纹章", AbilityCategory.Movement);
			Add(dictionary, AbilityId.ArchitectChargeSlash, "hasChargeSlash", "建筑师蓄力斩", AbilityCategory.Combat);
			return dictionary;
		}

		private static void Add(Dictionary<AbilityId, Ability> d, AbilityId id, string key, string name, AbilityCategory cat)
		{
			d[id] = new Ability
			{
				Id = id,
				Key = key,
				DisplayName = name,
				Category = cat
			};
		}
	}
	public static class AbilityAlias
	{
		private static readonly Dictionary<string, AbilityId> Map = new Dictionary<string, AbilityId>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"二段跳",
				AbilityId.DoubleJump
			},
			{
				"二段",
				AbilityId.DoubleJump
			},
			{
				"爬墙",
				AbilityId.Walljump
			},
			{
				"上冲",
				AbilityId.SuperJump
			},
			{
				"上劈",
				AbilityId.SuperJump
			},
			{
				"冲刺",
				AbilityId.Dash
			},
			{
				"疾跑",
				AbilityId.Dash
			},
			{
				"疾风步",
				AbilityId.Dash
			},
			{
				"斗篷",
				AbilityId.Brolly
			},
			{
				"披风",
				AbilityId.Brolly
			},
			{
				"飞针",
				AbilityId.HarpoonDash
			},
			{
				"丝冲",
				AbilityId.SilkDash
			},
			{
				"丝蓄",
				AbilityId.SilkCharge
			},
			{
				"蓄力丝冲",
				AbilityId.SilkCharge
			},
			{
				"丝之矛",
				AbilityId.NeedleThrow
			},
			{
				"灵丝风暴",
				AbilityId.ThreadSphere
			},
			{
				"丝风暴",
				AbilityId.ThreadSphere
			},
			{
				"符文之怒",
				AbilityId.SilkBomb
			},
			{
				"苍白之爪",
				AbilityId.SilkBossNeedle
			},
			{
				"蓄力斩",
				AbilityId.ChargeSlash
			},
			{
				"格挡",
				AbilityId.Parry
			},
			{
				"丝忆",
				AbilityId.Needolin
			},
			{
				"丝忆弦针",
				AbilityId.Needolin
			},
			{
				"琴弦乐",
				AbilityId.Needolin
			},
			{
				"风铃摇",
				AbilityId.EvaHeal
			},
			{
				"深邃挽歌",
				AbilityId.NeedolinMemory
			},
			{
				"挽歌",
				AbilityId.NeedolinMemory
			},
			{
				"幻兽歌",
				AbilityId.Teleport
			},
			{
				"传送",
				AbilityId.Teleport
			},
			{
				"游泳",
				AbilityId.Swim
			},
			{
				"萨满纹章",
				AbilityId.ShamanCrest
			},
			{
				"建筑师蓄力斩",
				AbilityId.ArchitectChargeSlash
			}
		};

		public static bool TryResolve(string alias, out AbilityId id)
		{
			if (alias != null && Map.TryGetValue(alias.Trim(), out id))
			{
				return true;
			}
			id = AbilityId.NeedleThrow;
			return false;
		}
	}
	public static class ItemTiers
	{
		private static readonly Dictionary<string, int> Tiers = new Dictionary<string, int>
		{
			{ "kind:item_skill", 3 },
			{ "kind:item_relic", 4 },
			{ "kind:item_other", 4 },
			{ "kind:item_simplekey", 2 },
			{ "ability:hasNeedleThrow", 2 },
			{ "ability:hasThreadSphere", 3 },
			{ "ability:hasSilkCharge", 2 },
			{ "ability:hasSilkBomb", 3 },
			{ "ability:hasSilkBossNeedle", 3 },
			{ "ability:hasParry", 3 },
			{ "ability:hasHarpoonDash", 1 },
			{ "ability:hasNeedolin", 1 },
			{ "ability:hasDash", 1 },
			{ "ability:hasBrolly", 1 },
			{ "ability:hasDoubleJump", 1 },
			{ "ability:hasChargeSlash", 3 },
			{ "ability:hasSuperJump", 1 },
			{ "ability:hasWalljump", 1 },
			{ "ability:HasSeenEvaHeal", 3 },
			{ "ability:hasNeedolinMemoryPowerup", 2 },
			{ "ability:hasFastTravelTeleport", 4 },
			{ "ability:HasMelodyConductor", 2 },
			{ "ability:HasMelodyLibrarian", 2 },
			{ "ability:HasMelodyArchitect", 2 },
			{ "ability:SilkHeart", 2 },
			{ "ability:Journal", 3 },
			{ "ability:ColdResist", 1 },
			{ "ability:Swim", 1 },
			{ "perm:upward", 2 },
			{ "perm:left", 2 },
			{ "perm:right", 2 },
			{ "perm:heal", 1 },
			{ "perm:hasDash_L", 1 },
			{ "perm:hasDash_R", 1 },
			{ "perm:hasHarpoonDash_L", 1 },
			{ "perm:hasHarpoonDash_R", 1 },
			{ "perm:hasBrolly_L", 1 },
			{ "perm:hasBrolly_R", 1 },
			{ "perm:hasWalljump_L", 1 },
			{ "perm:hasWalljump_R", 1 },
			{ "virt:HeartPiece", 3 },
			{ "virt:SpoolPart", 3 },
			{ "virt:UnlockCrestSlot", 3 },
			{ "virt:ExtraYellowSlot", 2 },
			{ "virt:ExtraBlueSlot", 2 },
			{ "virt:SlabKeyA", 2 },
			{ "virt:SlabKeyB", 2 },
			{ "virt:SlabKeyC", 2 },
			{ "virt:Bellshrines", 3 },
			{ "kind:maps", 4 },
			{ "kind:stations", 1 },
			{ "virt:LoreLog", 4 },
			{ "flea:Rescue", 3 },
			{ "virt:Silk_3", 4 },
			{ "virt:Shards_300", 4 },
			{ "virt:BlueHealth_Random", 4 },
			{ "virt:RandomCoin", 4 },
			{ "virt:FallbackCoin", 0 }
		};

		public static int Resolve(Item item)
		{
			string text = TierKey(item);
			if (text == null)
			{
				return 4;
			}
			if (!Tiers.TryGetValue(text, out var value))
			{
				return 4;
			}
			return value;
		}

		private static string TierKey(Item item)
		{
			switch (item.Kind)
			{
			case ItemKind.Ability:
			{
				if (!AbilitiesData.All.TryGetValue(item.AbilityId, out var value))
				{
					return null;
				}
				if (!value.Key.StartsWith("perm:"))
				{
					return "ability:" + value.Key;
				}
				return value.Key;
			}
			case ItemKind.Permission:
				return "perm:" + item.PermissionId;
			case ItemKind.Cold:
				return "ability:ColdResist";
			case ItemKind.NamedItem:
				return item.ItemName switch
				{
					"SimpleKey" => "kind:item_simplekey", 
					"CrestSocketUnlocker" => "virt:UnlockCrestSlot", 
					"SlabKeyA" => "virt:SlabKeyA", 
					"SlabKeyB" => "virt:SlabKeyB", 
					"SlabKeyC" => "virt:SlabKeyC", 
					_ => null, 
				};
			default:
				return null;
			}
		}
	}
	public static class PermissionsData
	{
		public const bool DefaultSidesSplit = true;

		public static readonly Dictionary<string, Permission> All = Build();

		private static Dictionary<string, Permission> Build()
		{
			Dictionary<string, Permission> dictionary = new Dictionary<string, Permission>();
			Add(dictionary, "Dash", AbilityId.Dash, PermissionSide.Left);
			Add(dictionary, "Dash", AbilityId.Dash, PermissionSide.Right);
			Add(dictionary, "HarpoonDash", AbilityId.HarpoonDash, PermissionSide.Left);
			Add(dictionary, "HarpoonDash", AbilityId.HarpoonDash, PermissionSide.Right);
			Add(dictionary, "Brolly", AbilityId.Brolly, PermissionSide.Left);
			Add(dictionary, "Brolly", AbilityId.Brolly, PermissionSide.Right);
			Add(dictionary, "Walljump", AbilityId.Walljump, PermissionSide.Left);
			Add(dictionary, "Walljump", AbilityId.Walljump, PermissionSide.Right);
			return dictionary;
		}

		private static void Add(Dictionary<string, Permission> d, string id, AbilityId ability, PermissionSide side)
		{
			d[id + "_" + SideMapping.EngineSuffix(side)] = new Permission
			{
				Id = id + "_" + SideMapping.EngineSuffix(side),
				BoundAbility = ability,
				Side = side,
				SidesSplit = true
			};
		}

		private static string SideSuffix(PermissionSide side)
		{
			return SideMapping.EngineSuffix(side);
		}

		public static string FullId(string baseId)
		{
			return baseId + "_Full";
		}

		public static bool IsFull(string id)
		{
			return id.EndsWith("_Full");
		}

		public static string ParseSide(string id, out PermissionSide side)
		{
			side = SideMapping.FromEngineSuffix(id);
			return id.Substring(0, id.Length - 2);
		}
	}
	[DataContract]
	public class PointConditionFile
	{
		[DataMember(Name = "version")]
		public int Version { get; set; }

		[DataMember(Name = "points")]
		public PointConditionData[] Points { get; set; }
	}
	[DataContract]
	public class PointConditionData
	{
		[DataMember(Name = "Type")]
		public string Type { get; set; }

		[DataMember(Name = "Scene")]
		public string Scene { get; set; }

		[DataMember(Name = "Key")]
		public string Key { get; set; }

		[DataMember(Name = "Item")]
		public string Item { get; set; }

		[DataMember(Name = "Vertical")]
		public int Vertical { get; set; }

		[DataMember(Name = "HorizLeft")]
		public int HorizLeft { get; set; }

		[DataMember(Name = "HorizRight")]
		public int HorizRight { get; set; }

		[DataMember(Name = "Cold")]
		public bool Cold { get; set; }

		[DataMember(Name = "ItemRequirement")]
		public string ItemRequirement { get; set; }

		[DataMember(Name = "AbilityRequirement")]
		public string AbilityRequirement { get; set; }

		[DataMember(Name = "Solutions")]
		public List<PointSolutionData> Solutions { get; set; }
	}
	[DataContract]
	public class PointSolutionData
	{
		[DataMember(Name = "Abilities")]
		public List<string> Abilities { get; set; }
	}
	public static class PointConditionLoader
	{
		private static readonly Dictionary<string, string> DirectionPermissionIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "疾跑", "Dash" },
			{ "漂浮", "Brolly" },
			{ "飞针", "HarpoonDash" },
			{ "爬墙", "Walljump" }
		};

		private static readonly Dictionary<string, AbilityId> DirectionAbilities = new Dictionary<string, AbilityId>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"疾跑",
				AbilityId.Dash
			},
			{
				"漂浮",
				AbilityId.Brolly
			},
			{
				"飞针",
				AbilityId.HarpoonDash
			},
			{
				"爬墙",
				AbilityId.Walljump
			}
		};

		private static readonly HashSet<string> LegalItemRequirements = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "SlabKeyA", "SlabKeyB", "SlabKeyC" };

		public static Dictionary<string, Gate> LoadFile(string path)
		{
			if (!File.Exists(path))
			{
				return null;
			}
			return LoadJson(File.ReadAllText(path));
		}

		public static Dictionary<string, Gate> LoadLines(IEnumerable<string> lines)
		{
			if (lines == null)
			{
				return null;
			}
			return LoadJson(string.Join("\n", lines));
		}

		public static Dictionary<string, string> LoadSceneMapFile(string path)
		{
			if (!File.Exists(path))
			{
				return null;
			}
			return LoadSceneMap(File.ReadAllText(path));
		}

		public static Dictionary<string, string> LoadSceneMapLines(IEnumerable<string> lines)
		{
			if (lines == null)
			{
				return null;
			}
			return LoadSceneMap(string.Join("\n", lines));
		}

		private static Dictionary<string, string> LoadSceneMap(string json)
		{
			if (string.IsNullOrWhiteSpace(json))
			{
				return null;
			}
			PointConditionFile pointConditionFile;
			try
			{
				using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
				pointConditionFile = (PointConditionFile)new DataContractJsonSerializer(typeof(PointConditionFile)).ReadObject(stream);
			}
			catch
			{
				return null;
			}
			if (pointConditionFile?.Points == null)
			{
				return null;
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			PointConditionData[] points = pointConditionFile.Points;
			foreach (PointConditionData pointConditionData in points)
			{
				if (pointConditionData != null && !string.IsNullOrEmpty(pointConditionData.Key) && !string.IsNullOrEmpty(pointConditionData.Scene))
				{
					dictionary[pointConditionData.Key.Trim()] = pointConditionData.Scene.Trim();
				}
			}
			if (dictionary.Count <= 0)
			{
				return null;
			}
			return dictionary;
		}

		private static Dictionary<string, Gate> LoadJson(string json)
		{
			if (string.IsNullOrWhiteSpace(json))
			{
				return null;
			}
			PointConditionFile pointConditionFile;
			try
			{
				using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
				pointConditionFile = (PointConditionFile)new DataContractJsonSerializer(typeof(PointConditionFile)).ReadObject(stream);
			}
			catch
			{
				return null;
			}
			if (pointConditionFile?.Points == null)
			{
				return null;
			}
			Dictionary<string, Gate> dictionary = new Dictionary<string, Gate>(StringComparer.Ordinal);
			PointConditionData[] points = pointConditionFile.Points;
			foreach (PointConditionData pointConditionData in points)
			{
				if (pointConditionData != null && !string.IsNullOrEmpty(pointConditionData.Key))
				{
					Gate gate = BuildGate(pointConditionData);
					if (gate != null)
					{
						dictionary[pointConditionData.Key.Trim()] = gate;
					}
				}
			}
			if (dictionary.Count <= 0)
			{
				return null;
			}
			return dictionary;
		}

		private static Gate BuildGate(PointConditionData p)
		{
			List<Gate> list = new List<Gate>();
			if (p.Vertical > 0)
			{
				list.Add(Gate.VerticalGate(p.Vertical));
			}
			if (p.HorizLeft > 0)
			{
				list.Add(Gate.HorizontalGate(p.HorizLeft, PermissionSide.Left));
			}
			if (p.HorizRight > 0)
			{
				list.Add(Gate.HorizontalGate(p.HorizRight, PermissionSide.Right));
			}
			if (p.Cold)
			{
				list.Add(Gate.ColdGate());
			}
			if (!string.IsNullOrWhiteSpace(p.ItemRequirement) && LegalItemRequirements.Contains(p.ItemRequirement.Trim()))
			{
				list.Add(Gate.ItemGate(p.ItemRequirement.Trim()));
			}
			if (!string.IsNullOrWhiteSpace(p.AbilityRequirement))
			{
				string text = p.AbilityRequirement.Trim();
				AbilityId id;
				if (text == "抗寒")
				{
					list.Add(Gate.ColdGate());
				}
				else if (AbilityAlias.TryResolve(text, out id))
				{
					list.Add(Gate.AbilityGate(id));
				}
			}
			if (p.Solutions != null && p.Solutions.Count > 0)
			{
				List<Gate> list2 = new List<Gate>();
				foreach (PointSolutionData solution in p.Solutions)
				{
					if (solution == null || solution.Abilities == null || solution.Abilities.Count == 0)
					{
						continue;
					}
					List<Gate> list3 = new List<Gate>();
					foreach (string ability in solution.Abilities)
					{
						list3.Add(ResolveSolutionWord(ability));
					}
					list2.Add((list3.Count == 1) ? list3[0] : Gate.And(list3.ToArray()));
				}
				if (list2.Count > 0)
				{
					list.Add((list2.Count == 1) ? list2[0] : Gate.Or(list2.ToArray()));
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			if (list.Count == 1)
			{
				return list[0];
			}
			return Gate.And(list.ToArray());
		}

		private static Gate ResolveSolutionWord(string word)
		{
			if (string.IsNullOrWhiteSpace(word))
			{
				return Gate.NeverGate();
			}
			string text = word.Trim();
			PermissionSide? permissionSide = null;
			int num = text.IndexOf('(');
			if (num > 0 && text.EndsWith(")", StringComparison.Ordinal))
			{
				string text2 = text.Substring(num + 1, text.Length - num - 2).Trim();
				text = text.Substring(0, num).Trim();
				if (text2 == "左")
				{
					permissionSide = PermissionSide.Left;
				}
				else if (text2 == "右")
				{
					permissionSide = PermissionSide.Right;
				}
			}
			if (DirectionPermissionIds.TryGetValue(text, out var value))
			{
				if (permissionSide.HasValue)
				{
					return Gate.PermissionGate(value, permissionSide.Value);
				}
				if (DirectionAbilities.TryGetValue(text, out var value2))
				{
					return Gate.AbilityGate(value2);
				}
			}
			if (AbilityAlias.TryResolve(text, out var id))
			{
				return Gate.AbilityGate(id);
			}
			return Gate.NeverGate();
		}
	}
	public static class RegionsData
	{
		public static readonly Region[] All = Build();

		private static Gate BrollyAny => Gate.Or(Perm("Brolly", PermissionSide.Left), Perm("Brolly", PermissionSide.Right));

		private static Gate WallJumpBoth => Gate.And(Perm("Walljump", PermissionSide.Left), Perm("Walljump", PermissionSide.Right));

		private static Gate HarpoonBoth => Gate.And(Perm("HarpoonDash", PermissionSide.Left), Perm("HarpoonDash", PermissionSide.Right));

		private static Gate Ability(AbilityId id)
		{
			return Gate.AbilityGate(id);
		}

		private static Gate Perm(string baseId, PermissionSide side)
		{
			return Gate.PermissionGate(baseId, side);
		}

		private static Region[] Build()
		{
			List<Region> list = new List<Region>();
			Region region = RegionsData.R("Tut", "苔藓洞穴(起点)", true, "Tut", "Mosstown");
			list.Add(region);
			Region regi

BepInEx/plugins/SilksongItemRandomizer.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using AssetChainFixer;
using Benchwarp.Components;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalEnums;
using GlobalSettings;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using PharloomCore;
using PharloomCore.Data;
using PharloomCore.Model;
using QuestPlaymakerActions;
using SilksongItemRandomizer;
using StartingAbilityPicker;
using TMProOld;
using TeamCherry.Localization;
using TeamCherry.SharedUtils;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.Events;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("SilksongItemRandomizer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SilksongItemRandomizer")]
[assembly: AssemblyTitle("SilksongItemRandomizer")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/YourGitHubUsername/SilksongItemRandomizer")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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 HotkeyHandler : MonoBehaviour
{
	private GUIStyle _tipStyle;

	private GUIStyle _titleBoldStyle;

	private GUIStyle _nameBoldStyle;

	private GUIStyle _hintStyle;

	private GUIStyle _pickBtnStyle;

	private GUIStyle _skipBtnStyle;

	private GUIStyle _smallHintStyle;

	private GUIStyle _noteFieldStyle;

	private GUIStyle _noteBtnStyle;

	private static bool _isChineseCache;

	private List<(string cat, string name)> _currentCandidates = new List<(string, string)>();

	private int _f4MsgCycleIndex;

	private int _f4ComboTier;

	private static readonly (string kind, string evt)[] F4GlowPopupItems = new(string, string)[9]
	{
		("heart", "CORAL"),
		("heart", "FLOWER"),
		("heart", "HUNTER"),
		("heart", "CLOVER"),
		("melody", "CONDUCTOR"),
		("melody", "LIBRARIAN"),
		("melody", "ARCHITECT"),
		("hcombo", "1"),
		("hcombo", "2")
	};

	private int _f4PopupIndex;

	private static bool _f4Toggle;

	private static int _crestPopupIndex;

	private static readonly string[] _testSkillFields = new string[17]
	{
		"hasDash", "hasWalljump", "hasHarpoonDash", "hasNeedolin", "hasSuperJump", "HasSeenEvaHeal", "hasNeedleThrow", "hasThreadSphere", "hasSilkCharge", "hasSilkBomb",
		"hasSilkBossNeedle", "hasParry", "hasBrolly", "hasDoubleJump", "hasChargeSlash", "hasNeedolinMemoryPowerup", "hasFastTravelTeleport"
	};

	private static int _extraSlotTestIndex = 0;

	private static bool _slotDepsLoaded;

	private static int _splitTestIndex = 0;

	private static readonly (string label, string skillField, bool right, bool left)[] DirectionCalibList = new(string, string, bool, bool)[8]
	{
		("冲刺左", "hasDash", false, true),
		("冲刺右", "hasDash", true, false),
		("飞针左", "hasHarpoonDash", false, true),
		("飞针右", "hasHarpoonDash", true, false),
		("漂浮左", "hasBrolly", false, true),
		("漂浮右", "hasBrolly", true, false),
		("壁跳左", "hasWalljump", false, true),
		("壁跳右", "hasWalljump", true, false)
	};

	private int _dirCalibIndex = 0;

	private static int _loreTestIndex = -1;

	private static int _f4SelfGiveIndex = 0;

	private static readonly (string label, string[] keys)[] SpriteSearchGroups = new(string, string[])[21]
	{
		("prompt", new string[1] { "prompt" }),
		("slash", new string[1] { "slash" }),
		("needle", new string[1] { "needle" }),
		("geo", new string[1] { "geo" }),
		("rosary", new string[2] { "rosary", "bead" }),
		("toll", new string[1] { "toll" }),
		("map", new string[1] { "map" }),
		("quest", new string[1] { "quest" }),
		("station", new string[1] { "station" }),
		("bench", new string[1] { "bench" }),
		("bell", new string[1] { "bell" }),
		("shrine", new string[2] { "shrine", "chapel" }),
		("lock", new string[2] { "lock", "door" }),
		("silk", new string[1] { "silk" }),
		("shell", new string[2] { "shell", "shard" }),
		("spool", new string[1] { "spool" }),
		("crest", new string[1] { "crest" }),
		("mask", new string[1] { "mask" }),
		("heart", new string[1] { "heart" }),
		("key", new string[1] { "key" }),
		("memory", new string[2] { "memory", "orb" })
	};

	private static readonly (string cat, string name)[] SpritePickCandidates = new(string, string)[144]
	{
		("prompt", "Cursed_item_prompt"),
		("prompt", "Map_prompt"),
		("prompt", "Tools_prompt"),
		("prompt", "Crest_prompt"),
		("prompt", "Journal_Prompt"),
		("prompt", "Deep_Memory_Prompt"),
		("prompt", "kings_brand_prompt"),
		("prompt", "Wall_Jump_Prompt"),
		("prompt", "Needolin_Prompt"),
		("prompt", "dreamer_mask_prompt"),
		("prompt", "Materium_Prompt"),
		("prompt", "prompt_silkheart"),
		("needle", "T_longneedle"),
		("needle", "S_needle_throw"),
		("needle", "cradle_needle"),
		("needle", "Curse_dark_needle"),
		("needle", "prompt_hornet_needle_throw"),
		("rosary", "I_rosary_icon_clean"),
		("rosary", "I_rosary_icon_big_clean"),
		("rosary", "I_rosary_icon_mid_clean"),
		("rosary", "I_rosary_icon_etched"),
		("rosary", "tiny_icon_rosary"),
		("rosary", "rosary_rock_type_base"),
		("rosary", "T_rosary_magnet"),
		("rosary", "tiny_tool_icon_rosary_cannon"),
		("rosary", "rosary_cache_bell"),
		("toll", "Toll_machine_silk_ration"),
		("toll", "Toll_cap0003"),
		("toll", "Toll_cog0006"),
		("toll", "bellbench_toll_machine"),
		("toll", "bellbench_toll_machine_map"),
		("map", "I_map"),
		("map", "I_map_type_02"),
		("map", "I_quill_and_map"),
		("map", "map_arrow"),
		("map", "No_Map_symbol"),
		("map", "quest_map_icon_round_style"),
		("map", "Shop_map_icon__weavehome"),
		("map", "gramaphone"),
		("quest", "quest_dot_full"),
		("quest", "quest_dot_empty"),
		("quest", "Kill_quest_icon"),
		("quest", "goop_quest_icon"),
		("quest", "hunters_nest_quest_icon"),
		("quest", "Steel_Servant_Quest_marker"),
		("quest", "Mr_Mushroom_quest_notch"),
		("quest", "quest_map_icon_round_style"),
		("station", "pin_stag_station_shop_icon"),
		("station", "pin_tube_station_shop_icon"),
		("station", "pin_stag_station"),
		("station", "pin_tube_station"),
		("bench", "Bench_item_prompt"),
		("bench", "pin_bench_shop_icon"),
		("bench", "pin_bench"),
		("bench", "pin_bench_bell"),
		("bench", "town_bench_lit"),
		("bell", "Hornet_icon_bell_clapper"),
		("bell", "Bell_Hub_Icons0001"),
		("bell", "Bell_Hub_Icons0006"),
		("bell", "Hornet_bellway_token"),
		("bell", "Hornet_bellway_token_duo"),
		("bell", "QI_Main_bell_beast"),
		("bell", "QI_Main_bellshrines"),
		("bell", "bell_shrine_single_silk"),
		("bell", "crawbell"),
		("bell", "Music_box_bell0000"),
		("bell", "bell_sub_sign"),
		("shrine", "QI_Main_bellshrines"),
		("shrine", "quest_map_icon_songshrines"),
		("shrine", "Bellshrine"),
		("shrine", "Belltown_Shrine"),
		("shrine", "bell_shrine_single_silk"),
		("lock", "UI_tool_slot_locked_fill"),
		("lock", "Tool_slot_lock_ring"),
		("lock", "trap_door_circle"),
		("lock", "trapdoor_lever"),
		("lock", "music_box_bell_lock0000"),
		("silk", "silk_heart_inv_icon"),
		("silk", "icon_silk_materium"),
		("silk", "silk_heart_scene"),
		("silk", "spell_core_slim_silk_heart_ss"),
		("silk", "Silk_Grub_large_cocoon0000"),
		("silk", "Silk_Grub_small_cocoon"),
		("silk", "Toll_machine_silk_ration"),
		("silk", "silk_bomb_prompt"),
		("silk", "UI_halo_silk0000"),
		("shell", "Shell_shard_icon"),
		("shell", "I_shell_shard_icon_large"),
		("shell", "Icon_Beast_Shard"),
		("shell", "T_shell_satchel"),
		("shell", "T_sting_shard"),
		("shell", "tiny_tool_icon_sting_shard"),
		("shell", "HUD_shard_shop"),
		("shell", "glass_shards"),
		("spool", "Hornet_Spool_Upgrade_Shop_Icon"),
		("spool", "Hornet_Spool_Upgrade_Shop_Icon_full"),
		("spool", "Hornet_Spool_Upgrade_Shop_Icon_Heart"),
		("spool", "Inv_spool_backboard_ss"),
		("spool", "T_focus_spool"),
		("spool", "T_spool_bar_extender"),
		("spool", "spool_upgrade_pickup"),
		("spool", "Thread_Spool_spinner0000"),
		("crest", "C_crest"),
		("crest", "M_crest"),
		("crest", "Tools_UI_Crest_Change"),
		("crest", "crest_blank"),
		("crest", "cursed_crest_animated0001"),
		("crest", "Bell_Hub_Crest_Icon_Animated0000"),
		("crest", "Crest_prompt"),
		("mask", "Hornet_T_fractured_mask"),
		("mask", "bestiary_icon_frame_mask"),
		("mask", "dreamer_mask_prompt"),
		("mask", "soft_masker"),
		("mask", "sand_blown_mask"),
		("mask", "Goomba_mask_chunk_01"),
		("heart", "Heart_Piece_01"),
		("heart", "Heart_Piece_02"),
		("heart", "Heart_Piece_03"),
		("heart", "silk_heart_inv_icon"),
		("heart", "bone_heart_egg"),
		("heart", "cog_heart_pieces"),
		("heart", "heart_prompt_clover"),
		("heart", "heart_prompt_flower"),
		("heart", "heart_prompt_coral"),
		("heart", "coral_king_heart_icon0000"),
		("key", "dock_key"),
		("key", "I_key_architect"),
		("key", "I_key_whiteward"),
		("key", "I_chute_key_whiteward"),
		("key", "I_slab_key"),
		("key", "I_slab_key_brass"),
		("key", "I_slab_key_gold"),
		("key", "I_slab_key_old"),
		("key", "belltown_house_key"),
		("key", "rusted_cage_key"),
		("memory", "soul_orb"),
		("memory", "soul_orb_generic"),
		("memory", "black_soul_orb"),
		("memory", "new_item_orb"),
		("memory", "sc_grey_orb_single"),
		("memory", "memory_large_flat"),
		("memory", "memory_large_flat_outer"),
		("memory", "red_memory_bottle"),
		("memory", "UI_halo_orb_beams")
	};

	private bool _pickerActive;

	private int _pickerIndex;

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

	private bool _annotateActive;

	private int _annotateIndex;

	private string _noteText = "";

	private readonly List<(string name, string note)> _annotated = new List<(string, string)>();

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

	private bool _isDumpingSprites;

	private bool _isDumpingTransitions;

	private static readonly string[] DumpSkipSubstrings = new string[9] { "Travel", "Caravan", "Diving_Bell", "Menu", "Boot", "Preloader", "Intro", "Cutscene", "Credits" };

	private static readonly string[] SpecialNameKeywords = new string[8] { "silk spool", "heart piece", "mossberry", "aspid berry", "berry", "spool", "moss", "mask piece" };

	private bool _isScanningSpecial;

	private static readonly string[] AspidBerryBoolNames = new string[3] { "mosstownAspidBerryCollected", "bonegraveAspidBerryCollected", "bonetownAspidBerryCollected" };

	public static bool IsScanningChecks { get; private set; }

	private void Update()
	{
		SilksongItemRandomizerAPI.FlushLimitsRegenerate();
		if (_pickerActive)
		{
			if (Input.GetKeyDown((KeyCode)13))
			{
				PickCurrent(pick: true);
			}
			else if (Input.GetKeyDown((KeyCode)120))
			{
				PickCurrent(pick: false);
			}
		}
		if (_annotateActive && Input.GetKeyDown((KeyCode)13))
		{
			SaveCurrentNote();
		}
		if (Input.GetKeyDown((KeyCode)287))
		{
			WarpToLastBench();
		}
		if (Input.GetKeyDown((KeyCode)289))
		{
			ToggleRecentItemsUI();
		}
		if (Input.GetKeyDown((KeyCode)27))
		{
			Plugin.Instance?.RefreshBenchwarpUI();
		}
	}

	private void StartFleaPicker()
	{
		if (!_isDumpingSprites)
		{
			((MonoBehaviour)this).StartCoroutine(LoadAtlasesThenStartFleaPicker());
		}
	}

	private void StartMapSpritePicker()
	{
		if (!_isDumpingSprites)
		{
			((MonoBehaviour)this).StartCoroutine(LoadAtlasesThenStartMapPicker());
		}
	}

	private void TestGrantDirectionPermissions()
	{
		try
		{
			DirectionPermissionReward directionPermissionReward = new DirectionPermissionReward(Locale.Get("上劈权限"), "upward", allowRight: false, allowLeft: false, isAttack: true);
			DirectionPermissionReward directionPermissionReward2 = new DirectionPermissionReward(Locale.Get("左劈权限"), "left", allowRight: false, allowLeft: false, isAttack: true);
			DirectionPermissionReward directionPermissionReward3 = new DirectionPermissionReward(Locale.Get("右劈权限"), "right", allowRight: false, allowLeft: false, isAttack: true);
			directionPermissionReward.Give();
			RecentItemsUI.AddItem(directionPermissionReward);
			directionPermissionReward2.Give();
			RecentItemsUI.AddItem(directionPermissionReward2);
			directionPermissionReward3.Give();
			RecentItemsUI.AddItem(directionPermissionReward3);
			Plugin.ShowNotification("已发放 上/左/右劈 方向权限(验证持久化+弹窗+图标)", 4f);
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[F4方向测试] 发放失败: {arg}");
		}
	}

	private IEnumerator LoadAtlasesThenStartMapPicker()
	{
		if (_isDumpingSprites)
		{
			yield break;
		}
		_isDumpingSprites = true;
		string[] pendingKeys = new string[1] { "inv_nail" };
		List<string> addrKeys = new List<string>();
		try
		{
			foreach (IResourceLocator locator in Addressables.ResourceLocators)
			{
				foreach (object key in locator.Keys)
				{
					string sk = key as string;
					if (sk != null && !string.IsNullOrEmpty(sk))
					{
						addrKeys.Add(sk);
					}
				}
			}
		}
		catch
		{
		}
		HashSet<string> atlasKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (string k in addrKeys)
		{
			if (!IsLikelyAtlasKey(k))
			{
				continue;
			}
			string[] array = pendingKeys;
			foreach (string kw in array)
			{
				if (k.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					atlasKeys.Add(k);
					break;
				}
			}
		}
		int loadedOk = 0;
		int loadedFail = 0;
		foreach (string k2 in atlasKeys)
		{
			AsyncOperationHandle<Object> handle;
			try
			{
				handle = Addressables.LoadAssetAsync<Object>((object)k2);
			}
			catch
			{
				loadedFail++;
				continue;
			}
			float deadline = Time.realtimeSinceStartup + 20f;
			while (!handle.IsDone && Time.realtimeSinceStartup <= deadline)
			{
				yield return null;
			}
			if (handle.IsDone && (int)handle.Status == 1)
			{
				loadedOk++;
				continue;
			}
			loadedFail++;
			try
			{
				if (handle.IsValid())
				{
					Addressables.Release<Object>(handle);
				}
			}
			catch
			{
			}
		}
		SpriteCache.Reset();
		SpriteCache.EnsureBuilt();
		_currentCandidates.Clear();
		Sprite[] allSprites = Resources.FindObjectsOfTypeAll<Sprite>();
		Sprite[] array2 = allSprites;
		foreach (Sprite sp in array2)
		{
			if ((Object)(object)sp == (Object)null || string.IsNullOrEmpty(((Object)sp).name))
			{
				continue;
			}
			string[] array3 = pendingKeys;
			foreach (string kw2 in array3)
			{
				if (((Object)sp).name.IndexOf(kw2, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_currentCandidates.Add(("map", ((Object)sp).name));
					break;
				}
			}
		}
		if (_currentCandidates.Count == 0)
		{
			Plugin.Log.LogInfo((object)"[F4] 未找到剩余地图名的贴图。");
			_isDumpingSprites = false;
			yield break;
		}
		_pickerActive = true;
		_pickerIndex = 0;
		_pickedNames.Clear();
		Plugin.Log.LogInfo((object)$"[F4] 找到 {_currentCandidates.Count} 个剩余地图图标,开始筛选。");
		_isDumpingSprites = false;
	}

	private void StartSwimIconPicker()
	{
		if (!_isDumpingSprites)
		{
			((MonoBehaviour)this).StartCoroutine(LoadAtlasesThenStartSwimIconPicker());
		}
	}

	private IEnumerator LoadAtlasesThenStartSwimIconPicker()
	{
		if (_isDumpingSprites)
		{
			yield break;
		}
		_isDumpingSprites = true;
		string[] pendingKeys = new string[5] { "clawline", "harpoon dash", "harpoondash", "harpoon", "dash" };
		List<string> addrKeys = new List<string>();
		try
		{
			foreach (IResourceLocator locator in Addressables.ResourceLocators)
			{
				foreach (object key in locator.Keys)
				{
					string sk = key as string;
					if (sk != null && !string.IsNullOrEmpty(sk))
					{
						addrKeys.Add(sk);
					}
				}
			}
		}
		catch
		{
		}
		HashSet<string> atlasKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (string k in addrKeys)
		{
			if (!IsLikelyAtlasKey(k))
			{
				continue;
			}
			string[] array = pendingKeys;
			foreach (string kw in array)
			{
				if (k.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					atlasKeys.Add(k);
					break;
				}
			}
		}
		int loadedOk = 0;
		int loadedFail = 0;
		foreach (string k2 in atlasKeys)
		{
			AsyncOperationHandle<Object> handle;
			try
			{
				handle = Addressables.LoadAssetAsync<Object>((object)k2);
			}
			catch
			{
				loadedFail++;
				continue;
			}
			float deadline = Time.realtimeSinceStartup + 20f;
			while (!handle.IsDone && Time.realtimeSinceStartup <= deadline)
			{
				yield return null;
			}
			if (handle.IsDone && (int)handle.Status == 1)
			{
				loadedOk++;
				continue;
			}
			loadedFail++;
			try
			{
				if (handle.IsValid())
				{
					Addressables.Release<Object>(handle);
				}
			}
			catch
			{
			}
		}
		SpriteCache.Reset();
		SpriteCache.EnsureBuilt();
		_currentCandidates.Clear();
		Sprite[] allSprites = Resources.FindObjectsOfTypeAll<Sprite>();
		Sprite[] array2 = allSprites;
		foreach (Sprite sp in array2)
		{
			if ((Object)(object)sp == (Object)null || string.IsNullOrEmpty(((Object)sp).name))
			{
				continue;
			}
			string[] array3 = pendingKeys;
			foreach (string kw2 in array3)
			{
				if (((Object)sp).name.IndexOf(kw2, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_currentCandidates.Add(("swimicon", ((Object)sp).name));
					break;
				}
			}
		}
		foreach (var c in _currentCandidates)
		{
			Plugin.Log.LogInfo((object)("[F4泳图标] " + c.name));
		}
		if (_currentCandidates.Count == 0)
		{
			Plugin.Log.LogInfo((object)"[F4泳图标] 未找到关键词图标。");
			_isDumpingSprites = false;
			yield break;
		}
		_pickerActive = true;
		_pickerIndex = 0;
		_pickedNames.Clear();
		Plugin.Log.LogInfo((object)$"[F4泳图标] 找到 {_currentCandidates.Count} 个图标,开始筛选。");
		_isDumpingSprites = false;
	}

	private void TestGlowPopupCycle()
	{
		try
		{
			var (text, text2) = F4GlowPopupItems[_f4PopupIndex++ % F4GlowPopupItems.Length];
			Plugin.Log.LogInfo((object)("[F4发光弹窗] " + text + ":" + text2));
			if (1 == 0)
			{
			}
			bool flag = text switch
			{
				"heart" => HeartMsgHelper.Show(text2), 
				"melody" => MelodyMsgHelper.Show(text2), 
				"hcombo" => OfficialMsgHelper.ShowHunterCombo(int.Parse(text2), (Action)null), 
				_ => false, 
			};
			if (1 == 0)
			{
			}
			if (!flag)
			{
				Plugin.Log.LogWarning((object)("[F4发光弹窗] " + text + " " + text2 + " 弹出失败"));
			}
			((MonoBehaviour)this).StartCoroutine(DumpGlowIconDelayed(text, text2));
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[F4发光弹窗] 异常: {arg}");
		}
	}

	private IEnumerator DumpGlowIconDelayed(string kind, string evt)
	{
		for (int f = 0; f < 6; f++)
		{
			yield return null;
		}
		try
		{
			List<GameObject> clones = (from g in Object.FindObjectsOfType<GameObject>()
				where Object.op_Implicit((Object)(object)g) && ((Object)g).name.StartsWith("UI Msg Get Item", StringComparison.OrdinalIgnoreCase)
				select g).ToList();
			Plugin.Log.LogInfo((object)$"[F4发光弹窗] {kind}:{evt}: 找到 {clones.Count} 个克隆体");
			foreach (GameObject go in clones)
			{
				Transform iconT = go.transform.Find("Icon");
				Transform glowT = go.transform.Find("Icon Glow");
				SpriteRenderer sr = (Object.op_Implicit((Object)(object)iconT) ? ((Component)iconT).GetComponentInChildren<SpriteRenderer>(true) : null);
				SpriteRenderer srGlow = (Object.op_Implicit((Object)(object)glowT) ? ((Component)glowT).GetComponentInChildren<SpriteRenderer>(true) : null);
				ManualLogSource log = Plugin.Log;
				string[] obj = new string[12]
				{
					"[F4发光弹窗] ", kind, ":", evt, ": Icon='", null, null, null, null, null,
					null, null
				};
				obj[5] = ((iconT != null) ? ((Object)iconT).name : null) ?? "NULL";
				obj[6] = "' sprite=";
				obj[7] = ((Object.op_Implicit((Object)(object)sr) && Object.op_Implicit((Object)(object)sr.sprite)) ? ((Object)sr.sprite).name : "NULL");
				obj[8] = " | Glow='";
				obj[9] = ((glowT != null) ? ((Object)glowT).name : null) ?? "NULL";
				obj[10] = "' sprite=";
				obj[11] = ((Object.op_Implicit((Object)(object)srGlow) && Object.op_Implicit((Object)(object)srGlow.sprite)) ? ((Object)srGlow.sprite).name : "NULL");
				log.LogInfo((object)string.Concat(obj));
			}
		}
		catch (Exception ex)
		{
			Exception ex2 = ex;
			Plugin.Log.LogError((object)("[F4发光弹窗] 反查图标异常: " + ex2.Message));
		}
	}

	private void TestTriggerChapelDoorClose()
	{
		//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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			Plugin.Log.LogInfo((object)("[教堂关门测试] 场景: " + name));
			GameObject val = null;
			GameObject val2 = null;
			GameObject val3 = null;
			GameObject val4 = null;
			List<string> list = new List<string>();
			PlayMakerFSM val5 = null;
			activeScene = SceneManager.GetActiveScene();
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			foreach (GameObject val6 in rootGameObjects)
			{
				Transform[] componentsInChildren = val6.GetComponentsInChildren<Transform>(true);
				foreach (Transform val7 in componentsInChildren)
				{
					string name2 = ((Object)val7).name;
					if (name2.IndexOf("Door", StringComparison.OrdinalIgnoreCase) >= 0 || name2.IndexOf("door", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						list.Add(name2);
					}
					if (name2 == "Door DoClose" && (Object)(object)val == (Object)null)
					{
						val = ((Component)val7).gameObject;
					}
					else if (name2 == "Door Closed" && (Object)(object)val2 == (Object)null)
					{
						val2 = ((Component)val7).gameObject;
					}
					else if (name2 == "Door Art" && (Object)(object)val4 == (Object)null)
					{
						val4 = ((Component)val7).gameObject;
					}
				}
				PlayMakerFSM[] componentsInChildren2 = val6.GetComponentsInChildren<PlayMakerFSM>(true);
				foreach (PlayMakerFSM val8 in componentsInChildren2)
				{
					if ((Object)(object)val5 == (Object)null && val8.FsmName == "chapel_door_control")
					{
						val5 = val8;
					}
				}
			}
			Plugin.Log.LogInfo((object)("[教堂关门测试] chapel_door_control FSM: " + (((Object)(object)val5 != (Object)null) ? ((Object)((Component)val5).gameObject).name : "未找到")));
			Plugin.Log.LogInfo((object)("[教堂关门测试] Door DoClose: " + (((Object)(object)val != (Object)null) ? ((Object)val).name : "未找到") + " | Door Closed: " + (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "未找到") + " | Door Art: " + (((Object)(object)val4 != (Object)null) ? ((Object)val4).name : "未找到")));
			Plugin.Log.LogInfo((object)("[教堂关门测试] 场景内 door 相关对象: " + string.Join(", ", list.Distinct<string>(StringComparer.OrdinalIgnoreCase))));
			if ((Object)(object)val5 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[教堂关门测试] 无 chapel_door_control FSM,退出");
				return;
			}
			Plugin.Log.LogInfo((object)("[教堂关门测试] FSM 当前状态: " + val5.Fsm.ActiveStateName));
			try
			{
				FsmVariables variables = val5.Fsm.Variables;
				FsmEnum fsmEnum = variables.GetFsmEnum("Crest Type");
				FsmObject fsmObject = variables.GetFsmObject("Crest Object");
				FsmString fsmString = variables.GetFsmString("Closed PD Bool");
				ManualLogSource log = Plugin.Log;
				Enum arg = ((fsmEnum != null) ? fsmEnum.Value : null);
				object obj;
				if (fsmObject == null)
				{
					obj = null;
				}
				else
				{
					Object value = fsmObject.Value;
					obj = ((value != null) ? value.name : null);
				}
				if (obj == null)
				{
					obj = "空";
				}
				log.LogInfo((object)string.Format("[教堂关门测试] Crest Type: {0} | Crest Object: {1} | Closed PD Bool: {2}", arg, obj, ((fsmString != null) ? fsmString.Value : null) ?? "空"));
				PlayerData instance = PlayerData.instance;
				if (instance != null)
				{
					Plugin.Log.LogInfo((object)$"[教堂关门测试] chapelClosed: reaper={instance.chapelClosed_reaper} wanderer={instance.chapelClosed_wanderer} beast={instance.chapelClosed_beast} witch={instance.chapelClosed_witch} toolmaster={instance.chapelClosed_toolmaster} shaman={instance.chapelClosed_shaman}");
				}
				try
				{
					Plugin.Log.LogInfo((object)("[教堂关门测试] 平替标记: " + string.Join(", ", Plugin.SaveData.ChapelRandomizedCrests)));
				}
				catch
				{
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[教堂关门测试] 诊断输出异常: " + ex.Message));
			}
			val5.Fsm.SetState("Do Close");
			Plugin.Log.LogInfo((object)"[教堂关门测试] 已 SetState(\"Do Close\"),观察关门动画是否播放");
		}
		catch (Exception arg2)
		{
			Plugin.Log.LogError((object)$"[教堂关门测试] 异常: {arg2}");
		}
	}

	private void TestGiveRandomCrest()
	{
		try
		{
			List<ToolCrest> allCrests = ToolItemManager.GetAllCrests();
			if (allCrests == null || allCrests.Count == 0)
			{
				Plugin.Log.LogError((object)"[F4纹章] ToolItemManager 无纹章清单");
				return;
			}
			ToolCrest val = null;
			foreach (ToolCrest item in allCrests)
			{
				if ((Object)(object)item != (Object)null && !item.IsUnlocked)
				{
					val = item;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = allCrests[Random.Range(0, allCrests.Count)];
			}
			if (!((Object)(object)val == (Object)null))
			{
				Plugin.Log.LogInfo((object)("[F4纹章] 随机发放纹章: " + val.name));
				SavedItemReward savedItemReward = new SavedItemReward((SavedItem)(object)val);
				savedItemReward.Give();
				ItemRandomizer.AddGivenCount(savedItemReward.Id);
				ItemRandomizer.RecordMapping("test:F4crest", "reward:" + savedItemReward.Id);
				RecentItemsUI.AddItem(savedItemReward);
			}
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[F4纹章] 异常: {arg}");
		}
	}

	private static void LoadSlotDependencyBundles()
	{
		if (_slotDepsLoaded)
		{
			return;
		}
		_slotDepsLoaded = true;
		try
		{
			string text = Path.Combine(Application.streamingAssetsPath, "aa", "StandaloneWindows64");
			if (!Directory.Exists(text))
			{
				Plugin.Log.LogWarning((object)("[F4额外槽] Addressables 目录不存在: " + text));
				return;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			string[] files = Directory.GetFiles(text, "*.bundle");
			foreach (string text2 in files)
			{
				try
				{
					AssetBundle val = AssetBundle.LoadFromFile(text2);
					if ((Object)(object)val == (Object)null)
					{
						num2++;
					}
					else if (val.isStreamedSceneAssetBundle)
					{
						val.Unload(false);
						num3++;
					}
					else
					{
						num++;
					}
				}
				catch
				{
					num2++;
				}
			}
			Plugin.Log.LogInfo((object)$"[F4额外槽] 依赖 bundle 全量加载: 成功{num} 场景跳过{num3} 失败{num2}");
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[F4额外槽] 依赖 bundle 加载异常: " + ex.Message));
		}
	}

	private void TestGiveExtraSlot()
	{
		//IL_0063: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			PlayerData instance = PlayerData.instance;
			if (instance == null)
			{
				Plugin.Log.LogError((object)"[F4额外槽] PlayerData 不可用");
				return;
			}
			int num = _extraSlotTestIndex % 2;
			_extraSlotTestIndex++;
			string text = ((num == 0) ? "UnlockedExtraYellowSlot" : "UnlockedExtraBlueSlot");
			ManualLogSource log = Plugin.Log;
			object arg = _extraSlotTestIndex - 1;
			Scene activeScene = SceneManager.GetActiveScene();
			log.LogInfo((object)$"[F4额外槽] 触发: slot#{arg} field={text} scene={((Scene)(ref activeScene)).name}");
			FieldInfo field = typeof(PlayerData).GetField(text, BindingFlags.Instance | BindingFlags.Public);
			if (field == null || field.FieldType != typeof(bool))
			{
				Plugin.Log.LogError((object)("[F4额外槽] 字段不存在: " + text));
				return;
			}
			field.SetValue(instance, true);
			Plugin.Log.LogInfo((object)("[F4额外槽] 物品给予: " + text + " = true"));
			ToolItemType slotType = (ToolItemType)((num != 0) ? 1 : 2);
			((MonoBehaviour)this).StartCoroutine(SpawnFullScreenSlotMsg(slotType));
		}
		catch (Exception arg2)
		{
			Plugin.Log.LogError((object)$"[F4额外槽] 异常: {arg2}");
		}
	}

	private IEnumerator SpawnFullScreenSlotMsg(ToolItemType slotType)
	{
		//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)
		GameObject evolvePrefab = ChainFixer.LoadPrefabFixed("prompts_assets_all.bundle", "Assets/Prefabs/UI/Messages/UI Msg Crest Evolve.prefab", "F4额外槽evolve");
		if ((Object)(object)evolvePrefab == (Object)null)
		{
			string socketName = (((int)slotType == 2) ? "Socket 0" : "Socket 1");
			Plugin.ShowNotification("解锁 " + socketName + "!");
			yield break;
		}
		GameObject evo = Object.Instantiate<GameObject>(evolvePrefab);
		evo.SetActive(false);
		evo.transform.position = new Vector3(0f, 0f, 0f);
		PlayMakerFSM fsmComp = ((IEnumerable<PlayMakerFSM>)evo.GetComponentsInChildren<PlayMakerFSM>(true)).FirstOrDefault((Func<PlayMakerFSM, bool>)((PlayMakerFSM f) => f.FsmName == "Msg Control"));
		if ((Object)(object)fsmComp != (Object)null)
		{
			FsmString itemVar = fsmComp.FsmVariables.GetFsmString("Item");
			if (itemVar != null)
			{
				string branch = (itemVar.Value = (((int)slotType == 2) ? "Socket 0" : "Socket 1"));
				Plugin.Log.LogInfo((object)("[F4额外槽] FSM '" + fsmComp.FsmName + "' 设 Item='" + branch + "',激活后 Init→StringSwitch→" + (((int)slotType == 2) ? "SOCKET 1" : "SOCKET 2") + " 分支"));
			}
			else
			{
				Plugin.Log.LogWarning((object)"[F4额外槽] FSM 无 Item 字符串变量");
			}
		}
		else
		{
			Plugin.Log.LogWarning((object)"[F4额外槽] 未找到 Msg Control FSM");
		}
		Plugin.Log.LogInfo((object)"[F4额外槽] 激活 evolve prefab,Msg Control FSM startState=Init 自动演出");
		evo.SetActive(true);
		((MonoBehaviour)this).StartCoroutine(DiagnoseBg(evo));
		((MonoBehaviour)this).StartCoroutine(HideEvolveVisualLater(evo, fsmComp));
	}

	private IEnumerator DiagnoseBg(GameObject evo)
	{
		yield return (object)new WaitForSeconds(0.5f);
		if ((Object)(object)evo == (Object)null)
		{
			yield break;
		}
		Transform bg = evo.transform.Find("BG");
		if ((Object)(object)bg == (Object)null)
		{
			Plugin.Log.LogWarning((object)"[F4额外槽] 未找到 BG 子物体");
			yield break;
		}
		SpriteRenderer sr = ((Component)bg).GetComponent<SpriteRenderer>();
		Animator anim = ((Component)bg).GetComponent<Animator>();
		PlayMakerFSM fsm = ((Component)bg).GetComponent<PlayMakerFSM>();
		ManualLogSource log = Plugin.Log;
		object[] obj = new object[5]
		{
			bg.position,
			((Component)bg).gameObject.activeSelf,
			null,
			null,
			null
		};
		object obj2;
		if (!((Object)(object)sr != (Object)null))
		{
			obj2 = "NULL";
		}
		else
		{
			object[] array = new object[5];
			Sprite sprite = sr.sprite;
			array[0] = ((sprite != null) ? ((Object)sprite).name : null);
			array[1] = ((Renderer)sr).enabled;
			array[2] = sr.color;
			array[3] = ((Renderer)sr).sortingLayerName;
			array[4] = ((Renderer)sr).sortingOrder;
			obj2 = string.Format("sprite={0} enabled={1} color={2} sortingL={3} order={4}", array);
		}
		obj[2] = obj2;
		object obj3;
		if (!((Object)(object)anim != (Object)null))
		{
			obj3 = "NULL";
		}
		else
		{
			RuntimeAnimatorController runtimeAnimatorController = anim.runtimeAnimatorController;
			obj3 = $"ctrl={((runtimeAnimatorController != null) ? ((Object)runtimeAnimatorController).name : null)} enabled={((Behaviour)anim).enabled}";
		}
		obj[3] = obj3;
		obj[4] = (((Object)(object)fsm != (Object)null) ? (fsm.FsmName + "/" + fsm.ActiveStateName) : "NULL");
		log.LogInfo((object)string.Format("[F4额外槽] BG pos={0} active={1} sr={2} anim={3} fsm={4}", obj));
		Component[] components = ((Component)bg).GetComponents<Component>();
		foreach (Component c in components)
		{
			Plugin.Log.LogInfo((object)("[F4额外槽] BG 组件: " + ((object)c).GetType().Name));
		}
	}

	private IEnumerator HideEvolveVisualLater(GameObject evo, PlayMakerFSM controlFsm)
	{
		yield return (object)new WaitForSeconds(7.5f);
		if ((Object)(object)evo == (Object)null)
		{
			yield break;
		}
		Plugin.Log.LogInfo((object)"[F4额外槽] 演出超时,发 PRESS 让 FSM 走完还原流程 (Detect→Down→Done)");
		if ((Object)(object)controlFsm != (Object)null)
		{
			try
			{
				controlFsm.SendEvent("PRESS");
				Plugin.Log.LogInfo((object)("[F4额外槽] 已发 PRESS,当前状态: " + controlFsm.Fsm.ActiveStateName));
			}
			catch (Exception ex)
			{
				Exception ex2 = ex;
				Plugin.Log.LogWarning((object)("[F4额外槽] 发 PRESS 异常: " + ex2.Message));
			}
		}
		float t = 0f;
		while (t < 3f && (Object)(object)evo != (Object)null)
		{
			t += Time.deltaTime;
			if ((Object)(object)controlFsm != (Object)null && controlFsm.Fsm.ActiveStateName == "Done")
			{
				Plugin.Log.LogInfo((object)"[F4额外槽] FSM 已到 Done(还原完成)");
				break;
			}
			yield return null;
		}
		RestoreMsgInputState();
		if ((Object)(object)evo != (Object)null)
		{
			evo.SetActive(false);
			Object.Destroy((Object)(object)evo);
			Plugin.Log.LogInfo((object)"[F4额外槽] evolve 视觉已回收");
		}
	}

	private static void RestoreMsgInputState()
	{
		try
		{
			UIMsgProxy[] array = Object.FindObjectsOfType<UIMsgProxy>(true);
			UIMsgProxy[] array2 = array;
			foreach (UIMsgProxy val in array2)
			{
				val.SetIsInMsg(false);
				Plugin.Log.LogInfo((object)("[F4额外槽] 兜底还原 UIMsgProxy '" + ((Object)val).name + "' SetIsInMsg(false)"));
			}
			if (array.Length == 0)
			{
				Plugin.Log.LogInfo((object)"[F4额外槽] 未找到 UIMsgProxy,跳过兜底还原");
			}
			try
			{
				PlayerData instance = PlayerData.instance;
				bool isInputBlocked = InventoryPaneInput.IsInputBlocked;
				bool isPickupPaused = CollectableItemPickup.IsPickupPaused;
				Plugin.Log.LogInfo((object)$"[F4额外槽] 还原后状态: disablePause={instance.disablePause} IsInputBlocked={isInputBlocked} IsPickupPaused={isPickupPaused}");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[F4额外槽] 还原后状态读取异常: " + ex.Message));
			}
			try
			{
				if (PlayerData.instance != null && PlayerData.instance.disablePause)
				{
					PlayerData.instance.disablePause = false;
					Plugin.Log.LogInfo((object)"[F4额外槽] 强制还原 disablePause=false(FSM 未走完 SetIsInMsg 还原链)");
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[F4额外槽] 强制还原 disablePause 异常: " + ex2.Message));
			}
		}
		catch (Exception ex3)
		{
			Plugin.Log.LogWarning((object)("[F4额外槽] 兜底还原异常: " + ex3.Message));
		}
	}

	private IEnumerator TraceSlotFsm(GameObject go, PlayMakerFSM controlFsm)
	{
		if ((Object)(object)go == (Object)null)
		{
			yield break;
		}
		string outPath = Path.Combine(Paths.PluginPath, $"crest_evolve_trace_{DateTime.Now:HHmmssfff}.txt");
		DumpGameObjectStructure(go, outPath);
		Transform icon = ((IEnumerable<Transform>)go.GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == "Icon"));
		Transform obj = go.transform.Find("Tool_Socket_Evolve_lvl1");
		Animator targetAnim = ((obj != null) ? ((Component)obj).GetComponent<Animator>() : null);
		string lastState = null;
		for (int frame = 1; frame <= 90; frame++)
		{
			yield return null;
			if ((Object)(object)go == (Object)null)
			{
				Plugin.Log.LogInfo((object)"[F4额外槽] 弹窗已销毁");
				break;
			}
			string state = (((Object)(object)controlFsm != (Object)null) ? (controlFsm.Fsm.ActiveStateName ?? "none") : "noCtrl");
			string iconActive = (((Object)(object)icon != (Object)null) ? ((Component)icon).gameObject.activeInHierarchy.ToString() : "noIcon");
			string animInfo = "noLvl1Anim";
			if ((Object)(object)targetAnim != (Object)null)
			{
				AnimatorStateInfo st = targetAnim.GetCurrentAnimatorStateInfo(0);
				string iconSprite = "noIcon";
				if ((Object)(object)icon != (Object)null)
				{
					SpriteRenderer sr = ((Component)icon).GetComponent<SpriteRenderer>();
					iconSprite = (((Object)(object)sr == (Object)null) ? "noSR" : (((Object)(object)sr.sprite != (Object)null) ? ((Object)sr.sprite).name : "nullSprite"));
				}
				animInfo = $"animOn={((Behaviour)targetAnim).isActiveAndEnabled} normTime={((AnimatorStateInfo)(ref st)).normalizedTime:F2} stateHash={((AnimatorStateInfo)(ref st)).fullPathHash} clip={targetAnim.GetCurrentAnimatorClipInfo(0).Length} icon={iconSprite}";
			}
			string line = "state=" + state + " icon=" + iconActive + " | " + animInfo;
			if (state != lastState || frame <= 3 || frame % 10 == 0)
			{
				Plugin.Log.LogInfo((object)$"[F4额外槽] 帧{frame}: {line}");
				lastState = state;
			}
			if (state == "Done" || state == "Finished" || state == "Stop")
			{
				break;
			}
		}
	}

	private void TestDirectionSplitStep()
	{
		(string, bool)[] array = new(string, bool)[8]
		{
			("hasDash", true),
			("hasDash", false),
			("hasHarpoonDash", true),
			("hasHarpoonDash", false),
			("hasBrolly", true),
			("hasBrolly", false),
			("hasWalljump", true),
			("hasWalljump", false)
		};
		int splitTestIndex = _splitTestIndex;
		_splitTestIndex = (_splitTestIndex + 1) % (array.Length + 1);
		if (splitTestIndex < array.Length)
		{
			(string, bool) tuple = array[splitTestIndex];
			Plugin.Log.LogInfo((object)("[分裂弹窗测试] 弹出 " + tuple.Item1 + " " + (tuple.Item2 ? "LEFT" : "RIGHT")));
			DirectionPopupHelper.ShowDirectionSplit(tuple.Item1, tuple.Item2, (Action)null);
		}
		else
		{
			Plugin.Log.LogInfo((object)"[分裂弹窗测试] 弹出 回血");
			Sprite val = SpriteCache.Find("prompt_silkheart");
			UiMsgCustomBannerHelper.Show("Brolly", val, "Vincular", "缚丝", "enable heal", false);
		}
	}

	private void DumpGameObjectStructure(GameObject root, string outputPath)
	{
		//IL_0086: 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)root == (Object)null)
		{
			return;
		}
		try
		{
			using (StreamWriter streamWriter = new StreamWriter(outputPath, append: false, Encoding.UTF8))
			{
				streamWriter.WriteLine("=== GameObject 结构导出: " + ((Object)root).name + " ===");
				streamWriter.WriteLine($"时间: {DateTime.Now:HH:mm:ss.fff}");
				streamWriter.WriteLine($"Active Self: {root.activeSelf}  Active In Hierarchy: {root.activeInHierarchy}");
				Scene scene = root.scene;
				streamWriter.WriteLine("场景: " + ((Scene)(ref scene)).name);
				streamWriter.WriteLine("层: " + LayerMask.LayerToName(root.layer));
				streamWriter.WriteLine();
				DumpTransformRecursive(root.transform, streamWriter, 0);
			}
			Plugin.Log.LogInfo((object)("[结构导出] 已保存到: " + outputPath));
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[结构导出] 失败: {arg}");
		}
	}

	private void DumpTransformRecursive(Transform t, StreamWriter writer, int depth)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Expected O, but got Unknown
		string text = new string(' ', depth * 2);
		writer.WriteLine($"{text}[{depth}] ─ {((Object)t).name}");
		writer.WriteLine($"{text}   Position: {t.localPosition}  Rotation: {t.localEulerAngles}  Scale: {t.localScale}");
		writer.WriteLine($"{text}   Active Self: {((Component)t).gameObject.activeSelf}  Active In Hierarchy: {((Component)t).gameObject.activeInHierarchy}");
		writer.WriteLine(text + "   Tag: " + ((Component)t).tag + "  Layer: " + LayerMask.LayerToName(((Component)t).gameObject.layer));
		Component[] components = ((Component)t).GetComponents<Component>();
		writer.WriteLine($"{text}   Components ({components.Length}):");
		Component[] array = components;
		foreach (Component val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				writer.WriteLine(text + "     - (missing)");
				continue;
			}
			string fullName = ((object)val).GetType().FullName;
			writer.WriteLine(text + "     - " + fullName);
			DumpComponentDetail(val, writer, text + "       ");
		}
		foreach (Transform item in t)
		{
			Transform t2 = item;
			DumpTransformRecursive(t2, writer, depth + 1);
		}
	}

	private void DumpComponentDetail(Component comp, StreamWriter writer, string indent)
	{
		//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0678: Unknown result type (might be due to invalid IL or missing references)
		//IL_067d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0681: Unknown result type (might be due to invalid IL or missing references)
		//IL_0686: Unknown result type (might be due to invalid IL or missing references)
		//IL_0696: Unknown result type (might be due to invalid IL or missing references)
		//IL_069b: Unknown result type (might be due to invalid IL or missing references)
		//IL_069f: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Animator val = (Animator)(object)((comp is Animator) ? comp : null);
			if (val != null)
			{
				writer.WriteLine(indent + "Animator:");
				writer.WriteLine(indent + "  Controller: " + (((Object)(object)val.runtimeAnimatorController != (Object)null) ? ((Object)val.runtimeAnimatorController).name : "NULL"));
				writer.WriteLine(indent + "  Avatar: " + (((Object)(object)val.avatar != (Object)null) ? ((Object)val.avatar).name : "NULL"));
				writer.WriteLine($"{indent}  Root Motion: {val.applyRootMotion}");
				writer.WriteLine($"{indent}  Update Mode: {val.updateMode}");
				writer.WriteLine($"{indent}  Enabled: {((Behaviour)val).enabled}");
				if ((Object)(object)val.runtimeAnimatorController != (Object)null)
				{
					int layerCount = val.layerCount;
					writer.WriteLine($"{indent}  Layers: {layerCount}");
					for (int i = 0; i < layerCount; i++)
					{
						writer.WriteLine($"{indent}    Layer[{i}]: {val.GetLayerName(i)}  weight={val.GetLayerWeight(i)}");
					}
					AnimatorControllerParameter[] parameters = val.parameters;
					writer.WriteLine($"{indent}  Parameters: {parameters.Length}");
					AnimatorControllerParameter[] array = parameters;
					foreach (AnimatorControllerParameter val2 in array)
					{
						writer.WriteLine($"{indent}    {val2.name} ({val2.type}) = {GetAnimatorParamValue(val, val2)}");
					}
				}
				return;
			}
			SpriteRenderer val3 = (SpriteRenderer)(object)((comp is SpriteRenderer) ? comp : null);
			if (val3 != null)
			{
				writer.WriteLine(indent + "SpriteRenderer:");
				writer.WriteLine(indent + "  Sprite: " + (((Object)(object)val3.sprite != (Object)null) ? ((Object)val3.sprite).name : "NULL"));
				writer.WriteLine($"{indent}  Color: {val3.color}");
				writer.WriteLine(indent + "  Material: " + (((Object)(object)((Renderer)val3).sharedMaterial != (Object)null) ? ((Object)((Renderer)val3).sharedMaterial).name : "NULL"));
				writer.WriteLine($"{indent}  Sorting Layer: {((Renderer)val3).sortingLayerName}  Order: {((Renderer)val3).sortingOrder}");
				writer.WriteLine($"{indent}  Flip X: {val3.flipX}  Flip Y: {val3.flipY}");
				return;
			}
			PlayMakerFSM val4 = (PlayMakerFSM)(object)((comp is PlayMakerFSM) ? comp : null);
			if (val4 != null)
			{
				writer.WriteLine(indent + "PlayMakerFSM:");
				writer.WriteLine(indent + "  FSM Name: " + val4.FsmName);
				writer.WriteLine(indent + "  Active State: " + val4.ActiveStateName);
				writer.WriteLine(indent + "  Start State: " + ((val4.Fsm != null) ? val4.Fsm.StartState : "NULL"));
				writer.WriteLine($"{indent}  Enabled: {((Behaviour)val4).enabled}");
				writer.WriteLine(indent + "  Variables:");
				if (val4.Fsm == null || val4.Fsm.Variables == null)
				{
					return;
				}
				FsmVariables variables = val4.Fsm.Variables;
				FieldInfo[] fields = ((object)variables).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.FieldType.Name.StartsWith("Fsm"))
					{
						object value = fieldInfo.GetValue(variables);
						if (value != null)
						{
							string fsmVariableValue = GetFsmVariableValue(value);
							writer.WriteLine(indent + "    " + fieldInfo.Name + " (" + fieldInfo.FieldType.Name + ") = " + fsmVariableValue);
						}
					}
				}
				return;
			}
			Canvas val5 = (Canvas)(object)((comp is Canvas) ? comp : null);
			if (val5 != null)
			{
				writer.WriteLine(indent + "Canvas:");
				writer.WriteLine($"{indent}  Render Mode: {val5.renderMode}");
				writer.WriteLine(indent + "  World Camera: " + (((Object)(object)val5.worldCamera != (Object)null) ? ((Object)val5.worldCamera).name : "NULL"));
				writer.WriteLine($"{indent}  Pixel Perfect: {val5.pixelPerfect}");
				writer.WriteLine($"{indent}  Sort Order: {val5.sortingOrder}");
				writer.WriteLine($"{indent}  Scale Factor: {val5.scaleFactor}");
				return;
			}
			AudioSource val6 = (AudioSource)(object)((comp is AudioSource) ? comp : null);
			if (val6 != null)
			{
				writer.WriteLine(indent + "AudioSource:");
				writer.WriteLine(indent + "  Clip: " + (((Object)(object)val6.clip != (Object)null) ? ((Object)val6.clip).name : "NULL"));
				writer.WriteLine($"{indent}  Loop: {val6.loop}  Mute: {val6.mute}");
				writer.WriteLine($"{indent}  Volume: {val6.volume}  Pitch: {val6.pitch}");
				return;
			}
			ParticleSystem val7 = (ParticleSystem)(object)((comp is ParticleSystem) ? comp : null);
			if (val7 != null)
			{
				writer.WriteLine(indent + "ParticleSystem:");
				writer.WriteLine($"{indent}  Enabled: {val7.isPlaying}");
				MainModule main = val7.main;
				MinMaxCurve val8 = ((MainModule)(ref main)).startLifetime;
				object arg = ((MinMaxCurve)(ref val8)).constant;
				main = val7.main;
				val8 = ((MainModule)(ref main)).startSpeed;
				writer.WriteLine($"{indent}  Main: startLifetime={arg}  startSpeed={((MinMaxCurve)(ref val8)).constant}");
				EmissionModule emission = val7.emission;
				val8 = ((EmissionModule)(ref emission)).rateOverTime;
				object arg2 = ((MinMaxCurve)(ref val8)).constant;
				emission = val7.emission;
				writer.WriteLine($"{indent}  Emission: rate={arg2}  enabled={((EmissionModule)(ref emission)).enabled}");
			}
		}
		catch (Exception ex)
		{
			writer.WriteLine(indent + "  [组件详情输出异常: " + ex.Message + "]");
		}
	}

	private string GetAnimatorParamValue(Animator anim, AnimatorControllerParameter p)
	{
		//IL_0003: 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_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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_0023: Expected I4, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Invalid comparison between Unknown and I4
		try
		{
			AnimatorControllerParameterType type = p.type;
			AnimatorControllerParameterType val = type;
			switch (val - 1)
			{
			default:
				if ((int)val != 9)
				{
					break;
				}
				return "Trigger";
			case 0:
				return anim.GetFloat(p.nameHash).ToString("F3");
			case 2:
				return anim.GetInteger(p.nameHash).ToString();
			case 3:
				return anim.GetBool(p.nameHash).ToString();
			case 1:
				break;
			}
			return "?";
		}
		catch
		{
			return "获取失败";
		}
	}

	private string GetFsmVariableValue(object v)
	{
		if (v == null)
		{
			return "null";
		}
		try
		{
			PropertyInfo property = v.GetType().GetProperty("Value");
			if (property != null)
			{
				object value = property.GetValue(v);
				return (value != null) ? value.ToString() : "null";
			}
			FieldInfo field = v.GetType().GetField("Value");
			if (field != null)
			{
				object value2 = field.GetValue(v);
				return (value2 != null) ? value2.ToString() : "null";
			}
			return v.ToString();
		}
		catch
		{
			return "??";
		}
	}

	private void TestGiveSkillsInOrder()
	{
		try
		{
			PlayerData instance = PlayerData.instance;
			if (instance == null)
			{
				Plugin.Log.LogError((object)"[F4弹窗测试] PlayerData 为空");
				return;
			}
			List<string> list = new List<string>();
			try
			{
				List<ToolCrest> allCrests = ToolItemManager.GetAllCrests();
				if (allCrests != null)
				{
					foreach (ToolCrest item in allCrests)
					{
						if ((Object)(object)item != (Object)null && !string.IsNullOrEmpty(item.name))
						{
							list.Add(item.name);
						}
					}
				}
			}
			catch
			{
			}
			int num = _testSkillFields.Length + list.Count;
			if (num == 0)
			{
				Plugin.Log.LogError((object)"[F4弹窗测试] 测试序列为空");
				return;
			}
			int num2 = _f4SelfGiveIndex % num;
			_f4SelfGiveIndex++;
			if (num2 < _testSkillFields.Length)
			{
				string text = _testSkillFields[num2];
				ResetPdBoolForTest(instance, text);
				if (text == "HasSeenEvaHeal")
				{
					ResetPdBoolForTest(instance, "HasBoundCrestUpgrader");
				}
				Plugin.Log.LogInfo((object)$"[F4弹窗测试] 技能 #{_f4SelfGiveIndex}/{num}: {text}");
				StartingAbilityPickerAPI.GiveSkill(text, true);
			}
			else
			{
				string text2 = list[num2 - _testSkillFields.Length];
				Plugin.Log.LogInfo((object)$"[F4弹窗测试] 纹章 #{_f4SelfGiveIndex}/{num}: {text2}");
				OfficialMsgHelper.ShowToolCrestByName(text2, (Action)null);
			}
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[F4弹窗测试] 异常: {arg}");
		}
	}

	private static void ResetPdBoolForTest(PlayerData pd, string field)
	{
		try
		{
			FieldInfo field2 = typeof(PlayerData).GetField(field, BindingFlags.Instance | BindingFlags.Public);
			if (field2 != null && field2.FieldType == typeof(bool))
			{
				field2.SetValue(pd, false);
			}
		}
		catch
		{
		}
	}

	private void TestShowCrestPopup()
	{
		try
		{
			List<ToolCrest> allCrests = ToolItemManager.GetAllCrests();
			if (allCrests == null || allCrests.Count == 0)
			{
				Plugin.Log.LogError((object)"[纹章弹窗] ToolItemManager 无纹章清单");
				return;
			}
			ToolCrest val = allCrests[_crestPopupIndex % allCrests.Count];
			_crestPopupIndex++;
			OfficialMsgHelper.ShowToolCrest(val, (Action)delegate
			{
				Plugin.Log.LogInfo((object)"[纹章弹窗] 弹窗结束");
			});
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[纹章弹窗] 异常: {arg}");
		}
	}

	private void TestGrantAllPermissions()
	{
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Expected O, but got Unknown
		try
		{
			Plugin.Log.LogInfo((object)"[F4全部权限] ===== 授予前 GlobalConfig =====");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 攻击: Up={GlobalConfig.AttackUp.Value}, Left={GlobalConfig.AttackLeft.Value}, Right={GlobalConfig.AttackRight.Value}");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 冲刺: L={GlobalConfig.DashLeft.Value}, R={GlobalConfig.DashRight.Value} | 飞针: L={GlobalConfig.HarpoonLeft.Value}, R={GlobalConfig.HarpoonRight.Value}");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 漂浮: L={GlobalConfig.FloatLeft.Value}, R={GlobalConfig.FloatRight.Value} | 壁跳: L={GlobalConfig.WallJumpLeft.Value}, R={GlobalConfig.WallJumpRight.Value}");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 回血: Heal={GlobalConfig.Heal.Value}");
			StartingAbilityPickerAPI.SetAttackPermissions(true, true, true);
			DirectionPermissions val = new DirectionPermissions();
			val.DashLeft = true;
			val.DashRight = true;
			val.HarpoonLeft = true;
			val.HarpoonRight = true;
			val.FloatLeft = true;
			val.FloatRight = true;
			val.WallJumpLeft = true;
			val.WallJumpRight = true;
			val.AllowHeal = true;
			StartingAbilityPickerAPI.SetMovementPermissions(val);
			Plugin.Log.LogInfo((object)"[F4全部权限] ===== 授予后 GlobalConfig =====");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 攻击: Up={GlobalConfig.AttackUp.Value}, Left={GlobalConfig.AttackLeft.Value}, Right={GlobalConfig.AttackRight.Value}");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 冲刺: L={GlobalConfig.DashLeft.Value}, R={GlobalConfig.DashRight.Value} | 飞针: L={GlobalConfig.HarpoonLeft.Value}, R={GlobalConfig.HarpoonRight.Value}");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 漂浮: L={GlobalConfig.FloatLeft.Value}, R={GlobalConfig.FloatRight.Value} | 壁跳: L={GlobalConfig.WallJumpLeft.Value}, R={GlobalConfig.WallJumpRight.Value}");
			Plugin.Log.LogInfo((object)$"[F4全部权限] 回血: Heal={GlobalConfig.Heal.Value}");
			(bool, bool, bool) attackPermissions = StartingAbilityPickerAPI.GetAttackPermissions();
			DirectionPermissions movementPermissions = StartingAbilityPickerAPI.GetMovementPermissions();
			Plugin.Log.LogInfo((object)$"[F4全部权限] 运行时攻击: Up={attackPermissions.Item1}, Left={attackPermissions.Item2}, Right={attackPermissions.Item3}");
			Plugin.Log.LogInfo((object)($"[F4全部权限] 运行时移动: 冲刺L={movementPermissions.DashLeft},R={movementPermissions.DashRight} 飞针L={movementPermissions.HarpoonLeft},R={movementPermissions.HarpoonRight} " + $"漂浮L={movementPermissions.FloatLeft},R={movementPermissions.FloatRight} 壁跳L={movementPermissions.WallJumpLeft},R={movementPermissions.WallJumpRight} 回血={movementPermissions.AllowHeal}"));
			Plugin.ShowNotification("已授予全部权限");
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[F4全部权限] 异常: {arg}");
		}
	}

	private void TestNextDirectionPermission()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected O, but got Unknown
		try
		{
			var (text, text2, flag, flag2) = DirectionCalibList[_dirCalibIndex % DirectionCalibList.Length];
			_dirCalibIndex++;
			DirectionPermissions val = new DirectionPermissions();
			switch (text2)
			{
			case "hasDash":
				val.DashLeft = flag2;
				val.DashRight = flag;
				break;
			case "hasHarpoonDash":
				val.HarpoonLeft = flag2;
				val.HarpoonRight = flag;
				break;
			case "hasBrolly":
				val.FloatLeft = flag2;
				val.FloatRight = flag;
				break;
			case "hasWalljump":
				val.WallJumpLeft = flag2;
				val.WallJumpRight = flag;
				break;
			}
			StartingAbilityPickerAPI.SetMovementPermissions(val);
			StartingAbilityPickerAPI.GiveSkill(text2, true);
			Plugin.ShowNotification(Locale.Get(text));
			Plugin.Log.LogInfo((object)$"[F10方向校准] 已只开 {text}(skill={text2}, right={flag}, left={flag2}),请实测实际移动方向");
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"[F10方向校准] 异常: {arg}");
		}
	}

	private void TestUnlockEvaHeal()
	{
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		PlayerData instance = PlayerData.instance;
		if (instance == null)
		{
			Plugin.Log.LogError((object)"PlayerData 不可用");
			return;
		}
		instance.HasSeenEvaHeal = true;
		instance.HasBoundCrestUpgrader = true;
		instance.CrestUpgraderOfferedFinal = true;
		instance.CrestPreUpgradeTalked = true;
		instance.CrestTalkedPurpose = true;
		instance.CrestUpgraderTalkedSnare = true;
		instance.CrestTalkedPurpose = true;
		instance.CrestUpgraderTalkedSnare = true;
		instance.chapelClosed_reaper = true;
		instance.chapelClosed_wanderer = true;
		instance.chapelClosed_beast = true;
		instance.chapelClosed_witch = true;
		instance.chapelClosed_toolmaster = true;
		instance.chapelClosed_shaman = true;
		instance.completedMemory_reaper = true;
		instance.completedMemory_wanderer = true;
		instance.completedMemory_beast = true;
		instance.completedMemory_witch = true;
		instance.completedMemory_toolmaster = true;
		instance.completedMemory_shaman = true;
		string[] array = new string[3] { "EvaHeal", "Sylphsong", "Slythsong" };
		string[] array2 = array;
		foreach (string text in array2)
		{
			try
			{
				Data data = ((SerializableNamedList<Data, NamedData>)(object)instance.Tools).GetData(text);
				data.IsUnlocked = true;
				data.AmountLeft = 1;
				((SerializableNamedList<Data, NamedData>)(object)instance.Tools).SetData(text, data);
			}
			catch
			{
			}
		}
		try
		{
			Data data2 = ((SerializableNamedList<Data, NamedData>)(object)instance.Collectables).GetData("EvaHeal");
			data2.Amount = 1;
			((SerializableNamedList<Data, NamedData>)(object)instance.Collectables).SetData("EvaHeal", data2);
		}
		catch
		{
		}
		try
		{
			MethodInfo methodInfo = Type.GetType("AutoSaveManager, Assembly-CSharp")?.GetMethod("Save", new Type[1] { typeof(Enum) });
			FieldInfo fieldInfo = Type.GetType("AutoSaveName, Assembly-CSharp")?.GetField("GAINED_SLYTHSONG");
			if (methodInfo != null && fieldInfo != null)
			{
				methodInfo.Invoke(null, new object[1] { fieldInfo.GetValue(null) });
			}
		}
		catch
		{
		}
		try
		{
			Type type = Type.GetType("InventoryCollectableItemSelectionHelper, Assembly-CSharp");
			if (type != null)
			{
				PropertyInfo property = type.GetProperty("LastSelectionUpdate", BindingFlags.Static | BindingFlags.Public);
				if (property != null)
				{
					Type nestedType = type.GetNestedType("SelectionType");
					if (nestedType != null)
					{
						object value = Enum.Parse(nestedType, "EvaHeal");
						property.SetValue(null, value);
					}
				}
			}
		}
		catch
		{
		}
		try
		{
			HeroController instance2 = HeroController.instance;
			if ((Object)(object)instance2 != (Object)null)
			{
				instance2.AddSilk(1, true);
			}
		}
		catch
		{
		}
	}

	private void TestLoreDialogue()
	{
		LoreRandomizer.LoreEntry[] loreTable = LoreRandomizer.LoreTable;
		if (loreTable.Length != 0)
		{
			_loreTestIndex = (_loreTestIndex + 1) % loreTable.Length;
			LoreRandomizer.LoreEntry loreEntry = loreTable[_loreTestIndex];
			LoreRandomizer.ShowLoreDialogue(loreEntry.Key, loreEntry.Sheet);
		}
	}

	private void PickCurrent(bool pick)
	{
		List<(string, string)> list = ((_currentCandidates.Count > 0) ? _currentCandidates : SpritePickCandidates.ToList());
		if (_pickerIndex < list.Count)
		{
			if (pick)
			{
				_pickedNames.Add(list[_pickerIndex].Item2);
			}
			_pickerIndex++;
			if (_pickerIndex >= list.Count)
			{
				FinishPicker();
			}
		}
	}

	private IEnumerator LoadAtlasesThenStartFleaPicker()
	{
		if (_isDumpingSprites)
		{
			yield break;
		}
		_isDumpingSprites = true;
		List<string> addrKeys = new List<string>();
		try
		{
			foreach (IResourceLocator locator in Addressables.ResourceLocators)
			{
				foreach (object key in locator.Keys)
				{
					string sk = key as string;
					if (sk != null && !string.IsNullOrEmpty(sk))
					{
						addrKeys.Add(sk);
					}
				}
			}
		}
		catch
		{
		}
		HashSet<string> atlasKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		(string label, string[] keys)[] spriteSearchGroups = SpriteSearchGroups;
		for (int i = 0; i < spriteSearchGroups.Length; i++)
		{
			(string label, string[] keys) group = spriteSearchGroups[i];
			foreach (string k in addrKeys)
			{
				if (!IsLikelyAtlasKey(k))
				{
					continue;
				}
				bool match = false;
				string[] item = group.keys;
				foreach (string kw in item)
				{
					if (k.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						match = true;
						break;
					}
				}
				if (match)
				{
					atlasKeys.Add(k);
				}
			}
		}
		int loadedOk = 0;
		int loadedFail = 0;
		foreach (string k2 in atlasKeys)
		{
			AsyncOperationHandle<Object> handle;
			try
			{
				handle = Addressables.LoadAssetAsync<Object>((object)k2);
			}
			catch
			{
				loadedFail++;
				continue;
			}
			float deadline = Time.realtimeSinceStartup + 20f;
			while (!handle.IsDone && Time.realtimeSinceStartup <= deadline)
			{
				yield return null;
			}
			if (handle.IsDone && (int)handle.Status == 1)
			{
				loadedOk++;
				continue;
			}
			loadedFail++;
			try
			{
				if (handle.IsValid())
				{
					Addressables.Release<Object>(handle);
				}
			}
			catch
			{
			}
		}
		SpriteCache.Reset();
		SpriteCache.EnsureBuilt();
		_currentCandidates.Clear();
		Sprite[] allSprites = Resources.FindObjectsOfTypeAll<Sprite>();
		Sprite[] array = allSprites;
		foreach (Sprite sp in array)
		{
			if (!((Object)(object)sp == (Object)null))
			{
				string name = ((Object)sp).name;
				if (!string.IsNullOrEmpty(name) && name.IndexOf("flea", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					_currentCandidates.Add(("flea", name));
				}
			}
		}
		if (_currentCandidates.Count == 0)
		{
			Plugin.Log.LogInfo((object)"[F4] 未找到任何包含 'flea' 的贴图。");
			_isDumpingSprites = false;
			yield break;
		}
		_pickerActive = true;
		_pickerIndex = 0;
		_pickedNames.Clear();
		Plugin.Log.LogInfo((object)$"[F4] 找到 {_currentCandidates.Count} 个 flea 图标,开始筛选。");
		_isDumpingSprites = false;
	}

	private static string NormalizeSpriteName(string s)
	{
		if (string.IsNullOrEmpty(s))
		{
			return s ?? "";
		}
		StringBuilder stringBuilder = new StringBuilder(s.Length);
		foreach (char c in s)
		{
			if (c != '-' && c != '_' && c != ' ')
			{
				stringBuilder.Append(char.ToLowerInvariant(c));
			}
		}
		return stringBuilder.ToString();
	}

	private IEnumerator LoadAtlasesThenStartPromptPicker()
	{
		if (_isDumpingSprites)
		{
			yield break;
		}
		_isDumpingSprites = true;
		List<string> addrKeys = new List<string>();
		try
		{
			foreach (IResourceLocator locator in Addressables.ResourceLocators)
			{
				foreach (object key in locator.Keys)
				{
					string sk = key as string;
					if (sk != null && !string.IsNullOrEmpty(sk))
					{
						addrKeys.Add(sk);
					}
				}
			}
		}
		catch
		{
		}
		HashSet<string> atlasKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (string k in addrKeys)
		{
			if (IsLikelyAtlasKey(k))
			{
				atlasKeys.Add(k);
			}
		}
		int loadedOk = 0;
		int loadedFail = 0;
		foreach (string k2 in atlasKeys)
		{
			AsyncOperationHandle<Object> handle;
			try
			{
				handle = Addressables.LoadAssetAsync<Object>((object)k2);
			}
			catch
			{
				loadedFail++;
				continue;
			}
			float deadline = Time.realtimeSinceStartup + 20f;
			while (!handle.IsDone && Time.realtimeSinceStartup <= deadline)
			{
				yield return null;
			}
			if (handle.IsDone && (int)handle.Status == 1)
			{
				loadedOk++;
				continue;
			}
			loadedFail++;
			try
			{
				if (handle.IsValid())
				{
					Addressables.Release<Object>(handle);
				}
			}
			catch
			{
			}
		}
		SpriteCache.Reset();
		SpriteCache.EnsureBuilt();
		_currentCandidates.Clear();
		Sprite[] allSprites = Resources.FindObjectsOfTypeAll<Sprite>();
		List<string> flowerPrompt = new List<string>();
		List<string> flowerAny = new List<string>();
		List<string> farsightPrompt = new List<string>();
		List<string> farsightAny = new List<string>();
		List<string> completionPrompt = new List<string>();
		List<string> completionAny = new List<string>();
		Sprite[] array = allSprites;
		foreach (Sprite sp in array)
		{
			if ((Object)(object)sp == (Object)null)
			{
				continue;
			}
			string name = ((Object)sp).name;
			if (string.IsNullOrEmpty(name))
			{
				continue;
			}
			string n = NormalizeSpriteName(name);
			if (n.Contains("flower"))
			{
				if (n.Contains("prompt"))
				{
					flowerPrompt.Add(name);
				}
				else
				{
					flowerAny.Add(name);
				}
			}
			if (n.Contains("far") && n.Contains("sight"))
			{
				if (n.Contains("prompt"))
				{
					farsightPrompt.Add(name);
				}
				else
				{
					farsightAny.Add(name);
				}
			}
			if (n.Contains("completion"))
			{
				if (n.Contains("prompt"))
				{
					completionPrompt.Add(name);
				}
				else
				{
					completionAny.Add(name);
				}
			}
		}
		foreach (string x in flowerPrompt)
		{
			_currentCandidates.Add(("花+prompt", x));
		}
		if (flowerPrompt.Count == 0)
		{
			foreach (string x2 in flowerAny)
			{
				_currentCandidates.Add(("花", x2));
			}
		}
		foreach (string x3 in farsightPrompt)
		{
			_currentCandidates.Add(("遥观仪+prompt", x3));
		}
		if (farsightPrompt.Count == 0)
		{
			foreach (string x4 in farsightAny)
			{
				_currentCandidates.Add(("遥观仪", x4));
			}
		}
		foreach (string x5 in completionPrompt)
		{
			_currentCandidates.Add(("completion+prompt", x5));
		}
		if (completionPrompt.Count == 0)
		{
			foreach (string x6 in completionAny)
			{
				_currentCandidates.Add(("completion", x6));
			}
		}
		Plugin.Log.LogInfo((object)($"[F4] 花: prompt命中{flowerPrompt.Count} / 回退{flowerAny.Count}," + $"遥观仪(far+sight): prompt命中{farsightPrompt.Count} / 回退{farsightAny.Count}," + $"completion: prompt命中{completionPrompt.Count} / 回退{completionAny.Count}"));
		if (_currentCandidates.Count == 0)
		{
			Plugin.Log.LogInfo((object)"[F4] 未找到任何含 whiteflower / farsight 的贴图。");
			_isDumpingSprites = false;
			yield break;
		}
		_pickerActive = true;
		_pickerIndex = 0;
		_pickedNames.Clear();
		Plugin.Log.LogInfo((object)$"[F4] 找到 {_currentCandidates.Count} 个目标图标,开始筛选。");
		_isDumpingSprites = false;
	}

	private void FinishPicker()
	{
		_pickerActive = false;
		string path = Path.Combine(Paths.PluginPath, "sprite_picked.txt");
		using (StreamWriter streamWriter = new StreamWriter(path, append: false))
		{
			foreach (string pickedName in _pickedNames)
			{
				streamWriter.WriteLine(pickedName);
			}
		}
		StartAnnotate(_pickedNames);
	}

	private void StartAnnotate(List<string> names)
	{
		_annotateList = names.Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
		if (_annotateList.Count != 0)
		{
			_annotated.Clear();
			_annotateIndex = 0;
			_noteText = "";
			_annotateActive = true;
		}
	}

	private void StartAnnotateFromFile()
	{
		string path = Path.Combine(Paths.PluginPath, "sprite_picked.txt");
		if (File.Exists(path))
		{
			List<string> names = (from l in File.ReadAllLines(path)
				select l.Trim() into l
				where l.Length > 0
				select l).ToList();
			StartAnnotate(names);
		}
	}

	private void SaveCurrentNote()
	{
		if (_annotateIndex < _annotateList.Count)
		{
			_annotated.Add((_annotateList[_annotateIndex], _noteText.Trim()));
			_annotateIndex++;
			_noteText = "";
			if (_annotateIndex >= _annotateList.Count)
			{
				FinishAnnotate();
			}
		}
	}

	private void FinishAnnotate()
	{
		_annotateActive = false;
		string path = Path.Combine(Paths.PluginPath, "sprite_annotated.txt");
		using StreamWriter streamWriter = new StreamWriter(path, append: false);
		streamWriter.WriteLine("#sprite_name|用途备注");
		foreach (var (text, text2) in _annotated)
		{
			streamWriter.WriteLine(text + "|" + text2);
		}
	}

	private IEnumerator DumpSpriteIconsCoroutine()
	{
		if (!_isDumpingSprites)
		{
			_isDumpingSprites = true;
			yield return ((MonoBehaviour)this).StartCoroutine(LoadAtlasesThenStartPicker());
			_isDumpingSprites = false;
		}
	}

	private IEnumerator LoadAtlasesThenStartPicker()
	{
		List<string> addrKeys = new List<string>();
		try
		{
			foreach (IResourceLocator locator in Addressables.ResourceLocators)
			{
				foreach (object key in locator.Keys)
				{
					string sk = key as string;
					if (sk != null && !string.IsNullOrEmpty(sk))
					{
						addrKeys.Add(sk);
					}
				}
			}
		}
		catch
		{
		}
		HashSet<string> atlasKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		(string label, string[] keys)[] spriteSearchGroups = SpriteSearchGroups;
		for (int i = 0; i < spriteSearchGroups.Length; i++)
		{
			(string label, string[] keys) group = spriteSearchGroups[i];
			foreach (string k in addrKeys)
			{
				if (!IsLikelyAtlasKey(k))
				{
					continue;
				}
				bool match = false;
				string[] item = group.keys;
				foreach (string kw in item)
				{
					if (k.IndexOf(kw, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						match = true;
						break;
					}
				}
				if (match)
				{
					atlasKeys.Add(k);
				}
			}
		}
		int loadedOk = 0;
		int loadedFail = 0;
		foreach (string k2 in atlasKeys)
		{
			AsyncOperationHandle<Object> handle;
			try
			{
				handle = Addressables.LoadAssetAsync<Object>((object)k2);
			}
			catch
			{
				loadedFail++;
				continue;
			}
			float deadline = Time.realtimeSinceStartup + 20f;
			while (!handle.IsDone && Time.realtimeSinceStartup <= deadline)
			{
				yield return null;
			}
			if (handle.IsDone && (int)handle.Status == 1)
			{
				loadedOk++;
				continue;
			}
			loadedFail++;
			try
			{
				if (handle.IsValid())
				{
					Addressables.Release<Object>(handle);
				}
			}
			catch
			{
			}
		}
		SpriteCache.Reset();
		SpriteCache.EnsureBuilt();
		string pickPath = Path.Combine(Paths.PluginPath, "sprite_picked.txt");
		if (File.Exists(pickPath))
		{
			StartAnnotateFromFile();
			yield break;
		}
		_pickerActive = true;
		_pickerIndex = 0;
		_pickedNames.Clear();
	}

	private static bool IsLikelyAtlasKey(string key)
	{
		if (key.IndexOf(".spriteatlas", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (key.IndexOf(".bundle", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (key.IndexOf("sprites/", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		return false;
	}

	private IEnumerator ExportSteelModeIconCoroutine()
	{
		_isDumpingSprites = true;
		try
		{
			SpriteCache.EnsureBuilt();
			Sprite sprite = SpriteCache.Find("mode_select_Steel_Soul_HUD");
			if ((Object)(object)sprite == (Object)null)
			{
				List<string> atlasKeys = new List<string>();
				try
				{
					foreach (IResourceLocator locator in Addressables.ResourceLocators)
					{
						foreach (object key in locator.Keys)
						{
							string sk = key as string;
							if (sk != null && !string.IsNullOrEmpty(sk) && IsLikelyAtlasKey(sk))
							{
								string low = sk.ToLowerInvariant();
								if (low.Contains("area_art") || low.Contains("mode_select") || low.Contains("steel"))
								{
									atlasKeys.Add(sk);
								}
							}
						}
					}
				}
				catch
				{
				}
				foreach (string k in atlasKeys)
				{
					AsyncOperationHandle<Object> handle;
					try
					{
						handle = Addressables.LoadAssetAsync<Object>((object)k);
					}
					catch
					{
						continue;
					}
					float deadline = Time.realtimeSinceStartup + 20f;
					while (!handle.IsDone && Time.realtimeSinceStartup <= deadline)
					{
						yield return null;
					}
					if (handle.IsDone && (int)handle.Status == 1)
					{
						continue;
					}
					try
					{
						if (handle.IsValid())
						{
							Addressables.Release<Object>(handle);
						}
					}
					catch
					{
					}
				}
				SpriteCache.Reset();
				SpriteCache.EnsureBuilt();
				sprite = SpriteCache.Find("mode_select_Steel_Soul_HUD");
			}
			if (!((Object)(object)sprite == (Object)null))
			{
				string outPath = Path.Combine(Paths.PluginPath, "steel_mode_icon.png");
				ExportSpriteToPng(sprite, outPath);
			}
		}
		finally
		{
			_isDumpingSprites = false;
		}
	}

	private static void ExportSpriteToPng(Sprite s, string outPath)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)s == (Object)null)
		{
			return;
		}
		Texture2D texture = s.texture;
		if ((Object)(object)texture == (Object)null)
		{
			return;
		}
		Rect textureRect = s.textureRect;
		int num = Mathf.FloorToInt(((Rect)(ref textureRect)).x);
		int num2 = Mathf.FloorToInt(((Rect)(ref textureRect)).y);
		int num3 = Mathf.CeilToInt(((Rect)(ref textureRect)).width);
		int num4 = Mathf.CeilToInt(((Rect)(ref textureRect)).height);
		Texture2D val = null;
		RenderTexture val2 = null;
		RenderTexture val3 = null;
		try
		{
			val2 = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
			Graphics.Blit((Texture)(object)texture, val2);
			val3 = RenderTexture.active;
			RenderTexture.active = val2;
			val = new Texture2D(num3, num4, (TextureFormat)4, false);
			val.ReadPixels(new Rect((float)num, (float)num2, (float)num3, (float)num4), 0, 0);
			val.Apply();
			RenderTexture.active = val3;
			val3 = null;
			RenderTexture.ReleaseTemporary(val2);
			val2 = null;
			byte[] bytes = ImageConversion.EncodeToPNG(val);
			File.WriteAllBytes(outPath, bytes);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[sprite搜索] 裁剪失败: " + ex.Message));
		}
		finally
		{
			if ((Object)(object)RenderTexture.active != (Object)(object)val3 && (Object)(object)val3 != (Object)null)
			{
				RenderTexture.active = val3;
			}
			if ((Object)(object)val2 != (Object)null)
			{
				RenderTexture.ReleaseTemporary(val2);
			}
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}

	private static bool IsDumpSkipped(string sceneName)
	{
		string[] dumpSkipSubstrings = DumpSkipSubstrings;
		foreach (string value in dumpSkipSubstrings)
		{
			if (sceneName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}

	private void DumpCheckPoints()
	{
		if (!IsScanningChecks && !_isDumpingTransitions)
		{
			((MonoBehaviour)this).StartCoroutine(DumpCheckPointsCoroutine());
		}
	}

	private IEnumerator DumpCheckPointsCoroutine()
	{
		IsScanningChecks = true;
		ThreadPriority oldLoadPriority = Application.backgroundLoadingPriority;
		Application.backgroundLoadingPriority = (ThreadPriority)4;
		FieldInfo suppressField = Type.GetType("HKSilksong_Randomizer.RandomSceneLoader, HKSilksong_SceneRandomizer")?.GetField("SuppressSceneEvents", BindingFlags.Static | BindingFlags.Public);
		suppressField?.SetValue(null, true);
		try
		{
			List<string> sceneNames = new List<string>();
			try
			{
				int bsCount = SceneManager.sceneCountInBuildSettings;
				for (int i = 0; i < bsCount; i++)
				{
					string p = SceneUtility.GetScenePathByBuildIndex(i);
					if (!string.IsNullOrEmpty(p))
					{
						sceneNames.Add(Path.GetFileNameWithoutExtension(p));
					}
				}
			}
			catch
			{
			}
			if (sceneNames.Count < 10)
			{
				sceneNames.Clear();
				try
				{
					HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
					foreach (IResourceLocator locator in Addressables.ResourceLocators)
					{
						foreach (object key in locator.Keys)
						{
							string s = key as string;
							if (s != null && s.StartsWith("Scenes/", StringComparison.OrdinalIgnoreCase) && seen.Add(s))
							{
								sceneNames.Add(s.Substring("Scenes/".Length));
							}
						}
					}
				}
				catch
				{
				}
			}
			if (sceneNames.Count == 0)
			{
				Plugin.Log.LogError((object)"[扫描] 无法枚举场景清单(Build Settings 与 Addressables 均为空)");
				yield break;
			}
			string outPath = Path.Combine(Paths.PluginPath, "check_points_scan.txt");
			int sceneCount = 0;
			int pointCount = 0;
			int failed = 0;
			int excluded = 0;
			using StreamWriter writer = new StreamWriter(outPath, append: false);
			writer.WriteLine("#type|scene|path|name|detail|key|x|y");
			writer.Flush();
			foreach (string sceneName in sceneNames)
			{
				if (IsDumpSkipped(sceneName))
				{
					excluded++;
					continue;
				}
				Scene scene = SceneManager.GetSceneByName(sceneName);
				bool weLoaded = false;
				bool viaAddr = false;
				AsyncOperationHandle<SceneInstance> addr = default(AsyncOperationHandle<SceneInstance>);
				if (!((Scene)(ref scene)).IsValid() || !((Scene)(ref scene)).isLoaded)
				{
					AsyncOperation op = null;
					try
					{
						op = SceneManager.LoadSceneAsync(sceneName, (LoadSceneMode)1);
					}
					catch
					{
					}
					if (op != null)
					{
						float deadline = Time.realtimeSinceStartup + 30f;
						while (!op.isDone && Time.realtimeSinceStartup <= deadline)
						{
							yield return null;
						}
						if (op.isDone)
						{
							scene = SceneManager.GetSceneByName(sceneName);
							if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded)
							{
								weLoaded = true;
							}
						}
					}
					if (!weLoaded)
					{
						bool started = false;
						try
						{
							addr = Addressables.LoadSceneAsync((object)("Scenes/" + sceneName), (LoadSceneMode)1, true, 100, (SceneReleaseMode)0);
							started = true;
						}
						catch
						{
						}
						if (started)
						{
							float deadline2 = Time.realtimeSinceStartup + 30f;
							while (!addr.IsDone && Time.realtimeSinceStartup <= deadline2)
							{
								yield return null;
							}
							if (addr.IsDone && (int)addr.Status == 1)
							{
								SceneInstance result = addr.Result;
								scene = ((SceneInstance)(ref result)).Scene;
								weLoaded = true;
								viaAddr = true;
							}
							else
							{
								try
								{
									if (addr.IsValid())
									{
										Addressables.Release<SceneInstance>(addr);
									}
								}
								catch
								{
								}
							}
						}
					}
					if (!weLoaded)
					{
						failed++;
						yield return null;
						continue;
					}
				}
				ResetSpawnedShopSingleton();
				try
				{
					int foundHere = ScanSceneCheckPoints(scene, sceneName, writer);
					pointCount += foundHere;
					sceneCount++;
				}
				catch
				{
					failed++;
				}
				if (weLoaded)
				{
					try
					{
						if (viaAddr)
						{
							Addressables.UnloadSceneAsync(addr, true);
						}
						else if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded)
						{
							SceneManager.UnloadSceneAsync(scene);
						}
					}
					catch
					{
					}
				}
				writer.Flush();
				yield return null;
			}
		}
		finally
		{
			Application.backgroundLoadingPriority = oldLoadPriority;
			suppressField?.SetValue(null, false);
			IsScanningChecks = false;
		}
	}

	private static int ScanSceneCheckPoints(Scene scene, string sceneName, StreamWriter writer)
	{
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Invalid comparison between Unknown and I4
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_0398: Unknown result type (might be due to invalid IL or missing references)
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0482: Unknown result type (might be due to invalid IL or missing references)
		//IL_0487: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d2: 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_0571: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0656: Unknown result type (might be due to invalid IL or missing references)
		//IL_065b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0697: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0740: Unknown result type (might be due to invalid IL or missing references)
		//IL_0745: Unknown result type (might be due to invalid IL or missing references)
		//IL_0781: Unknown result type (might be due to invalid IL or missing references)
		//IL_0790: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		string boolName;
		string text = (MapStationUnlockPatch.TryGetStationBoolForScene(sceneName, out boolName) ? ("station:" + boolName) : "");
		GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
		foreach (GameObject val in rootGameObjects)
		{
			CollectableItemPickup[] componentsInChildren = val.GetComponentsInChildren<CollectableItemPickup>(true);
			foreach (CollectableItemPickup val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				string text2;
				try
				{
					text2 = PickupPatch.GetPickupKey(val2);
				}
				catch
				{
					text2 = sceneName + "_" + ((Object)((Component)val2).gameObject).name;
				}
				string text3 = "";
				try
				{
					if ((Object)(object)val2.Item != (Object)null)
					{
						text3 = ((Object)val2.Item).name;
					}
				}
				catch
				{
				}
				Vector3 position = ((Component)val2).transform.position;
				writer.WriteLine($"Pickup|{sceneName}|{GetObjectPath(((Component)val2).transform)}|{((Object)((Component)val2).gameObject).name}|{text3}|{text2}|{position.x:F1}|{position.y:F1}");
				num++;
			}
			NPCControlBase[] componentsInChildren2 = val.GetComponentsInChildren<NPCControlBase>(true);
			foreach (NPCControlBase val3 in componentsInChildren2)
			{
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				string name = ((Object)((Component)val3).gameObject).name;
				Vector3 position2 = ((Component)val3).transform.position;
				if (LoreTriggerPatch.IsExcludedTollName(name))
				{
					writer.WriteLine($"Toll|{sceneName}|{GetObjectPath(((Component)val3).transform)}|{name}|{text}||{position2.x:F1}|{position2.y:F1}");
					num++;
					continue;
				}
				bool flag = false;
				try
				{
					flag = (int)((InteractableBase)val3).InteractLabel == 0;
				}
				catch
				{
				}
				if (flag)
				{
					string text4 = "loretrig:" + sceneName + ":" + name;
					writer.WriteLine($"Lore|{sceneName}|{GetObjectPath(((Component)val3).transform)}|{name}||{text4}|{position2.x:F1}|{position2.y:F1}");
					num++;
				}
			}
			BellBench[] componentsInChildren3 = val.GetComponentsInChildren<BellBench>(true);
			foreach (BellBench val4 in componentsInChildren3)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					Vector3 position3 = ((Component)val4).transform.position;
					writer.WriteLine($"BellBench|{sceneName}|{GetObjectPath(((Component)val4).transform)}|{((Object)((Component)val4).gameObject).name}|{text}||{position3.x:F1}|{position3.y:F1}");
					num++;
				}
			}
			ShopOwner[] componentsInChildren4 = val.GetComponentsInChildren<ShopOwner>(true);
			foreach (ShopOwner val5 in componentsInChildren4)
			{
				if (!((Object)(object)val5 == (Object)null))
				{
					for (int n = 0; n < 12; n++)
					{
						string text5 = $"shop:{sceneName}_{n}";
						Vector3 position4 = ((Component)val5).transform.position;
						writer.WriteLine($"ShopSlot|{sceneName}|{GetObjectPath(((Component)val5).transform)}|ShopSlot_{n}|Slot {n}|{text5}|{position4.x:F1}|{position4.y:F1}");
						num++;
					}
				}
			}
			SimpleShopMenuOwner[] componentsInChildren5 = val.GetComponentsInChildren<SimpleShopMenuOwner>(true);
			foreach (SimpleShopMenuOwner val6 in componentsInChildren5)
			{
				if (!((Object)(object)val6 == (Object)null))
				{
					for (int num3 = 0; num3 < 12; num3++)
					{
						string text6 = $"shop:{sceneName}_{num3}";
						Vector3 position5 = ((Component)val6).transform.position;
						writer.WriteLine($"ShopSlot|{sceneName}|{GetObjectPath(((Component)val6).transform)}|ShopSlot_{num3}|Slot {num3}|{text6}|{position5.x:F1}|{position5.y:F1}");
						num++;
					}
				}
			}
			CaravanSpider[] componentsInChildren6 = val.GetComponentsInChildren<CaravanSpider>(true);
			foreach (CaravanSpider val7 in componentsInChildren6)
			{
				if (!((Object)(object)val7 == (Object)null))
				{
					for (int num5 = 0; num5 < 12; num5++)
					{
						string text7 = $"shop:{sceneName}_{num5}";
						Vector3 position6 = ((Component)val7).transform.position;
						writer.WriteLine($"ShopSlot|{sceneName}|{GetObjectPath(((Component)val7).transform)}|ShopSlot_{num5}|Slot {num5}|{text7}|{position6.x:F1}|{position6.y:F1}");
						num++;
					}
				}
			}
			CaravanTroupeHunter[] componentsInChildren7 = val.GetComponentsInChildren<CaravanTroupeHunter>(true);
			foreach (CaravanTroupeHunter val8 in componentsInChildren7)
			{
				if (!((Object)(object)val8 == (Object)null))
				{
					for (int num7 = 0; num7 < 12; num7++)
					{
						string text8 = $"shop:{sceneName}_{num7}";
						Vector3 position7 = ((Component)val8).transform.position;
						writer.WriteLine($"ShopSlot|{sceneName}|{GetObjectPath(((Component)val8).transform)}|ShopSlot_{num7}|Slot {num7}|{text8}|{position7.x:F1}|{position7.y:F1}");
						num++;
					}
				}
			}
			SimpleQuestsShopOwner[] componentsInChildren8 = val.GetComponentsInChildren<SimpleQuestsShopOwner>(true);
			foreach (SimpleQuestsShopOwner val9 in componentsInChildren8)
			{
				if (!((Object)(object)val9 == (Object)null))
				{
					for (int num9 = 0; num9 < 12; num9++)
					{
						string text9 = $"shop:{sceneName}_{num9}";
						Vector3 position8 = ((Component)val9).transform.position;
						writer.WriteLine($"ShopSlot|{sceneName}|{GetObjectPath(((Component)val9).transform)}|ShopSlot_{num9}|Slot {num9}|{text9}|{position8.x:F1}|{position8.y:F1}");
						num++;
					}
				}
			}
		}
		return num;
	}

	private static void ResetSpawnedShopSingleton()
	{
		ShakraMerchantKeeper.ResetSpawnedShopSingleton();
	}

	private static string GetObjectPath(Transform t)
	{
		StringBuilder stringBuilder = new StringBuilder(((Object)t).name);
		while ((Object)(object)t.parent != (Object)null)
		{
			t = t.parent;
			stringBuilder.Insert(0, ((Object)t).name + "/");
		}
		return stringBuilder.ToString();
	}

	private void DumpVanillaTransitions()
	{
		if (!_isDumpingTransitions)
		{
			((MonoBehaviour)this).StartCoroutine(DumpVanillaTransitionsCoroutine());
		}
	}

	private IEnumerator DumpVanillaTransitionsCoroutine()
	{
		_isDumpingTransitions = true;
		ThreadPriority oldLoadPriority = Application.backgroundLoadingPriority;
		Application.backgroundLoadingPriority = (ThreadPriority)4;
		FieldInfo suppressField = Type.GetType("HKSilksong_Randomizer.RandomSceneLoader, HKSilksong_SceneRandomizer")?.GetField("SuppressSceneEvents", BindingFlags.Static | BindingFlags.Public);
		suppressField?.SetValue(null, true);
		try
		{
			List<string> sceneNames = new List<string>();
			string source = "Build Settings";
			try
			{
				int bsCount = SceneManager.sceneCountInBuildSettings;
				for (int i = 0; i < bsCount; i++)
				{
					string p = SceneUtility.GetScenePathByBuildIndex(i);
					if (!string.IsNullOrEmpty(p))
					{
						sceneNames.Add(Path.GetFileNameWithoutExtension(p));
					}
				}
			}
			catch
			{
			}
			if (sceneNames.Count < 10)
			{
				sceneNames.Clear();
				source = "Addressables";
				try
				{
					HashSet<string> seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
					foreach (IResourceLocator locator in Addressables.ResourceLocators)
					{
						foreach (object key in locator.Keys)
						{
							string s = key as string;
							if (s != null && s.StartsWith("Scenes/", StringComparison.OrdinalIgnoreCase) && seen.Add(s))
							{
								sceneNames.Add(s.Substring("Scenes/".Length));
							}
						}
					}
				}
				catch
				{
				}
			}
			if (sceneNames.Count == 0)
			{
				Plugin.Log.LogError((object)"[Dump] 无法枚举场景清单(Build Settings 与 Addressables 均为空)");
				yield break;
			}
			bool viaAddrList = source == "Addressables";
			string outPath = Path.Combine(Paths.PluginPath, "vanilla_transitions.txt");
			HashSet<string> seenPairs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			int sceneCount = 0;
			int pairCount = 0;
			int skipped = 0;
			int excluded = 0;
			using StreamWriter writer = new StreamWriter(outPath, append: false);
			writer.WriteLine("#sceneA|gateA|sceneB|gateB");
			for (int batchStart = 0; batchStart < sceneNames.Count; batchStart += 10)
			{
				int batchLen = Math.Min(10, sceneNames.Count - batchStart);
				List<(string name, Scene scene, AsyncOperation op, AsyncOperationHandle<SceneInstance> addr, bool weLoaded, bool viaAddr)> items = new List<(string, Scene, AsyncOperation, AsyncOperationHandle<SceneInstance>, bool, bool)>(batchLen);
				for (int j = batchStart; j < batchStart + batchLen; j++)
				{
					string sceneName = sceneNames[j];
					if (IsDumpSkipped(sceneName))
					{
						excluded++;
						continue;
					}
					Scene scene = SceneManager.GetSceneByName(sceneName);
					if (((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded)
					{
						items.Add((sceneName, scene, null, default(AsyncOperationHandle<SceneInstance>), false, false));
						continue;
					}
					AsyncOperation op = null;
					AsyncOperationHandle<SceneInstance> addr = default(AsyncOperationHandle<SceneInstance>);
					bool started = false;
					try
					{
						if (viaAddrList)
						{
							addr = Addressables.LoadSceneAsync((object)("Scenes/" + sceneName), (LoadSceneMode)1, true, 100, (SceneReleaseMode)0);
						}
						else
						{
							op = SceneManager.LoadSceneAsync(sceneName, (LoadSceneMode)1);
						}
						started = true;
					}
					catch
					{
						skipped++;
					}
					if (started && (op != null || viaAddrList))
					{
						items.Add((sceneName, default(Scene), op, addr, true, viaAddrList));
					}
					else if (started)
					{
						skipped++;
					}
				}
				float deadline = Time.realtimeSinceStartup + 60f;
				bool pending = true;
				while (pending && Time.realtimeSinceStartup <= deadline)
				{
					pending = false;
					foreach (var e in items)
					{
						if (e.weLoaded)
						{
							bool isDone;
							if (!e.viaAddr)
							{
								isDone = e.op.isDone;
							}
							else
							{
								AsyncOperationHandle<SceneInstance> item = e.addr;
								isDone = item.IsDone;
							}
							if (!isDone)
							{
								pending = true;
								break;
							}
						}
					}
					if (pending)
					{
						yield return null;
					}
				}
				foreach (var e2 in items)
				{
					Scene scene2;
					if (!e2.weLoaded)
					{
						scene2 = e2.scene;
					}
					else
					{
						int num;
						if (!e2.viaAddr)
						{
							num = (e2.op.isDone ? 1 : 0);
						}
						else
						{
							AsyncOperationHandle<SceneInstance> item = e2.addr;
							if (item.IsDone)
							{
								item = e2.addr;
								num = (((int)item.Status == 1) ? 1 : 0);
							}
							else
							{
								num = 0;
							}
						}
						if (num == 0)
						{
							skipped++;
							if (!e2.viaAddr)
							{
								continue;
							}
							try
							{
								AsyncOperationHandle<SceneInstance> item = e2.addr;
								if (item.IsValid())
								{
									Addressables.Release<SceneInstance>(e2.addr);
								}
							}
							catch
							{
							}
							continue;
						}
						Scene val;
						if (!e2.viaAddr)
						{
							val = SceneManager.GetSceneByName(e2.name);
						}
						else
						{
							AsyncOperationHandle<SceneInstance> item = e2.addr;
							SceneInstance result = item.Result;
							val = ((SceneInstance)(ref result)).Scene;
						}
						scene2 = val;
					}
					try
					{
						if (((Scene)(ref scene2)).IsValid() && ((Scene)(ref scene2)).isLoaded)
						{
							int foundHere = 0;
							int totalHere = 0;
							GameObject[] rootGameObjects = ((Scene)(ref scene2)).GetRootGameObjects();
							foreach (GameObject root in rootGameObjects)
							{
								TransitionPoint[] componentsInChildren = root.GetComponentsInChildren<TransitionPoint>(true);
								foreach (TransitionPoint tp in componentsInChildren)
								{
									if (!((Object)(object)tp == (Object)null) && !string.IsNullOrEmpty(tp.targetScene))
									{
										totalHere++;
										string keyA = e2.name + "|" + ((Object)((Component)tp).gameObject).name;
										string keyB = tp.targetScene + "|" + tp.entryPoint;
										string pairKey = ((string.CompareOrdinal(keyA, keyB) <= 0) ? (keyA + "<->" + keyB) : (keyB + "<->" + keyA));
										if (seenPairs.Add(pairKey))
										{
											writer.WriteLine(keyA + "|" + tp.targetScene + "|" + tp.entryPoint);
											pairCount++;
											foundHere++;
										}
									}
								}
							}
							sceneCount++;
						}
						else
						{
							skipped++;
						}
					}
					catch
					{
						skipped++;
					}
				}
				foreach (var e3 in items)
				{
					if (!e3.weLoaded)
					{
						continue;
					}
					try
					{
						int num2;
						if (e3.viaAddr)
						{
							AsyncOperationHandle<SceneInstance> item = e3.addr;
							if (item.IsValid())
							{
								item = e3.addr;
								if (item.IsDone)
								{
									item = e3.addr;
									num2 = (((int)item.Status == 1) ? 1 : 0);
									goto IL_0ba4;
								}
							}
							num2 = 0;
							goto IL_0ba4;
						}
						Scene s2 = SceneManager.GetSceneByName(e3.name);
						if (((Scene)(ref s2)).IsValid() && ((Scene)(ref s2)).isLoaded)
						{
							SceneManager.UnloadSceneAsync(s2);
						}
						goto end_IL_0b4b;
						IL_0ba4:
						if (num2 != 0)
						{
							Addressables.UnloadSceneAsync(e3.addr, true);
						}
						end_IL_0b4b:;
					}
					catch
					{
					}
				}
				writer.Flush();
				yield return null;
			}
		}
		finally
		{
			Application.backgroundLoadingPriority = oldLoadPriority;
			suppressField?.SetValue(null, false);
			_isDumpingTransitions = false;
		}
	}

	private void WarpToLastBench()
	{
		try
		{
			PlayerData instance = PlayerData.instance;
			if (instance == null)
			{
				Plugin.Log.LogError((object)"[HotkeyHandler] PlayerData 不可用");
				return;
			}
			string respawnScene = instance.respawnScene;
			if (string.IsNullOrEmpty(respawnScene))
			{
				Plugin.Log.LogWarning((object)"[HotkeyHandler] 重生点场景为空,请先坐一次椅子");
				return;
			}
			Plugin.Log.LogInfo((object)("[HotkeyHandler] 传送至重生点: " + respawnScene + " / " + instance.respawnMarkerName));
			GameManager gm = GameManager.instance;
			gm.SaveGame((Action<bool>)delegate(bool success)
			{
				if (!success)
				{
					Plugin.Log.LogError((object)"[HotkeyHandler] 保存游戏失败");
				}
				else
				{
					gm.LoadGameFromUI(gm.profileID);
				}
			});
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("[HotkeyHandler] 传送异常: " + ex.Message));
		}
	}

	private static void ToggleRecentItemsUI()
	{
		RecentItemsUI.Toggle();
		Plugin.Log.LogInfo((object)("最近获得物品UI " + (RecentItemsUI.IsVisible ? "显示" : "隐藏")));
	}

	private void DrawAnnotateWindow()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		//IL_00f5: Expected O, but got Unknown
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Expected O, but got Unknown
		//IL_01b3: Expected O, but got Unknown
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: 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_0203: Expected O, but got Unknown
		//IL_0208: Expected O, but got Unknown
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Expected O, but got Unknown
		//IL_025f: Expected O, but got Unknown
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Expected O, but got Unknown
		//IL_02bb: Expected O, but got Unknown
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: 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_0313: Expected O, but got Unknown
		//IL_0318: Expected O, but got Unknown
		if (_annotateIndex >= _annotateList.Count)
		{
			FinishAnnotate();
			return;
		}
		string text = _an

BepInEx/plugins/StartingAbilityPicker.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GlobalEnums;
using GlobalSettings;
using HKSilksong_Randomizer;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using SilksongItemRandomizer;
using TMPro;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("StartingAbilityPicker")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("StartingAbilityPicker")]
[assembly: AssemblyTitle("StartingAbilityPicker")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/YourGitHubUsername/StartingAbilityPicker")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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;
		}
	}
}
namespace StartingAbilityPicker
{
	public static class CrazyRandomizer
	{
		private static readonly Random GlobalRng = new Random();

		public static void Apply()
		{
			Plugin.allowUpward = GlobalRng.Next(2) == 1;
			Plugin.allowLeft = GlobalRng.Next(2) == 1;
			Plugin.allowRight = GlobalRng.Next(2) == 1;
			Plugin.skillMode = true;
			Plugin.skillV = WeightedRandom(5, GlobalRng);
			Plugin.skillH = WeightedRandom(4, GlobalRng);
			Plugin.skillS = WeightedRandom(4, GlobalRng);
			Plugin.skillA = WeightedRandom(5, GlobalRng);
			if (Plugin.skillV == 0)
			{
				Plugin.skillV = 1;
			}
			if (Plugin.skillH == 0)
			{
				Plugin.skillH = 1;
			}
			Plugin.itemCount = WeightedRandom(10, GlobalRng);
			Plugin.seedInput = GlobalRng.Next(1, int.MaxValue).ToString();
		}

		private static int WeightedRandom(int max, Random rng)
		{
			if (max <= 0)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i <= max; i++)
			{
				int num2 = max - i + 1;
				num += num2 * num2;
			}
			int num3 = rng.Next(num);
			int num4 = 0;
			for (int j = 0; j <= max; j++)
			{
				int num5 = max - j + 1;
				num4 += num5 * num5;
				if (num3 < num4)
				{
					return j;
				}
			}
			return 0;
		}
	}
	public static class SharedRuntimeSettings
	{
		public static bool AttackUp = true;

		public static bool AttackLeft = true;

		public static bool AttackRight = true;

		public static bool UseTypeMode = false;

		public static int SkillTotal = 0;

		public static int SkillVertical = 0;

		public static int SkillHorizontal = 0;

		public static int SkillSpecial = 0;

		public static int SkillAttack = 0;

		public static int ItemCount = 0;

		public static int Seed = 0;

		public static bool ResetSeedWorld = false;

		public static bool FullRandomMode = false;

		public static bool CrestCurseEnabled = false;

		public static bool ForceCompletionDisplay = true;

		public static bool DashLeft = false;

		public static bool DashRight = false;

		public static bool HarpoonLeft = false;

		public static bool HarpoonRight = false;

		public static bool FloatLeft = false;

		public static bool FloatRight = false;

		public static bool WallJumpLeft = false;

		public static bool WallJumpRight = false;

		public static bool AllowHeal = false;

		public static bool HealGateEnabled = false;

		public static bool JumpGateEnabled = false;

		public static bool ColdResistGateEnabled = false;

		public static bool ColdResistOwned = false;

		public static bool DoubleJumpOwned = false;

		public static bool SwimOwned = false;

		public static bool SwimGateEnabled = false;

		public static bool ItemRandomEnabled = true;

		public static bool CrestRandomEnabled = false;

		public static bool SkillItemRandomEnabled = true;

		public static bool RelicRandomEnabled = true;

		public static bool TrapEnabled = false;

		public static bool TrapMovementEnabled = false;

		public static int TrapDifficulty = 0;

		public static int CurrencyFirstThreshold = 30;

		public static int CurrencySecondThreshold = 1000;

		public static int SilkSpearPityCount = 5;

		public static bool SilkRandomEnabled = false;

		public static bool SceneRandomEnabled = false;

		public static bool ShowSceneLabel = true;

		public static bool ShowSeedLabel = true;

		public static int RoomSeed = 0;

		public static int RoomRandomizerMode = 0;

		public static bool SkillTriggerEnabled = true;

		public static bool EnemyRandomEnabled = false;
	}
	public static class Locale
	{
		private static bool? _forceChinese;

		private static Dictionary<string, string> _externalTranslations;

		private static string _languageFolderPath;

		private static bool _isLoaded;

		private static bool? _cachedAutoDetect;

		private static readonly Dictionary<string, string> FallbackEnglish = new Dictionary<string, string>
		{
			{ "开局选项 & 场景随机", "Startup Options & Scene Randomizer" },
			{ "当前存档开局设置:", "Current Save Startup Settings:" },
			{ "(此存档已设置过,只能查看)", "(This save has been configured, view only)" },
			{ "重置本存档设置", "Reset This Save's Settings" },
			{ "攻击方向选择:", "Attack Direction Selection:" },
			{ "下劈 (默认)", "Down Slash (Default)" },
			{ "上劈", "Up Slash" },
			{ "左劈", "Left Slash" },
			{ "右劈", "Right Slash" },
			{ "技能随机模式:", "Skill Random Mode:" },
			{ "总随机", "Total Mode" },
			{ "分类随机", "Type Mode" },
			{ "开局随机技能总数量:", "Total Random Skills:" },
			{ "分类随机数量:", "Category Random Count:" },
			{ "垂直技能", "Vertical Skills" },
			{ "水平技能", "Horizontal Skills" },
			{ "特殊技能", "Special Skills" },
			{ "攻击技能", "Attack Skills" },
			{ "开局随机物品数量:", "Starting Random Item Count:" },
			{ "种子", "Seed" },
			{ "重置种子世界(含技能触发器)", "Reset Seed World (incl. Skill Triggers)" },
			{ "警告:重置后当前种子世界将重新生成,所有拾取点会重生,技能触发器也会重置。", "Warning: This will regenerate the seed world, respawn all pickups, and reset skill triggers." },
			{ "确认", "Confirm" },
			{ "关闭", "Close" },
			{ "提示: 按 F7 呼出此窗口", "Tip: Press F7 to open this window" },
			{ "彻底疯狂", "Crazy Mode" },
			{ "纹章诅咒", "Crest Curse" },
			{ "启用纹章诅咒(每个纹章带有偏科效果)", "Enable Crest Curse (each crest has specialized effects)" },
			{ "丝之心、疾跑和上冲", "Silk Heart, Dash & Super Jump" },
			{ "[开]", "[ON]" },
			{ "[关]", "[OFF]" },
			{ "启用物品随机", "Enable Item Randomizer" },
			{ "场景随机未加载", "Scene Randomizer Not Loaded" },
			{ "场景随机设置", "Scene Randomizer" },
			{ "启用场景随机", "Enable Randomizer" },
			{ "启用陷阱随机", "Enable Trap Randomizer" },
			{ "陷阱、房间随机建议丝之心,疾跑和上冲", "Trap & Room Randomizer: Silk Heart, Dash & Super Jump recommended" },
			{ "陷阱难度:", "Trap Difficulty:" },
			{ "初猎", "Beginner" },
			{ "专注", "Focused" },
			{ "满溢", "Overflow" },
			{ "当前种子", "Current Seed" },
			{ "当前场景", "Current Scene" },
			{ "修改种子:", "Modify Seed:" },
			{ "应用种子", "Apply Seed" },
			{ "场景传送:", "Teleport:" },
			{ "传送", "Teleport" },
			{ "稍后传送至", "Teleporting to " },
			{ "场景连接已重新生成", "Regenerated" },
			{ "显示选项:", "Display:" },
			{ "显示当前场景名", "Show Scene Name" },
			{ "显示当前种子", "Show Seed" },
			{ "陷阱生命化", "Trap Life" },
			{ "完成度", "Completion" },
			{ "直接应用可随机", "Apply directly to randomize" },
			{ "启用怪物随机", "Enable Enemy Randomizer" },
			{ "面板背景", "Panel Background" },
			{ "全随机模式", "Full Random Mode" },
			{ "CN", "CN" },
			{ "EN", "EN" },
			{ "Auto", "Auto" },
			{ "Current Seed: ", "Current Seed: " },
			{ "Seed: ", "Seed: " },
			{ "Scene: ", "Scene: " },
			{ "正在传送到 ", "Teleporting to " },
			{ "纹章槽位已满,获得 100 念珠", "Crest slots full, gained 100 Geo" },
			{ "纹章槽位 {0} ({1}) 已解锁!", "Crest slot {0} ({1}) unlocked!" },
			{ "纹章槽位解锁器", "Crest Slot Unlocker" },
			{ "小生命", "Small Health" },
			{ "中灵丝", "Medium Silk" },
			{ "大念珠", "Large Geo" },
			{ "完全恢复", "Full Restore" },
			{ "面具碎片", "Mask Shard" },
			{ "丝轴碎片", "Spool Part" },
			{ "丝线恢复上限 +1", "Max Silk Regen +1" },
			{ "随机念珠", "Random Geo" },
			{ "随机蓝血", "Random Blue Health" },
			{ "丝之矛", "Silk Spear" },
			{ "灵丝风暴", "Thread Sphere" },
			{ "飞针", "Harpoon Dash" },
			{ "丝刃标", "Silk Charge" },
			{ "符文之怒", "Silk Bomb" },
			{ "苍白之爪", "Silk Boss Needle" },
			{ "丝忆弦针", "Needolin" },
			{ "疾风步", "Swift Step" },
			{ "流浪者披风", "Drifter's Cloak" },
			{ "雪绒披风", "Faydown Cloak" },
			{ "蓄力斩", "Charge Slash" },
			{ "灵丝升腾", "Silk Soar" },
			{ "蛛攀术", "Cling Grip" },
			{ "风铃摇", "EvaHeal" },
			{ "格挡", "Cross Stitch" },
			{ "深邃挽歌", "Deep Elegy" },
			{ "幻兽歌", "Beast Song" },
			{ "猎人日志", "Hunter's Journal" },
			{ "最近获得物品", "Recent Items" },
			{ "按 F6 可直接传送", "Press F6 to warp directly" },
			{ "攻击槽", "Attack Slot" },
			{ "工具槽", "Tool Slot" },
			{ "法术槽", "Spell Slot" },
			{ "未知", "Unknown" },
			{ "保底念珠", "Fallback Geo" },
			{ "灵丝", "Silk" },
			{ "蓝血", "Blue Health" },
			{ "念珠", "Geo" },
			{ "甲壳", "Shell" },
			{ "大灵丝碎片", "Large Silk Part" },
			{ "小念珠", "Small Geo" },
			{ "灵丝碎片", "Silk Fragment" },
			{ "生命", "Health" },
			{ "丝线恢复上限", "Max Silk Regen" }
		};

		public static bool IsChinese
		{
			get
			{
				if (_forceChinese.HasValue)
				{
					return _forceChinese.Value;
				}
				if (_cachedAutoDetect.HasValue)
				{
					return _cachedAutoDetect.Value;
				}
				bool flag = DetectChinese();
				_cachedAutoDetect = flag;
				return flag;
			}
		}

		public static void SetLanguageFolder(string path)
		{
			if (!string.IsNullOrEmpty(path) && Directory.Exists(path))
			{
				_languageFolderPath = path;
				_isLoaded = false;
			}
		}

		public static void SetForceChinese(bool? force)
		{
			if (_forceChinese != force)
			{
				_forceChinese = force;
				_cachedAutoDetect = null;
			}
		}

		public static void Reload()
		{
			_isLoaded = false;
			_externalTranslations = null;
			_cachedAutoDetect = null;
		}

		public static string Get(string chineseText)
		{
			if (string.IsNullOrEmpty(chineseText))
			{
				return chineseText;
			}
			EnsureLoaded();
			if (_externalTranslations != null && _externalTranslations.TryGetValue(chineseText, out var value))
			{
				return value;
			}
			if (IsChinese)
			{
				return chineseText;
			}
			if (FallbackEnglish.TryGetValue(chineseText, out var value2))
			{
				return value2;
			}
			return chineseText;
		}

		private static void EnsureLoaded()
		{
			if (_isLoaded)
			{
				return;
			}
			_externalTranslations = null;
			_isLoaded = true;
			string text = _languageFolderPath;
			if (string.IsNullOrEmpty(text))
			{
				text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "language");
			}
			if (!Directory.Exists(text))
			{
				Debug.LogWarning((object)("[Locale] Language folder not found: " + text));
				return;
			}
			List<string> list = (from f in Directory.GetFiles(text, "*.json")
				orderby Path.GetFileName(f)
				select f).ToList();
			if (list.Count == 0)
			{
				Debug.LogWarning((object)("[Locale] No JSON files found in " + text));
				return;
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in list)
			{
				try
				{
					Dictionary<string, string> dictionary2 = JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(item));
					if (dictionary2 == null)
					{
						continue;
					}
					foreach (KeyValuePair<string, string> item2 in dictionary2)
					{
						dictionary[item2.Key] = item2.Value;
					}
					Debug.Log((object)$"[Locale] Loaded {dictionary2.Count} entries from {Path.GetFileName(item)}");
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[Locale] Failed to load " + item + ": " + ex.Message));
				}
			}
			if (dictionary.Count > 0)
			{
				_externalTranslations = dictionary;
				Debug.Log((object)$"[Locale] Total external translations: {_externalTranslations.Count}");
			}
		}

		private static bool DetectChinese()
		{
			try
			{
				Type type = Type.GetType("FontManager, Assembly-CSharp");
				if (type != null)
				{
					FieldInfo field = type.GetField("_currentLanguage", BindingFlags.Static | BindingFlags.NonPublic);
					if (field != null)
					{
						object value = field.GetValue(null);
						if (value != null)
						{
							string text = value.ToString().ToUpper();
							if (text == "ZH" || text == "ZH_TW")
							{
								return true;
							}
						}
					}
				}
			}
			catch
			{
			}
			try
			{
				GameSettings val = GameManager.instance?.gameSettings;
				if (val != null)
				{
					FieldInfo field2 = ((object)val).GetType().GetField("language", BindingFlags.Instance | BindingFlags.Public);
					if (field2 != null)
					{
						object value2 = field2.GetValue(val);
						if (value2 != null)
						{
							string text2 = value2.ToString().ToUpper();
							if (text2 == "ZH" || text2 == "ZH_TW")
							{
								return true;
							}
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	public static class PanelRenderer
	{
		private static readonly Color BrightWhite = new Color(0.95f, 0.97f, 1f);

		private static GUIStyle _titleStyle;

		private static GUIStyle _statusStyle;

		private static GUIStyle _diffTitleStyle;

		private static GUIStyle _diffStatusStyle;

		private static GUIStyle _seedPlaceholderStyle;

		private static readonly Dictionary<int, GUIStyle> _titleStyleCache = new Dictionary<int, GUIStyle>();

		private static readonly Dictionary<int, GUIStyle> _statusStyleCache = new Dictionary<int, GUIStyle>();

		private static Vector2 _skillScrollPos;

		private static void EnsureStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0077: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			if (_titleStyle == null)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)1,
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				val.normal.textColor = BrightWhite;
				_titleStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)7,
					fontSize = 11
				};
				val2.normal.textColor = BrightWhite;
				_statusStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)1,
					fontSize = 18,
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = BrightWhite;
				_diffTitleStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)7,
					fontSize = 15
				};
				val4.normal.textColor = BrightWhite;
				_diffStatusStyle = val4;
			}
		}

		public static void DrawLeftPanel(Plugin p)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: 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_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: 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_031b: 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_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			Color textColor = GUI.skin.label.normal.textColor;
			GUI.skin.label.normal.textColor = BrightWhite;
			GUI.skin.toggle.normal.textColor = BrightWhite;
			GUI.skin.button.normal.textColor = BrightWhite;
			GUI.skin.horizontalSlider.normal.textColor = BrightWhite;
			GUI.skin.textField.normal.textColor = BrightWhite;
			GUI.skin.label.fontSize = 20;
			GUI.skin.toggle.fontSize = 20;
			GUI.skin.button.fontSize = 24;
			GUI.skin.horizontalSlider.fontSize = 18;
			GUI.skin.textField.fontSize = 18;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(Locale.Get("当前存档开局设置:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) });
			DrawBackgroundToggle(p);
			GUILayout.EndHorizontal();
			GUILayout.Space(15f);
			bool flag = IsAlreadyChosen(p);
			if (flag)
			{
				GUILayout.Label(Locale.Get("(此存档已设置过,只能查看)"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
				GUI.backgroundColor = new Color(0.8f, 0.5f, 0.2f);
				if (GUILayout.Button(Locale.Get("重置本存档设置"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(45f) }))
				{
					ResetProfile(p);
					GUI.backgroundColor = Color.white;
					GUI.skin.label.normal.textColor = textColor;
					GUI.skin.toggle.normal.textColor = textColor;
					GUI.skin.button.normal.textColor = textColor;
					GUI.skin.horizontalSlider.normal.textColor = textColor;
					GUI.skin.textField.normal.textColor = textColor;
					return;
				}
				GUI.backgroundColor = Color.white;
			}
			GUILayout.Space(20f);
			DrawAttackDirection(p, flag);
			GUILayout.Space(20f);
			DrawSkillModeButtons(p, flag);
			GUILayout.Space(10f);
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(200f) });
			_skillScrollPos = GUILayout.BeginScrollView(_skillScrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			if (!SharedRuntimeSettings.UseTypeMode)
			{
				DrawTotalSlider(p, flag);
			}
			else
			{
				DrawCategorySliders(p, flag);
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
			GUILayout.Space(15f);
			DrawItemSlider(p, flag);
			GUILayout.Space(25f);
			DrawSeedInput(p, flag);
			DrawConfirmAndClose(p, flag);
			GUILayout.Space(15f);
			int fontSize = GUI.skin.label.fontSize;
			GUI.skin.label.fontSize = 26;
			GUI.color = Color.yellow;
			GUILayout.Label(Locale.Get("提示: 按 F7 呼出此窗口"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) });
			GUI.color = BrightWhite;
			GUI.skin.label.fontSize = fontSize;
			GUI.skin.label.normal.textColor = textColor;
			GUI.skin.toggle.normal.textColor = textColor;
			GUI.skin.button.normal.textColor = textColor;
			GUI.skin.horizontalSlider.normal.textColor = textColor;
			GUI.skin.textField.normal.textColor = textColor;
		}

		public static void DrawScenePanel(Plugin p)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			Color textColor = GUI.skin.label.normal.textColor;
			GUI.skin.label.normal.textColor = BrightWhite;
			GUI.skin.button.normal.textColor = BrightWhite;
			GUI.skin.toggle.normal.textColor = BrightWhite;
			if (!p.SceneRandomAvailable)
			{
				GUILayout.Label(Locale.Get("场景随机未加载"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
				GUI.skin.label.normal.textColor = textColor;
				return;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("CN", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(20f),
				GUILayout.Width(60f)
			}))
			{
				Locale.SetForceChinese(true);
			}
			if (GUILayout.Button("EN", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(20f),
				GUILayout.Width(60f)
			}))
			{
				Locale.SetForceChinese(false);
			}
			if (GUILayout.Button("Auto", (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(20f),
				GUILayout.Width(60f)
			}))
			{
				Locale.SetForceChinese(null);
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(8f);
			GUILayout.Label(Locale.Get("场景随机设置"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.Space(12f);
			DrawItemRandomToggle(p);
			DrawSceneToggle(p);
			DrawEnemyRandoAdjustToggle(p);
			DrawTrapToggle(p);
			DrawTrapDifficulty(p);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			DrawTrapMovementToggle(p);
			GUILayout.Space(12f);
			int currentRoomSeed = StartingAbilityPickerAPI.GetCurrentRoomSeed();
			GUILayout.Label(string.Format("{0}: {1}", Locale.Get("当前种子"), currentRoomSeed), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.Space(8f);
			string currentRoomScene = StartingAbilityPickerAPI.GetCurrentRoomScene();
			GUILayout.Label(Locale.Get("当前场景") + ": " + currentRoomScene, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.Space(18f);
			DrawSeedChanger(p);
			GUILayout.Space(20f);
			DrawTeleporter(p);
			GUILayout.Space(20f);
			DrawDisplayToggles(p);
			GUI.skin.label.normal.textColor = textColor;
			GUI.skin.button.normal.textColor = textColor;
			GUI.skin.toggle.normal.textColor = textColor;
		}

		private static bool IsAlreadyChosen(Plugin p)
		{
			int item = GameManager.instance?.profileID ?? (-1);
			if (Plugin.chosenProfileSet != null)
			{
				return Plugin.chosenProfileSet.Contains(item);
			}
			return false;
		}

		private static void ResetProfile(Plugin p)
		{
			int item = GameManager.instance?.profileID ?? (-1);
			Plugin.chosenProfileSet?.Remove(item);
			p.SaveChosenProfiles();
			SharedRuntimeSettings.AttackUp = true;
			SharedRuntimeSettings.AttackLeft = true;
			SharedRuntimeSettings.AttackRight = true;
			SharedRuntimeSettings.UseTypeMode = false;
			SharedRuntimeSettings.SkillTotal = 0;
			SharedRuntimeSettings.SkillVertical = 0;
			SharedRuntimeSettings.SkillHorizontal = 0;
			SharedRuntimeSettings.SkillSpecial = 0;
			SharedRuntimeSettings.SkillAttack = 0;
			SharedRuntimeSettings.ItemCount = 0;
			SharedRuntimeSettings.ResetSeedWorld = false;
			SharedRuntimeSettings.FullRandomMode = false;
			SharedRuntimeSettings.CrestCurseEnabled = false;
			SharedRuntimeSettings.ForceCompletionDisplay = true;
			SharedRuntimeSettings.DashLeft = false;
			SharedRuntimeSettings.DashRight = false;
			SharedRuntimeSettings.HarpoonLeft = false;
			SharedRuntimeSettings.HarpoonRight = false;
			SharedRuntimeSettings.FloatLeft = false;
			SharedRuntimeSettings.FloatRight = false;
			SharedRuntimeSettings.WallJumpLeft = false;
			SharedRuntimeSettings.WallJumpRight = false;
			SharedRuntimeSettings.AllowHeal = false;
			SharedRuntimeSettings.ColdResistOwned = false;
			SharedRuntimeSettings.SwimOwned = false;
			SharedRuntimeSettings.DoubleJumpOwned = false;
			SharedRuntimeSettings.ColdResistGateEnabled = false;
			SharedRuntimeSettings.SwimGateEnabled = false;
			SharedRuntimeSettings.JumpGateEnabled = false;
			SharedRuntimeSettings.HealGateEnabled = false;
			StartingAbilityPickerAPI.SetAttackPermissions(SharedRuntimeSettings.AttackUp, SharedRuntimeSettings.AttackLeft, SharedRuntimeSettings.AttackRight);
			StartingAbilityPickerAPI.SetSkillRandomMode(SharedRuntimeSettings.UseTypeMode);
			StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
			StartingAbilityPickerAPI.SetStartingItemCount(SharedRuntimeSettings.ItemCount);
			StartingAbilityPickerAPI.SetResetSeedWorld(SharedRuntimeSettings.ResetSeedWorld);
			StartingAbilityPickerAPI.SetFullRandomMode(SharedRuntimeSettings.FullRandomMode);
			StartingAbilityPickerAPI.SetCrestCurseEnabled(SharedRuntimeSettings.CrestCurseEnabled);
			StartingAbilityPickerAPI.SetForceCompletionDisplay(SharedRuntimeSettings.ForceCompletionDisplay);
			StartingAbilityPickerAPI.SetMovementPermissions(new DirectionPermissions
			{
				DashLeft = SharedRuntimeSettings.DashLeft,
				DashRight = SharedRuntimeSettings.DashRight,
				HarpoonLeft = SharedRuntimeSettings.HarpoonLeft,
				HarpoonRight = SharedRuntimeSettings.HarpoonRight,
				FloatLeft = SharedRuntimeSettings.FloatLeft,
				FloatRight = SharedRuntimeSettings.FloatRight,
				WallJumpLeft = SharedRuntimeSettings.WallJumpLeft,
				WallJumpRight = SharedRuntimeSettings.WallJumpRight,
				AllowHeal = SharedRuntimeSettings.AllowHeal
			});
			RoomRandomMode.ResetPending();
			try
			{
				GlobalConfig.FullRandomMode.Value = false;
				GlobalConfig.Heal.Value = false;
				GlobalConfig.Swim.Value = false;
				GlobalConfig.ColdResist.Value = false;
				GlobalConfig.Save();
				Plugin.Log.LogInfo((object)"[ResetProfile] 已重置全部权限配置并写回 cfg(攻击开、移动/回血/游泳/抗寒关、全随机关)");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[ResetProfile] 重置写回 cfg 失败: {arg}");
			}
		}

		private static void DrawAttackDirection(Plugin p, bool alreadyChosen)
		{
			GUILayout.Label(Locale.Get("攻击方向选择:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
			GUILayout.Space(5f);
			GUI.enabled = false;
			DrawModeButton("下劈 (默认)", true, 18, GUILayout.Width(220f), GUILayout.Height(60f));
			GUI.enabled = !alreadyChosen && !SharedRuntimeSettings.FullRandomMode;
			bool flag = DrawModeButton(Locale.Get("上劈"), SharedRuntimeSettings.AttackUp, 18, GUILayout.Width(220f), GUILayout.Height(60f));
			if (flag != SharedRuntimeSettings.AttackUp && !alreadyChosen)
			{
				SharedRuntimeSettings.AttackUp = flag;
				StartingAbilityPickerAPI.SetAttackPermissions(SharedRuntimeSettings.AttackUp, SharedRuntimeSettings.AttackLeft, SharedRuntimeSettings.AttackRight);
				GlobalConfig.Save();
			}
			bool flag2 = DrawModeButton(Locale.Get("左劈"), SharedRuntimeSettings.AttackLeft, 18, GUILayout.Width(220f), GUILayout.Height(60f));
			if (flag2 != SharedRuntimeSettings.AttackLeft && !alreadyChosen)
			{
				SharedRuntimeSettings.AttackLeft = flag2;
				StartingAbilityPickerAPI.SetAttackPermissions(SharedRuntimeSettings.AttackUp, SharedRuntimeSettings.AttackLeft, SharedRuntimeSettings.AttackRight);
				GlobalConfig.Save();
			}
			bool flag3 = DrawModeButton(Locale.Get("右劈"), SharedRuntimeSettings.AttackRight, 18, GUILayout.Width(220f), GUILayout.Height(60f));
			if (flag3 != SharedRuntimeSettings.AttackRight && !alreadyChosen)
			{
				SharedRuntimeSettings.AttackRight = flag3;
				StartingAbilityPickerAPI.SetAttackPermissions(SharedRuntimeSettings.AttackUp, SharedRuntimeSettings.AttackLeft, SharedRuntimeSettings.AttackRight);
				GlobalConfig.Save();
			}
			GUI.enabled = true;
		}

		private static void DrawSkillModeButtons(Plugin p, bool alreadyChosen)
		{
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(Locale.Get("技能随机模式:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag = !SharedRuntimeSettings.UseTypeMode;
			if (DrawModeButton(Locale.Get("总随机"), flag, 18, GUILayout.Width(130f), GUILayout.Height(60f)) != flag && !alreadyChosen)
			{
				SharedRuntimeSettings.UseTypeMode = false;
				StartingAbilityPickerAPI.SetSkillRandomMode(SharedRuntimeSettings.UseTypeMode);
				GlobalConfig.Save();
			}
			bool useTypeMode = SharedRuntimeSettings.UseTypeMode;
			if (DrawModeButton(Locale.Get("分类随机"), useTypeMode, 18, GUILayout.Width(130f), GUILayout.Height(60f)) != useTypeMode && !alreadyChosen)
			{
				SharedRuntimeSettings.UseTypeMode = true;
				StartingAbilityPickerAPI.SetSkillRandomMode(SharedRuntimeSettings.UseTypeMode);
				GlobalConfig.Save();
			}
			GUI.enabled = !alreadyChosen && !SharedRuntimeSettings.FullRandomMode;
			if (DrawModeButton(Locale.Get("彻底疯狂"), false, 18, GUILayout.Width(160f), GUILayout.Height(60f)) && !alreadyChosen)
			{
				CrazyRandomizer.Apply();
				SharedRuntimeSettings.AttackUp = Plugin.allowUpward;
				SharedRuntimeSettings.AttackLeft = Plugin.allowLeft;
				SharedRuntimeSettings.AttackRight = Plugin.allowRight;
				SharedRuntimeSettings.UseTypeMode = Plugin.skillMode;
				SharedRuntimeSettings.SkillVertical = Plugin.skillV;
				SharedRuntimeSettings.SkillHorizontal = Plugin.skillH;
				SharedRuntimeSettings.SkillSpecial = Plugin.skillS;
				SharedRuntimeSettings.SkillAttack = Plugin.skillA;
				SharedRuntimeSettings.ItemCount = Plugin.itemCount;
				StartingAbilityPickerAPI.SetAttackPermissions(SharedRuntimeSettings.AttackUp, SharedRuntimeSettings.AttackLeft, SharedRuntimeSettings.AttackRight);
				StartingAbilityPickerAPI.SetSkillRandomMode(SharedRuntimeSettings.UseTypeMode);
				StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
				StartingAbilityPickerAPI.SetStartingItemCount(SharedRuntimeSettings.ItemCount);
				GlobalConfig.Save();
			}
			GUI.enabled = true;
			bool isPending = RoomRandomMode.IsPending;
			if (DrawModeButton(Locale.Get("丝之心、疾跑和上冲"), isPending, 14, GUILayout.Width(160f), GUILayout.Height(60f)) != isPending && !alreadyChosen)
			{
				RoomRandomMode.Toggle();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(8f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUI.enabled = !alreadyChosen;
			bool flag2 = DrawModeButton(Locale.Get("全随机模式"), SharedRuntimeSettings.FullRandomMode, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag2 != SharedRuntimeSettings.FullRandomMode && !alreadyChosen)
			{
				SharedRuntimeSettings.FullRandomMode = flag2;
				StartingAbilityPickerAPI.SetFullRandomMode(SharedRuntimeSettings.FullRandomMode);
				DirectionPermissions movementPermissions = StartingAbilityPickerAPI.GetMovementPermissions();
				movementPermissions.AllowHeal = !flag2;
				StartingAbilityPickerAPI.SetMovementPermissions(movementPermissions);
				GlobalConfig.Save();
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			bool flag3 = DrawModeButton(Locale.Get("纹章诅咒"), SharedRuntimeSettings.CrestCurseEnabled, 18, GUILayout.Width(160f), GUILayout.Height(60f));
			if (flag3 != SharedRuntimeSettings.CrestCurseEnabled && !alreadyChosen)
			{
				SharedRuntimeSettings.CrestCurseEnabled = flag3;
				StartingAbilityPickerAPI.SetCrestCurseEnabled(SharedRuntimeSettings.CrestCurseEnabled);
				GlobalConfig.Save();
			}
			bool flag4 = DrawModeButton(Locale.Get("完成度"), SharedRuntimeSettings.ForceCompletionDisplay, 18, GUILayout.Width(160f), GUILayout.Height(60f));
			if (flag4 != SharedRuntimeSettings.ForceCompletionDisplay && !alreadyChosen)
			{
				SharedRuntimeSettings.ForceCompletionDisplay = flag4;
				StartingAbilityPickerAPI.SetForceCompletionDisplay(SharedRuntimeSettings.ForceCompletionDisplay);
				GlobalConfig.Save();
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			if (SharedRuntimeSettings.CrestCurseEnabled)
			{
				GUILayout.Space(5f);
				GUI.color = Color.yellow;
				GUILayout.Label(Locale.Get("启用纹章诅咒(每个纹章带有偏科效果)"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
				GUI.color = BrightWhite;
			}
		}

		private static void DrawTotalSlider(Plugin p, bool alreadyChosen)
		{
			GUILayout.Label(Locale.Get("开局随机技能总数量:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(SharedRuntimeSettings.SkillTotal.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(35f),
				GUILayout.Height(40f)
			});
			int num = (int)GUILayout.HorizontalSlider((float)SharedRuntimeSettings.SkillTotal, 0f, 13f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
			if (num != SharedRuntimeSettings.SkillTotal && !alreadyChosen)
			{
				SharedRuntimeSettings.SkillTotal = num;
				StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
				GlobalConfig.Save();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
		}

		private static void DrawCategorySliders(Plugin p, bool alreadyChosen)
		{
			GUILayout.Label(Locale.Get("分类随机数量:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
			DrawOneSlider(Locale.Get("垂直技能"), ref SharedRuntimeSettings.SkillVertical, Plugin.MaxVerticalDynamic, alreadyChosen);
			DrawOneSlider(Locale.Get("水平技能"), ref SharedRuntimeSettings.SkillHorizontal, Plugin.MaxHorizontalDynamic, alreadyChosen);
			DrawOneSlider(Locale.Get("特殊技能"), ref SharedRuntimeSettings.SkillSpecial, Plugin.MaxSpecialDynamic, alreadyChosen);
			DrawOneSlider(Locale.Get("攻击技能"), ref SharedRuntimeSettings.SkillAttack, Plugin.MaxAttackDynamic, alreadyChosen);
		}

		private static void DrawOneSlider(string label, ref int value, int max, bool disabled)
		{
			GUILayout.Label($"{label} (0-{max})", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(value.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(35f),
				GUILayout.Height(40f)
			});
			int num = (int)GUILayout.HorizontalSlider((float)value, 0f, (float)max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
			if (num != value && !disabled)
			{
				value = num;
				StartingAbilityPickerAPI.SetSkillCounts(SharedRuntimeSettings.SkillTotal, SharedRuntimeSettings.SkillVertical, SharedRuntimeSettings.SkillHorizontal, SharedRuntimeSettings.SkillSpecial, SharedRuntimeSettings.SkillAttack);
				GlobalConfig.Save();
			}
			GUILayout.EndHorizontal();
		}

		private static void DrawItemSlider(Plugin p, bool alreadyChosen)
		{
			GUILayout.Label(Locale.Get("开局随机物品数量:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(35f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(SharedRuntimeSettings.ItemCount.ToString(), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(35f),
				GUILayout.Height(40f)
			});
			int num = (int)GUILayout.HorizontalSlider((float)SharedRuntimeSettings.ItemCount, 0f, 10f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
			if (num != SharedRuntimeSettings.ItemCount && !alreadyChosen)
			{
				SharedRuntimeSettings.ItemCount = num;
				StartingAbilityPickerAPI.SetStartingItemCount(SharedRuntimeSettings.ItemCount);
				GlobalConfig.Save();
			}
			GUILayout.EndHorizontal();
		}

		private static void DrawSeedInput(Plugin p, bool alreadyChosen)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(Locale.Get("种子"), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(60f),
				GUILayout.Height(40f)
			});
			string text = SharedRuntimeSettings.Seed.ToString();
			string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(160f),
				GUILayout.Height(40f)
			});
			if (text2 != text && !alreadyChosen && int.TryParse(text2, out var result))
			{
				SharedRuntimeSettings.Seed = result;
				StartingAbilityPickerAPI.SetSeed(SharedRuntimeSettings.Seed);
				GlobalConfig.Save();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(5f);
			bool resetSeedWorld = SharedRuntimeSettings.ResetSeedWorld;
			GUI.color = (resetSeedWorld ? Color.red : BrightWhite);
			bool flag = GUILayout.Toggle(resetSeedWorld, Locale.Get("重置种子世界(含技能触发器)"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) });
			if (flag != resetSeedWorld && !alreadyChosen)
			{
				SharedRuntimeSettings.ResetSeedWorld = flag;
				StartingAbilityPickerAPI.SetResetSeedWorld(SharedRuntimeSettings.ResetSeedWorld);
				GlobalConfig.Save();
			}
			GUI.color = BrightWhite;
			if (resetSeedWorld)
			{
				GUI.color = Color.yellow;
				GUILayout.Label(Locale.Get("警告:重置后当前种子世界将重新生成,所有拾取点会重生,技能触发器也会重置。"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(70f) });
				GUI.color = BrightWhite;
			}
			GUILayout.Space(35f);
		}

		private static void DrawConfirmAndClose(Plugin p, bool alreadyChosen)
		{
			//IL_0009: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			GUI.enabled = !alreadyChosen;
			GUI.backgroundColor = Color.green;
			if (GUILayout.Button(Locale.Get("确认"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) }) && !alreadyChosen)
			{
				StartingAbilityPickerAPI.ApplyPending();
				p.ApplySettings();
				GlobalConfig.Save();
			}
			GUI.backgroundColor = Color.white;
			GUI.enabled = true;
			GUI.backgroundColor = new Color(0.8f, 0.2f, 0.2f);
			if (GUILayout.Button(Locale.Get("关闭"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }))
			{
				p.ShowUI = false;
			}
			GUI.backgroundColor = Color.white;
		}

		private static void DrawSceneToggle(Plugin p)
		{
			bool flag = StartingAbilityPickerAPI.IsRoomRandomizationEnabled();
			bool flag2 = DrawModeButton(Locale.Get("启用场景随机"), flag, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag2 != flag)
			{
				StartingAbilityPickerAPI.SetRoomRandomizationEnabled(flag2);
				GlobalConfig.Save();
			}
		}

		private static void DrawTrapToggle(Plugin p)
		{
			bool flag = SilksongItemRandomizerAPI.IsTrapEnabled();
			bool flag2 = DrawModeButton(Locale.Get("启用陷阱随机"), flag, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag2 != flag)
			{
				SilksongItemRandomizerAPI.SetTrapEnabled(flag2);
				if (flag2)
				{
					SilksongItemRandomizerAPI.RegenerateTrapsNow();
				}
				else
				{
					SilksongItemRandomizerAPI.SetTrapEnabled(false);
				}
				GlobalConfig.Save();
			}
		}

		private static void DrawItemRandomToggle(Plugin p)
		{
			bool itemRandomEnabled = p.GetItemRandomEnabled();
			bool flag = DrawModeButton(Locale.Get("启用物品随机"), itemRandomEnabled, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag != itemRandomEnabled)
			{
				p.SetItemRandomEnabled(flag);
			}
		}

		private static void DrawTrapDifficulty(Plugin p)
		{
			//IL_0094: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label(Locale.Get("陷阱难度:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Sprite[] array = (Sprite[])(object)new Sprite[3]
			{
				Plugin.BeginnerIcon,
				Plugin.FocusedIcon,
				Plugin.OverflowIcon
			};
			string[] array2 = new string[3] { "初猎", "专注", "满溢" };
			float num = 50f;
			Rect rect;
			if ((Object)(object)Plugin.OverflowIcon != (Object)null && (Object)(object)Plugin.OverflowIcon.texture != (Object)null)
			{
				rect = Plugin.OverflowIcon.rect;
				float width = ((Rect)(ref rect)).width;
				rect = Plugin.OverflowIcon.rect;
				float height = ((Rect)(ref rect)).height;
				num = 90f * (height / width);
			}
			EnsureStyles();
			Rect val2 = default(Rect);
			for (int i = 0; i < 3; i++)
			{
				bool flag = SilksongItemRandomizerAPI.GetTrapDifficulty() == i;
				Sprite val = array[i];
				Rect rect2 = GUILayoutUtility.GetRect(90f, num, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(90f),
					GUILayout.Height(num)
				});
				Color backgroundColor = (flag ? new Color(0.2f, 1f, 0.2f) : new Color(0.6f, 0.6f, 0.6f));
				Color backgroundColor2 = GUI.backgroundColor;
				GUI.backgroundColor = backgroundColor;
				GUI.Box(rect2, "");
				GUI.backgroundColor = backgroundColor2;
				if ((Object)(object)((val != null) ? val.texture : null) != (Object)null)
				{
					rect = val.rect;
					float width2 = ((Rect)(ref rect)).width;
					rect = val.rect;
					float height2 = ((Rect)(ref rect)).height;
					float num2;
					float num3;
					float num4;
					float num5;
					if (i == 0)
					{
						num2 = ((Rect)(ref rect2)).height;
						num3 = num2 * (width2 / height2);
						num4 = ((Rect)(ref rect2)).x + (((Rect)(ref rect2)).width - num3) / 2f;
						num5 = ((Rect)(ref rect2)).y;
					}
					else
					{
						num3 = 90f;
						num2 = num3 * (height2 / width2);
						num4 = ((Rect)(ref rect2)).x + (((Rect)(ref rect2)).width - num3) / 2f;
						num5 = ((Rect)(ref rect2)).y + (((Rect)(ref rect2)).height - num2) / 2f;
					}
					GUI.DrawTexture(new Rect(num4, num5, num3, num2), (Texture)(object)val.texture, (ScaleMode)0);
				}
				if (GUI.Button(rect2, "", GUIStyle.none))
				{
					SilksongItemRandomizerAPI.SetTrapDifficulty(i);
					if (SilksongItemRandomizerAPI.IsTrapEnabled())
					{
						SilksongItemRandomizerAPI.RegenerateTrapsNow();
					}
					GlobalConfig.Save();
				}
				((Rect)(ref val2))..ctor(((Rect)(ref rect2)).x, ((Rect)(ref rect2)).y, ((Rect)(ref rect2)).width, ((Rect)(ref rect2)).height / 2f);
				Rect val3 = new Rect(((Rect)(ref rect2)).x, ((Rect)(ref rect2)).y + ((Rect)(ref rect2)).height / 2f, ((Rect)(ref rect2)).width, ((Rect)(ref rect2)).height / 2f);
				GUI.Label(val2, Locale.Get(array2[i]), _diffTitleStyle);
				GUI.Label(val3, flag ? Locale.Get("[开]") : Locale.Get("[关]"), _diffStatusStyle);
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(5f);
		}

		private static void DrawTrapMovementToggle(Plugin p)
		{
			bool flag = SilksongItemRandomizerAPI.IsTrapMovementEnabled();
			bool flag2 = DrawModeButton(Locale.Get("陷阱生命化"), flag, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag2 != flag)
			{
				SilksongItemRandomizerAPI.SetTrapMovementEnabled(flag2);
				if (SilksongItemRandomizerAPI.IsTrapEnabled())
				{
					SilksongItemRandomizerAPI.RegenerateTrapsNow();
				}
				GlobalConfig.Save();
			}
		}

		private static void DrawEnemyRandoAdjustToggle(Plugin p)
		{
			bool value = Plugin.EnemyRandoAdjustEnabled.Value;
			bool flag = DrawModeButton(Locale.Get("启用怪物随机"), value, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag != value)
			{
				p.SetEnemyRandoAdjustEnabled(flag);
				GlobalConfig.Save();
			}
		}

		private static void DrawBackgroundToggle(Plugin p)
		{
			bool value = Plugin.PanelBackgroundEnabled.Value;
			bool flag = DrawModeButton(Locale.Get("面板背景"), value, 18, GUILayout.Width(260f), GUILayout.Height(60f));
			if (flag != value)
			{
				p.SetPanelBackgroundEnabled(flag);
				GlobalConfig.Save();
			}
		}

		private static void DrawSeedChanger(Plugin p)
		{
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			GUILayout.Label(Locale.Get("修改种子:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
			string text = GUILayout.TextField(p.SceneSeedInput, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(260f),
				GUILayout.Height(30f)
			});
			if (string.IsNullOrEmpty(text) && GUI.GetNameOfFocusedControl() != "SeedTextField")
			{
				Rect lastRect = GUILayoutUtility.GetLastRect();
				GUI.SetNextControlName("SeedTextField");
				Color color = GUI.color;
				GUI.color = Color.yellow;
				if (_seedPlaceholderStyle == null)
				{
					_seedPlaceholderStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontSize = 14
					};
				}
				GUI.Label(lastRect, Locale.Get("直接应用可随机"), _seedPlaceholderStyle);
				GUI.color = color;
			}
			else
			{
				GUI.SetNextControlName("SeedTextField");
			}
			p.SceneSeedInput = text;
			GUILayout.Space(4f);
			GUI.backgroundColor = Color.green;
			if (GUILayout.Button(Locale.Get("应用种子"), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(32f),
				GUILayout.Width(260f)
			}))
			{
				string text2 = p.SceneSeedInput.Trim();
				int result;
				if (string.IsNullOrEmpty(text2))
				{
					result = new Random().Next(1, int.MaxValue);
				}
				else if (!int.TryParse(text2, out result))
				{
					return;
				}
				try
				{
					object seedManager = p.SeedManager;
					object obj = seedManager.GetType().GetField("cfgNewSeed", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(seedManager);
					object obj2 = seedManager.GetType().GetField("cfgRegenerateTrigger", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(seedManager);
					obj.GetType().GetProperty("Value").SetValue(obj, result, null);
					obj2.GetType().GetProperty("Value").SetValue(obj2, true, null);
					Plugin.ShowNotification(Locale.Get("场景连接已重新生成"));
					if (SilksongItemRandomizerAPI.IsTrapEnabled())
					{
						SilksongItemRandomizerAPI.SetSeed(result);
						SilksongItemRandomizerAPI.RegenerateTrapsNow();
					}
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"场景种子更新失败: {arg}");
				}
			}
			GUI.backgroundColor = Color.white;
		}

		private static void DrawTeleporter(Plugin p)
		{
			//IL_005d: 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)
			GUILayout.Label(Locale.Get("场景传送:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
			p.SceneTeleportInput = GUILayout.TextField(p.SceneTeleportInput, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(260f),
				GUILayout.Height(30f)
			});
			GUILayout.Space(4f);
			GUI.backgroundColor = Color.green;
			if (GUILayout.Button(Locale.Get("传送"), (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(32f),
				GUILayout.Width(260f)
			}) && !string.IsNullOrWhiteSpace(p.SceneTeleportInput))
			{
				p.PendingTeleport = true;
				p.PendingTeleportScene = p.SceneTeleportInput;
				p.ShowUI = false;
				Plugin.ShowNotification(Locale.Get("稍后传送至") + p.SceneTeleportInput + " ...");
			}
			GUI.backgroundColor = Color.white;
		}

		private static void DrawDisplayToggles(Plugin p)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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)
			bool showSceneLabel = p.GetShowSceneLabel();
			bool showSeedLabel = p.GetShowSeedLabel();
			GUILayout.Label(Locale.Get("显示选项:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) });
			GUILayout.Space(4f);
			GUI.color = (showSceneLabel ? Color.green : BrightWhite);
			if (GUILayout.Toggle(showSceneLabel, Locale.Get("显示当前场景名"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				if (!showSceneLabel)
				{
					p.SetShowSceneLabel(value: true);
				}
			}
			else if (showSceneLabel)
			{
				p.SetShowSceneLabel(value: false);
			}
			GUI.color = BrightWhite;
			GUILayout.Space(6f);
			GUI.color = (showSeedLabel ? Color.green : BrightWhite);
			if (GUILayout.Toggle(showSeedLabel, Locale.Get("显示当前种子"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
			{
				if (!showSeedLabel)
				{
					p.SetShowSceneLabel(value: true, isSeed: true);
				}
			}
			else if (showSeedLabel)
			{
				p.SetShowSceneLabel(value: false, isSeed: true);
			}
			GUI.color = BrightWhite;
		}

		private static bool DrawModeButton(string label, bool isOn, int titleFontSize = 18, params GUILayoutOption[] options)
		{
			//IL_0042: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0095: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00c5: Expected O, but got Unknown
			string text = (isOn ? Locale.Get("[开]") : Locale.Get("[关]"));
			Color backgroundColor = (isOn ? new Color(0.2f, 1f, 0.2f) : new Color(0.6f, 0.6f, 0.6f));
			Color backgroundColor2 = GUI.backgroundColor;
			GUI.backgroundColor = backgroundColor;
			bool num = GUILayout.Button("", options);
			Rect lastRect = GUILayoutUtility.GetLastRect();
			EnsureStyles();
			if (!_titleStyleCache.TryGetValue(titleFontSize, out var value))
			{
				Dictionary<int, GUIStyle> titleStyleCache = _titleStyleCache;
				GUIStyle val = new GUIStyle(_titleStyle)
				{
					fontSize = titleFontSize
				};
				value = val;
				titleStyleCache[titleFontSize] = val;
			}
			if (!_statusStyleCache.TryGetValue(titleFontSize, out var value2))
			{
				Dictionary<int, GUIStyle> statusStyleCache = _statusStyleCache;
				GUIStyle val2 = new GUIStyle(_statusStyle)
				{
					fontSize = titleFontSize - 3
				};
				value2 = val2;
				statusStyleCache[titleFontSize] = val2;
			}
			GUI.Label(new Rect(((Rect)(ref lastRect)).x, ((Rect)(ref lastRect)).y, ((Rect)(ref lastRect)).width, ((Rect)(ref lastRect)).height / 2f), label, value);
			GUI.Label(new Rect(((Rect)(ref lastRect)).x, ((Rect)(ref lastRect)).y + ((Rect)(ref lastRect)).height / 2f, ((Rect)(ref lastRect)).width, ((Rect)(ref lastRect)).height / 2f), text, value2);
			GUI.backgroundColor = backgroundColor2;
			if (!num)
			{
				return isOn;
			}
			return !isOn;
		}
	}
	[BepInPlugin("HardItemRandomizer.StartingAbilityPicker", "Starting Ability Picker", "1.0.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		public static bool AllowLeftAttack = false;

		public static bool AllowRightAttack = false;

		public static bool AllowUpwardAttack = false;

		public static bool DirectionEnabled = true;

		public static bool AllowDashLeft = false;

		public static bool AllowDashRight = false;

		public static bool AllowHarpoonLeft = false;

		public static bool AllowHarpoonRight = false;

		public static bool AllowFloatLeft = false;

		public static bool AllowFloatRight = false;

		public static bool AllowWallJumpLeft = false;

		public static bool AllowWallJumpRight = false;

		public static bool AllowHeal = false;

		public static bool skillMode = false;

		public static int skillTotal = 0;

		public static int skillV = 0;

		public static int skillH = 0;

		public static int skillS = 0;

		public static int skillA = 0;

		public const int MaxVertical = 5;

		public const int MaxHorizontal = 4;

		public const int MaxSpecial = 4;

		public const int MaxAttack = 5;

		private bool _lastSceneWasMenu = true;

		private bool showUI;

		public static bool allowUpward = false;

		public static bool allowLeft = false;

		public static bool allowRight = false;

		public static int itemCount = 0;

		public static bool resetPickups = false;

		public static string seedInput = "";

		internal static HashSet<int> chosenProfileSet = new HashSet<int>();

		private static string _notificationMessage = null;

		private static float _notificationEndTime = 0f;

		private static GUIStyle _notificationStyle;

		private static Sprite _backgroundSprite;

		private static Sprite _beginnerIcon;

		private static Sprite _focusedIcon;

		private static Sprite _overflowIcon;

		private static bool _bgLoaded = false;

		private static Rect _windowRect;

		private static float _lastScreenHeight;

		public static bool crestCurseEnabled = false;

		public static ConfigEntry<bool> CfgAllowDashLeft;

		public static ConfigEntry<bool> CfgAllowDashRight;

		public static ConfigEntry<bool> CfgAllowHarpoonLeft;

		public static ConfigEntry<bool> CfgAllowHarpoonRight;

		public static ConfigEntry<bool> CfgAllowFloatLeft;

		public static ConfigEntry<bool> CfgAllowFloatRight;

		public static ConfigEntry<bool> CfgAllowWallJumpLeft;

		public static ConfigEntry<bool> CfgAllowWallJumpRight;

		public static ConfigEntry<bool> CfgAllowHeal;

		private static readonly WaitForSeconds HalfSecondWait = new WaitForSeconds(0.5f);

		public bool _pendingApply;

		public int _pendingSkillTotal;

		public int _pendingSkillV;

		public int _pendingSkillH;

		public int _pendingSkillS;

		public int _pendingSkillA;

		public bool _pendingSkillMode;

		public int _pendingItemCount;

		private bool _sceneRandomAvailable;

		private Type _sceneLoaderType;

		private Type _roomRandoType;

		private Type _seedManagerType;

		private object _sceneLoader;

		private object _roomRando;

		private object _seedManager;

		private FieldInfo _cfgShowSceneLabelField;

		private FieldInfo _currentSceneNameField;

		private MethodInfo _getSeedMethod;

		private string sceneSeedInput = "";

		private string sceneTeleportInput = "";

		private bool _pendingTeleport;

		private string _pendingTeleportScene = "";

		private bool _apiInitialized;

		private static bool _hasLoadedFromSaveData = false;

		private static FieldInfo _currentSeedField;

		private static FieldInfo _enableRandomizationField;

		private static PropertyInfo _publicItemRandomProp;

		public static Plugin Instance { get; private set; }

		public static ConfigEntry<bool> UseNativeSkillGiving { get; private set; }

		public static ConfigEntry<string> ChosenProfiles { get; private set; }

		public static ConfigEntry<int> StartingSkillCount { get; private set; }

		public static ConfigEntry<int> StartingItemCount { get; private set; }

		public static ConfigEntry<int> RandomSeed { get; private set; }

		public static ConfigEntry<bool> CfgCrestCurseEnabled { get; private set; }

		public static ConfigEntry<bool> EnemyRandoAdjustEnabled { get; private set; }

		public static ConfigEntry<bool> PanelBackgroundEnabled { get; private set; }

		public static ConfigEntry<bool> CfgDirectionEnabled { get; private set; }

		public static ConfigEntry<bool> CfgFullRandomMode { get; private set; }

		public bool ShowUI
		{
			get
			{
				return showUI;
			}
			set
			{
				showUI = value;
			}
		}

		public string SceneSeedInput
		{
			get
			{
				return sceneSeedInput;
			}
			set
			{
				sceneSeedInput = value;
			}
		}

		public string SceneTeleportInput
		{
			get
			{
				return sceneTeleportInput;
			}
			set
			{
				sceneTeleportInput = value;
			}
		}

		public bool PendingTeleport
		{
			get
			{
				return _pendingTeleport;
			}
			set
			{
				_pendingTeleport = value;
			}
		}

		public string PendingTeleportScene
		{
			get
			{
				return _pendingTeleportScene;
			}
			set
			{
				_pendingTeleportScene = value;
			}
		}

		public object SeedManager => _seedManager;

		public bool SceneRandomAvailable => _sceneRandomAvailable;

		public static int MaxVerticalDynamic => 5;

		public static int MaxHorizontalDynamic => 4;

		public static int MaxSpecialDynamic => 4;

		public static int MaxAttackDynamic => 5;

		public static Sprite BeginnerIcon => _beginnerIcon;

		public static Sprite FocusedIcon => _focusedIcon;

		public static Sprite OverflowIcon => _overflowIcon;

		public static bool FullRandomModeEnabled
		{
			get
			{
				return DirectionPatch.FullRandomMode;
			}
			set
			{
				DirectionPatch.FullRandomMode = value;
			}
		}

		private int currentProfileID => PlayerData.instance?.profileID ?? (-1);

		public void SetPendingOpeningSettings(bool skillMode, int skillTotal, int skillV, int skillH, int skillS, int skillA, int itemCount)
		{
			_pendingSkillMode = skillMode;
			_pendingSkillTotal = skillTotal;
			_pendingSkillV = skillV;
			_pendingSkillH = skillH;
			_pendingSkillS = skillS;
			_pendingSkillA = skillA;
			_pendingItemCount = itemCount;
			_pendingApply = true;
		}

		public static void ShowNotification(string message, float duration = 3f)
		{
			_notificationMessage = message;
			_notificationEndTime = Time.time + duration;
		}

		private Texture2D MakeTexture(int width, int height, Color col)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Color[] array = (Color[])(object)new Color[width * height];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = col;
			}
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		public static bool GetCrestCurseEnabled()
		{
			return crestCurseEnabled;
		}

		public static void SetCrestCurseEnabled(bool value)
		{
			crestCurseEnabled = value;
			CfgCrestCurseEnabled.Value = value;
			try
			{
				Type.GetType("SilksongItemRandomizer.ToolEffectRandomizer, SilksongItemRandomizer")?.GetMethod("SetEnabled", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { value });
			}
			catch
			{
			}
			Log.LogInfo((object)("纹章诅咒开关: " + (value ? "启用" : "禁用")));
		}

		public static void SetFullRandomMode(bool enabled)
		{
			DirectionPatch.FullRandomMode = enabled;
		}

		public void SetForceCompletionDisplay(bool value)
		{
			int num = currentProfileID;
			if (num == -1 || GetForceCompletionDisplay() == value)
			{
				return;
			}
			Plugin.SaveData.ProfileCompletionDisplay[num] = value;
			Plugin.SaveGlobalData();
			Log.LogInfo((object)string.Format("强制完成度显示开关 (存档 {0}): {1}", num, value ? "启用(显示)" : "禁用(隐藏)"));
			PlayerData instance = PlayerData.instance;
			if (instance != null)
			{
				if (value)
				{
					instance.ConstructedFarsight = true;
					RefreshCompletionUI(forceShow: true);
				}
				else
				{
					ClearFsmCompletionVariables();
				}
			}
			GlobalConfig.Save();
		}

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"StartingAbilityPicker loaded! Press F7 to open starting options.");
			ChosenProfiles = GlobalConfig.ChosenProfiles;
			StartingSkillCount = GlobalConfig.StartingSkillCount;
			StartingItemCount = GlobalConfig.StartingItemCount;
			RandomSeed = GlobalConfig.RandomSeed;
			CfgCrestCurseEnabled = GlobalConfig.CrestCurseEnabled;
			crestCurseEnabled = CfgCrestCurseEnabled.Value;
			AllowUpwardAttack = GlobalConfig.AttackUp.Value;
			AllowLeftAttack = GlobalConfig.AttackLeft.Value;
			AllowRightAttack = GlobalConfig.AttackRight.Value;
			SharedRuntimeSettings.AttackUp = AllowUpwardAttack;
			SharedRuntimeSettings.AttackLeft = AllowLeftAttack;
			SharedRuntimeSettings.AttackRight = AllowRightAttack;
			_hasLoadedFromSaveData = true;
			Log.LogInfo((object)$"从 cfg 加载攻击方向: Up={AllowUpwardAttack}, Left={AllowLeftAttack}, Right={AllowRightAttack}");
			try
			{
				Type.GetType("SilksongItemRandomizer.ToolEffectRandomizer, SilksongItemRandomizer")?.GetMethod("SetEnabled", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { crestCurseEnabled });
			}
			catch
			{
			}
			EnemyRandoAdjustEnabled = GlobalConfig.EnemyRandoAdjustEnabled;
			try
			{
				Type type = Type.GetType("SilksongItemRandomizer.EnemyRandoAdjuster, SilksongItemRandomizer");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("Enabled", BindingFlags.Static | BindingFlags.Public);
					if (property != null)
					{
						property.SetValue(null, EnemyRandoAdjustEnabled.Value);
					}
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"同步怪物调整开关失败: {arg}");
			}
			PanelBackgroundEnabled = GlobalConfig.PanelBackgroundEnabled;
			UseNativeSkillGiving = GlobalConfig.UseNativeSkillGiving;
			SkillRandomizer.UseNativeItemGiving = UseNativeSkillGiving.Value;
			CfgDirectionEnabled = GlobalConfig.DirectionEnabled;
			DirectionEnabled = CfgDirectionEnabled.Value;
			CfgAllowDashLeft = GlobalConfig.DashLeft;
			CfgAllowDashRight = GlobalConfig.DashRight;
			CfgAllowHarpoonLeft = GlobalConfig.HarpoonLeft;
			CfgAllowHarpoonRight = GlobalConfig.HarpoonRight;
			CfgAllowFloatLeft = GlobalConfig.FloatLeft;
			CfgAllowFloatRight = GlobalConfig.FloatRight;
			CfgAllowWallJumpLeft = GlobalConfig.WallJumpLeft;
			CfgAllowWallJumpRight = GlobalConfig.WallJumpRight;
			CfgAllowHeal = GlobalConfig.Heal;
			AllowDashLeft = CfgAllowDashLeft.Value;
			AllowDashRight = CfgAllowDashRight.Value;
			AllowHarpoonLeft = CfgAllowHarpoonLeft.Value;
			AllowHarpoonRight = CfgAllowHarpoonRight.Value;
			AllowFloatLeft = CfgAllowFloatLeft.Value;
			AllowFloatRight = CfgAllowFloatRight.Value;
			AllowWallJumpLeft = CfgAllowWallJumpLeft.Value;
			AllowWallJumpRight = CfgAllowWallJumpRight.Value;
			AllowHeal = CfgAllowHeal.Value;
			CfgFullRandomMode = GlobalConfig.FullRandomMode;
			DirectionPatch.FullRandomMode = CfgFullRandomMode.Value;
			SharedRuntimeSettings.UseTypeMode = GlobalConfig.UseTypeMode.Value;
			SharedRuntimeSettings.SkillTotal = GlobalConfig.StartingSkillCount.Value;
			SharedRuntimeSettings.SkillVertical = GlobalConfig.SkillVertical.Value;
			SharedRuntimeSettings.SkillHorizontal = GlobalConfig.SkillHorizontal.Value;
			SharedRuntimeSettings.SkillSpecial = GlobalConfig.SkillSpecial.Value;
			SharedRuntimeSettings.SkillAttack = GlobalConfig.SkillAttack.Value;
			SharedRuntimeSettings.ItemCount = GlobalConfig.StartingItemCount.Value;
			SharedRuntimeSettings.ForceCompletionDisplay = GlobalConfig.ForceCompletionDisplay.Value;
			SharedRuntimeSettings.ResetSeedWorld = GlobalConfig.ResetSeedWorld.Value;
			LoadChosenProfiles();
			EnsureRandomSeed();
			SceneManager.sceneLoaded += OnSceneLoaded;
			Harmony.CreateAndPatchAll(typeof(DirectionPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(AbilityGatePatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(DirectionPopupHelper), (string)null);
			Harmony.CreateAndPatchAll(typeof(SaveStats_GetCompletionPercentage_Patch), (string)null);
			Harmony.CreateAndPatchAll(typeof(SaveStats_UnlockedCompletionRate_Patch), (string)null);
			Harmony.CreateAndPatchAll(typeof(PlayerData_CountGameCompletion_Patch), (string)null);
			Harmony.CreateAndPatchAll(typeof(ConvertFloatToString_Patch), (string)null);
			Harmony.CreateAndPatchAll(typeof(BuildString_Patch), (string)null);
			((MonoBehaviour)this).StartCoroutine(LoadAllImages());
			InitSceneRandomRefs();
			StartingAbilityPickerAPI.Initialize(new StartingAbilityPickerConfig
			{
				Seed = RandomSeed.Value,
				FullRandomMode = CfgFullRandomMode.Value,
				MovementPermissions = new DirectionPermissions
				{
					DashLeft = AllowDashLeft,
					DashRight = AllowDashRight,
					HarpoonLeft = AllowHarpoonLeft,
					HarpoonRight = AllowHarpoonRight,
					FloatLeft = AllowFloatLeft,
					FloatRight = AllowFloatRight,
					WallJumpLeft = AllowWallJumpLeft,
					WallJumpRight = AllowWallJumpRight,
					AllowHeal = AllowHeal
				},
				CrestCurseEnabled = crestCurseEnabled,
				ForceCompletionDisplay = GetForceCompletionDisplay(),
				UseNativeSkillGiving = UseNativeSkillGiving.Value,
				PanelBackgroundEnabled = PanelBackgroundEnabled.Value,
				DefaultStartingItemCount = StartingItemCount.Value,
				DefaultSkillTotal = StartingSkillCount.Value,
				DefaultSkillV = 0,
				DefaultSkillH = 0,
				DefaultSkillS = 0,
				DefaultSkillA = 0,
				DefaultSkillTypeMode = false,
				DefaultResetPickups = false,
				DefaultAttackPermissions = (up: AllowUpwardAttack, left: AllowLeftAttack, right: AllowRightAttack),
				DisableBuiltinShortcut = false
			});
			_apiInitialized = true;
		}

		private IEnumerator LoadAllImages()
		{
			string folder = Path.Combine(Paths.PluginPath, "elesanren-Hard_Item_Randomizer", "nandu");
			string text = Path.Combine(folder, "4.png");
			if (File.Exists(text))
			{
				WWW www = new WWW("file://" + text);
				try
				{
					yield return www;
					if (string.IsNullOrEmpty(www.error) && (Object)(object)www.texture != (Object)null)
					{
						_backgroundSprite = Sprite.Create(www.texture, new Rect(0f, 0f, (float)((Texture)www.texture).width, (float)((Texture)www.texture).height), new Vector2(0.5f, 0.5f));
					}
				}
				finally
				{
					((IDisposable)www)?.Dispose();
				}
			}
			string[] iconFiles = new string[3] { "1.png", "2.png", "3.png" };
			for (int i = 0; i < 3; i++)
			{
				string text2 = Path.Combine(folder, iconFiles[i]);
				if (!File.Exists(text2))
				{
					continue;
				}
				WWW www = new WWW("file://" + text2);
				try
				{
					yield return www;
					if (string.IsNullOrEmpty(www.error) && (Object)(object)www.texture != (Object)null)
					{
						Sprite val = Sprite.Create(www.texture, new Rect(0f, 0f, (float)((Texture)www.texture).width, (float)((Texture)www.texture).height), new Vector2(0.5f, 0.5f));
						switch (i)
						{
						case 0:
							_beginnerIcon = val;
							break;
						case 1:
							_focusedIcon = val;
							break;
						case 2:
							_overflowIcon = val;
							break;
						}
					}
				}
				finally
				{
					((IDisposable)www)?.Dispose();
				}
			}
			_bgLoaded = true;
		}

		private void EnsureRandomSeed()
		{
			if (RandomSeed.Value == 0)
			{
				int num = (int)DateTime.UtcNow.Ticks ^ Environment.TickCount;
				if (num <= 0)
				{
					num = -num;
				}
				if (num <= 0)
				{
					num = 1;
				}
				RandomSeed.Value = num;
				GlobalConfig.Save();
			}
		}

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

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			if (((Scene)(ref scene)).name != "Menu_Title" && ((Scene)(ref scene)).name != "Menu" && ((Scene)(ref scene)).name != "Loading" && (Object)(object)HeroController.instance != (Object)null)
			{
				AllowUpwardAttack = GlobalConfig.AttackUp.Value;
				AllowLeftAttack = GlobalConfig.AttackLeft.Value;
				AllowRightAttack = GlobalConfig.AttackRight.Value;
				SharedRuntimeSettings.AttackUp = AllowUpwardAttack;
				SharedRuntimeSettings.AttackLeft = AllowLeftAttack;
				SharedRuntimeSettings.AttackRight = AllowRightAttack;
				_hasLoadedFromSaveData = true;
				LoadPlayerDataSettings();
				SharedRuntimeSettings.UseTypeMode = skillMode;
				SharedRuntimeSettings.SkillTotal = skillTotal;
				SharedRuntimeSettings.SkillVertical = skillV;
				SharedRuntimeSettings.SkillHorizontal = skillH;
				SharedRuntimeSettings.SkillSpecial = skillS;
				SharedRuntimeSettings.SkillAttack = skillA;
				SharedRuntimeSettings.ItemCount = StartingItemCount.Value;
				InitSceneRandomInstances();
				if (GetForceCompletionDisplay())
				{
					PlayerData instance = PlayerData.instance;
					if (instance != null && !instance.ConstructedFarsight)
					{
						instance.ConstructedFarsight = true;
						Log.LogInfo((object)$"已强制解锁完成度显示 (ConstructedFarsight) for profile {currentProfileID}");
					}
					RefreshCompletionUI(forceShow: true);
				}
				Log.LogInfo((object)($"[OnSceneLoaded] 场景 '{((Scene)(ref scene)).name}' 加载完成, _pendingApply={_pendingApply}, " + $"total={_pendingSkillTotal}, V={_pendingSkillV}, H={_pendingSkillH}, S={_pendingSkillS}, A={_pendingSkillA}, items={_pendingItemCount}"));
				if (_pendingApply)
				{
					Log.LogInfo((object)"[OnSceneLoaded] _pendingApply=true, 启动 DelayedGiveAfterSceneLoad 协程");
					((MonoBehaviour)this).StartCoroutine(DelayedGiveAfterSceneLoad());
				}
				else
				{
					Log.LogInfo((object)"[OnSceneLoaded] _pendingApply=false, 跳过给予流程");
				}
				if (_apiInitialized)
				{
					StartingAbilityPickerAPI.MarkGameReady();
				}
			}
			else if (((Scene)(ref scene)).name == "Menu_Title" || ((Scene)(ref scene)).name == "Menu")
			{
				_lastSceneWasMenu = true;
			}
			if (!GetForceCompletionDisplay())
			{
				ClearFsmCompletionVariables();
			}
		}

		private IEnumerator DelayedGiveAfterSceneLoad()
		{
			ManualLogSource log = Log;
			string[] obj = new string[5] { "[DelayedGiveAfterSceneLoad] 场景: ", null, null, null, null };
			Scene activeScene = SceneManager.GetActiveScene();
			obj[1] = ((Scene)(ref activeScene)).name;
			obj[2] = ", ";
			obj[3] = $"total={_pendingSkillTotal}, V={_pendingSkillV}, H={_pendingSkillH}, ";
			obj[4] = $"S={_pendingSkillS}, A={_pendingSkillA}, items={_pendingItemCount}";
			log.LogInfo((object)string.Concat(obj));
			float timeout = 15f;
			while (timeout > 0f && (PlayerData.instance == null || !((Object)(object)HeroController.instance != (Object)null) || !((Component)HeroController.instance).gameObject.activeInHierarchy))
			{
				yield return null;
				timeout -= Time.deltaTime;
			}
			if (timeout <= 0f)
			{
				Log.LogWarning((object)"[DelayedGiveAfterSceneLoad] 等待超时,放弃给予");
				_pendingApply = false;
				yield break;
			}
			yield return null;
			skillMode = _pendingSkillMode;
			skillTotal = _pendingSkillTotal;
			skillV = _pendingSkillV;
			skillH = _pendingSkillH;
			skillS = _pendingSkillS;
			skillA = _pendingSkillA;
			itemCount = _pendingItemCount;
			resetPickups = false;
			ApplySettings();
			_pendingApply = false;
		}

		private void GivePendingSkillsAndItems()
		{
			Log.LogInfo((object)($"[GivePendingSkillsAndItems] 开始给予 — mode={_pendingSkillMode}, " + $"total={_pendingSkillTotal}, V={_pendingSkillV}, H={_pendingSkillH}, S={_pendingSkillS}, A={_pendingSkillA}, items={_pendingItemCount}"));
			if (!_pendingSkillMode)
			{
				for (int i = 0; i < _pendingSkillTotal; i++)
				{
					SkillRandomizer.GiveRandomSkill();
				}
			}
			else
			{
				for (int j = 0; j < _pendingSkillV; j++)
				{
					SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.VerticalSkills);
				}
				for (int k = 0; k < _pendingSkillH; k++)
				{
					SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.HorizontalSkills);
				}
				for (int l = 0; l < _pendingSkillS; l++)
				{
					SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.SpecialSkills);
				}
				for (int m = 0; m < _pendingSkillA; m++)
				{
					SkillRandomizer.GiveRandomSkillFromCategory(SkillRandomizer.AttackSkills);
				}
			}
			for (int n = 0; n < _pendingItemCount; n++)
			{
				SavedItem randomItem = ItemRandomizer.GetRandomItem();
				if ((Object)(object)randomItem != (Object)null)
				{
					randomItem.TryGet(false, true);
				}
			}
			RoomRandomMode.TryApply();
			_pendingApply = false;
			showUI = false;
			Log.LogInfo((object)"技能和物品给予完成");
		}

		private void LoadPlayerDataSettings()
		{
			try
			{
				PlayerData instance = PlayerData.instance;
				if (instance != null)
				{
					skillMode = instance.GetBool("SkillRandomMode");
					skillTotal = instance.GetInt("SkillTotalCount");
					skillV = instance.GetInt("SkillVerticalCount");
					skillH = instance.GetInt("SkillHorizontalCount");
					skillS = instance.GetInt("SkillSpecialCount");
					skillA = instance.GetInt("SkillAttackCount");
					if (!skillMode && skillTotal == 0)
					{
						skillTotal = StartingSkillCount.Value;
					}
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"加载技能随机设置失败: {arg}");
			}
		}

		private void InitSceneRandomRefs()
		{
			_sceneRandomAvailable = false;
			try
			{
				_sceneLoaderType = Type.GetType("HKSilksong_Randomizer.RandomSceneLoader, HKSilksong_SceneRandomizer");
				_roomRandoType = Type.GetType("HKSilksong_Randomizer.RoomRando, HKSilksong_SceneRandomizer");
				_seedManagerType = Type.GetType("HKSilksong_Randomizer.SeedManager, HKSilksong_SceneRandomizer");
				if (_sceneLoaderType == null || _roomRandoType == null || _seedManagerType == null)
				{
					Log.LogWarning((object)"场景随机模块类型未找到,右侧面板将不可用");
					return;
				}
				_cfgShowSceneLabelField = _sceneLoaderType.GetField("cfgShowSceneLabel", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field = _sceneLoaderType.GetField("currentSceneName", BindingFlags.Instance | BindingFlags.NonPublic);
				_currentSceneNameField = field;
				MethodInfo method = _roomRandoType.GetMethod("GetGenerationSeed");
				_getSeedMethod = method;
				_sceneRandomAvailable = true;
				Log.LogInfo((object)"场景随机模块可用(静态接口)");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("场景随机模块初始化失败: " + ex.Message));
			}
		}

		private void InitSceneRandomInstances()
		{
			try
			{
				GameObject val = GameObject.Find("__RoomRando");
				GameObject val2 = GameObject.Find("__SeedManager");
				if ((Object)(object)val != (Object)null)
				{
					_roomRando = val.GetComponent(_roomRandoType);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					_seedManager = val2.GetComponent(_seedManagerType);
				}
				if (_seedManager != null)
				{
					_sceneLoader = _seedManager.GetType().GetField("sceneLoader", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_seedManager);
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("获取场景随机实例失败: " + ex.Message));
			}
		}

		private void LoadChosenProfiles()
		{
			chosenProfileSet.Clear();
			string[] array = ChosenProfiles.Value.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				if (int.TryParse(array[i].Trim(), out var result))
				{
					chosenProfileSet.Add(result);
				}
			}
		}

		internal void SaveChosenProfiles()
		{
			ChosenProfiles.Value = string.Join(",", chosenProfileSet);
			GlobalConfig.Save();
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)288) && currentProfileID != -1)
			{
				showUI = !showUI;
				if (showUI)
				{
					allowUpward = AllowUpwardAttack;
					allowLeft = AllowLeftAttack;
					allowRight = AllowRightAttack;
					itemCount = StartingItemCount.Value;
					resetPickups = false;
					seedInput = RandomSeed.Value.ToString();
				}
			}
			if (Input.GetKeyDown((KeyCode)9) && !GetForceCompletionDisplay())
			{
				ClearFsmCompletionVariables();
			}
			if (_pendingTeleport)
			{
				_pendingTeleport = false;
				((MonoBehaviour)this).StartCoroutine(DelayedTeleport(_pendingTeleportScene));
			}
		}

		private IEnumerator DelayedTeleport(string sceneName)
		{
			yield return HalfSecondWait;
			try
			{
				if (_sceneLoader != null)
				{
					object obj = _sceneLoader.GetType().GetField("cfgTeleportScene", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_sceneLoader);
					object obj2 = _sceneLoader.GetType().GetField("cfgTeleportConfirm", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_sceneLoader);
					obj?.GetType().GetProperty("Value")?.SetValue(obj, sceneName, null);
					obj2?.GetType().GetProperty("Value")?.SetValue(obj2, true, null);
					ShowNotification(Locale.Get("正在传送到 ") + sceneName + " ...");
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"传送失败: {arg}");
			}
		}

		private void OnGUI()
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0043: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			if (_notificationMessage != null && Time.time <= _notificationEndTime)
			{
				if (_notificationStyle == null)
				{
					_notificationStyle = new GUIStyle(GUI.skin.box)
					{
						fontSize = 40,
						alignment = (TextAnchor)4
					};
					_notificationStyle.normal.textColor = Color.white;
					_notificationStyle.normal.background = MakeTexture(2, 2, new Color(0f, 0f, 0f, 0.7f));
				}
				float num = 600f;
				float num2 = 120f;
				GUI.Box(new Rect(((float)Screen.width - num) / 2f, (float)(Screen.height / 2 - 100), num, num2), _notificationMessage, _notificationStyle);
			}
			else
			{
				_notificationMessage = null;
			}
			if (!showUI)
			{
				return;
			}
			if (((Rect)(ref _windowRect)).width == 0f || Mathf.Abs((float)Screen.height - _lastScreenHeight) > 1f)
			{
				float num3 = Screen.height;
				float num4 = 1080f;
				float num5 = 925f;
				float num6 = num3 / 8f;
				float num7 = num3 - num4 - num6;
				if (num7 < 0f)
				{
					num7 = 0f;
				}
				_windowRect = new Rect(20f, num7, num5, num4);
				_lastScreenHeight = num3;
			}
			_windowRect = GUILayout.Window(100, _windowRect, new WindowFunction(DrawUIWindow), Locale.Get("开局选项 & 场景随机"), Array.Empty<GUILayoutOption>());
		}

		private void DrawUIWindow(int windowID)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (PanelBackgroundEnabled.Value && (Object)(object)_backgroundSprite != (Object)null && (Object)(object)_backgroundSprite.texture != (Object)null)
			{
				GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height), (Texture)(object)_backgroundSprite.texture, (ScaleMode)0);
			}
			else
			{
				GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height), (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0, true, 0f, new Color(0.15f, 0.15f, 0.15f, 0.85f), 0f, 0f);
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(558f) });
			PanelRenderer.DrawLeftPanel(this);
			GUILayout.EndVertical();
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(270f) });
			PanelRenderer.DrawScenePanel(this);
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUI.DragWindow();
		}

		internal void ApplySettings()
		{
			Log.LogInfo((object)"ApplySettings 开始执行");
			StartingAbilityPickerAPI.SetAttackPermissions(allowUpward, allowLeft, allowRight);
			StartingAbilityPickerAPI.SetSkillRandomMode(skillMode);
			StartingAbilityPickerAPI.SetSkillCounts(skillTotal, skillV, skillH, skillS, skillA);
			StartingAbilityPickerAPI.SetStartingItemCount(itemCount);
			if (int.TryParse(seedInput, out var result))
			{
				StartingAbilityPickerAPI.SetSeed(result);
			}
			StartingAbilityPickerAPI.SetResetSeedWorld(resetPickups);
			StartingAbilityPickerAPI.SetFullRandomMode(DirectionPatch.FullRandomMode);
			StartingAbilityPickerAPI.SetCrestCurseEnabled(crestCurseEnabled);
			StartingAbilityPickerAPI.SetForceCompletionDisplay(GetForceCompletionDisplay());
			StartingAbilityPickerAPI.ApplyPending();
			_pendingSkillMode = skillMode;
			_pendingSkillTotal = skillTotal;
			_pendingSkillV = skillV;
			_pendingSkillH = skillH;
			_pendingSkillS = skillS;
			_pendingSkillA = skillA;
			_pendingItemCount = itemCount;
			if (resetPickups)
			{
				_pendingApply = true;
				Log.LogInfo((object)"重置种子世界,将在场景加载完成后给予技能和物品");
				ResetSeedWorld();
			}
			else
			{
				GivePendingSkillsAndItems();
				RoomRandomMode.TryApply();
				showUI = false;
			}
			Log.LogInfo((object)"ApplySettings 执行完成");
			StartingAbilityPickerAPI.SaveAllSettingsToConfig();
		}

		private void ResetSeedWorld()
		{
			if (!int.TryParse(seedInput, out var result) || result == RandomSeed.Value)
			{
				result = new Random().Next(1, int.MaxValue);
			}
			seedInput = result.ToString();
			RandomSeed.Value = result;
			GlobalConfig.Save();
			TrySyncOtherMods(result);
			try
			{
				PlayerData instance = PlayerData.instance;
				if (instance == null)
				{
					return;
				}
				FieldInfo[] fields = typeof(PlayerData).GetFields(BindingFlags.Instance | BindingFlags.Public);
				int num = 0;
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					if (fieldInfo.Name.StartsWith("SkillTriggered_"))
					{
						fieldInfo.SetValue(instance, false);
						num++;
					}
				}
				Log.LogInfo((object)$"已重置 {num} 个技能触发器记录");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"重置技能触发器失败: {arg}");
			}
		}

		public static void ResetSeedWorldExternal(int newSeed)
		{
			seedInput = newSeed.ToString();
			RandomSeed.Value = newSeed;
			GlobalConfig.Save();
			Instance.TrySyncOtherMods(newSeed);
			try
			{
				PlayerData instance = PlayerData.instance;
				if (instance == null)
				{
					return;
				}
				FieldInfo[] fields = typeof(PlayerData).GetFields(BindingFlags.Instance | BindingFlags.Public);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.Name.StartsWith("SkillTriggered_"))
					{
						fieldInfo.SetValue(instance, false);
					}
				}
			}
			catch
			{
			}
		}

		private void TrySyncOtherMods(int newSeed)
		{
			try
			{
				Type type = Type.GetType("SilksongItemRandomizer.Plugin, SilksongItemRandomizer");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("RandomSeed", BindingFlags.Static | BindingFlags.Public);
					if (property != null && property.GetValue(null) is ConfigEntry<int> val)
					{
						val.Value = newSeed;
					}
					type.GetMethod("ResetAllStaticData", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
				}
			}
			catch
			{
			}
			try
			{
				Type type2 = Type.GetType("SkillTriggerMod.Plugin, SkillTriggerMod");
				if (type2 != null)
				{
					PropertyInfo property2 = type2.GetProperty("RandomSeed", BindingFlags.Static | BindingFlags.Public);
					if (property2 != null && property2.GetValue(null) is ConfigEntry<int> val2)
					{
						val2.Value = newSeed;
					}
					Type.GetType("SkillTriggerMod.SkillRandomizer, SkillTriggerMod")?.GetMethod("SetSeed", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { newSeed });
					type2.GetMethod("ResetAllRecords", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
				}
				Plugin.SaveData.SkillTriggerRecords.Clear();
				Plugin.SaveGlobalData();
			}
			catch
			{
			}
			try
			{
				Type? type3 = Type.GetType("SilksongItemRandomizer.CrestRandomizer, SilksongItemRandomizer");
				type3?.GetMethod("ResetMappings", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
				type3?.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
				Type.GetType("SilksongItemRandomizer.CrestRandomizePatch, SilksongItemRandomizer")?.GetMethod("ResetProcessedIds", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
				Type.GetType("SilksongItemRandomizer.BenchRespawnPatch, SilksongItemRandomizer")?.GetMethod("ResetCooldown", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null);
			}
			catch
			{
			}
		}

		public int GetCurrentSeed()
		{
			if (_sceneLoaderType == null)
			{
				return 0;
			}
			try
			{
				if (_currentSeedField == null)
				{
					_currentSeedField = _sceneLoaderType.GetField("CurrentSeed", BindingFlags.Static | BindingFlags.Public);
				}
				FieldInfo currentSeedField = _currentSeedField;
				if (currentSeedField != null)
				{
					return (int)currentSeedField.GetValue(null);
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("获取当前种子失败: " + ex.Message));
			}
			return 0;
		}

		public string GetCurrentSceneName()
		{
			if (_sceneLoader == null)
			{
				return "";
			}
			try
			{
				return (string)_currentSceneNameField?.GetValue(_sceneLoader);
			}
			catch
			{
				return "";
			}
		}

		public bool GetSceneRandomEnabled()
		{
			if (_sceneLoaderType == null)
			{
				return false;
			}
			try
			{
				if (_enableRandomizationField == null)
				{
					_enableRandomizationField = _sceneLoaderType.GetField("EnableRandomization", BindingFlags.Static | BindingFlags.Public);
				}
				FieldInfo enableRandomizationField = _enableRandomizationField;
				if (enableRandomizationField != null)
				{
					return (bool)enableRandomizationField.GetValue(null);
				}
			}
			catch
			{
			}
			return false;
		}

		public void SetSceneRandomEnabled(bool enabled)
		{
			if (_sceneLoaderType == null)
			{
				return;
			}
			try
			{
				if (_enableRandomizationField == null)
				{
					_enableRandomizationField = _sceneLoaderType.GetField("EnableRandomization", BindingFlags.Static | BindingFlags.Public);
				}
				_enableRandomizationField?.SetValue(null, enabled);
				if (_sceneLoader != null)
				{
					FieldInfo field = _sceneLoaderType.GetField("cfgEnableRandomization", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field != null)
					{
						object value = field.GetValue(_sceneLoader);
						value?.GetType().GetProperty("Value")?.SetValue(value, enabled, null);
					}
				}
			}
			catch
			{
			}
		}

		public bool GetShowSceneLabel()
		{
			if (_cfgShowSceneLabelField != null && _sceneLoader != null)
			{
				try
				{
					object value = _cfgShowSceneLabelField.GetValue(_sceneLoader);
					object obj = value?.GetType().GetProperty("Value")?.GetValue(value);
					if (obj is bool)
					{
						return (bool)obj;
					}
				}
				catch
				{
				}
			}
			return true;
		}

		public void SetShowSceneLabel(bool value, bool isSeed = false)
		{
			try
			{
				if (!isSeed)
				{
					if (_cfgShowSceneLabelField != null && _sceneLoader != null)
					{
						object value2 = _cfgShowSceneLabelField.GetValue(_sceneLoader);
						value2?.GetType().GetProperty("Value")?.SetValue(value2, value, null);
					}
				}
				else if (_seedManager != null)
				{
					object obj = _seedManager.GetType().GetField("cfgShowSeedOnScreen", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_seedManager);
					obj?.GetType().GetProperty("Value")?.SetValue(obj, value, null);
				}
			}
			catch
			{
			}
		}

		public bool GetShowSeedLabel()
		{
			try
			{
				if (_seedManager != null)
				{
					object obj = _seedManager.GetType().GetField("cfgShowSeedOnScreen", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(_seedManager);
					return (bool)(obj?.GetType().GetProperty("Value")?.GetValue(obj) ?? ((object)true));
				}
			}
			catch
			{
			}
			return true;
		}

		public bool GetForceCompletionDisplay()
		{
			int num = currentProfileID;
			if (num == -1)
			{
				return true;
			}
			if (Plugin.SaveData.ProfileCompletionDisplay.TryGetValue(num, out var value))
			{
				return value;
			}
			return true;
		}

		private void RefreshCompletionUI(bool forceShow = false)
		{
			if (!GetForceCompletionDisplay() && !forceShow)
			{
				ClearFsmCompletionVariables();
				return;
			}
			PlayerData instance = PlayerData.instance;
			if (instance == null)
			{
				return;
			}
			string value = Mathf.RoundToInt(instance.completionPercentage) + "%";
			string[] array = new string[4] { "Inv", "Tools", "Journal", "Quests" };
			for (int i = 0; i < array.Length; i++)
			{
				GameObject val = GameObject.Find(array[i]);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				PlayMakerFSM component = val.GetComponent<PlayMakerFSM>();
				if (!((Object)(object)component == (Object)null))
				{
					FsmString val2 = component.FsmVariables.FindFsmString("Completion Percentage Str");
					if (val2 != null)
					{
						val2.Value = value;
					}
				}
			}
		}

		private void ClearFsmCompletionVariables()
		{
			try
			{
				string[] array = new string[4] { "Inv", "Tools", "Journal", "Quests" };
				for (int i = 0; i < array.Length; i++)
				{
					GameObject val = GameObject.Find(array[i]);
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					PlayMakerFSM component = val.GetComponent<PlayMakerFSM>();
					if ((Object)(object)component == (Object)null)
					{
						continue;
					}
					FsmString[] stringVariables = component.FsmVariables.StringVariables;
					foreach (FsmString val2 in stringVariables)
					{
						if (((NamedVariable)val2).Name.IndexOf("Completion", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							val2.Value = "";
						}
					}
				}
			}
			catch (Exception arg)
			{
				Log.LogWarning((object)$"清空完成度变量失败: {arg}");
			}
		}

		public bool GetItemRandomEnabled()
		{
			try
			{
				if (_publicItemRandomProp == null)
				{
					_publicItemRandomProp = Type.GetType("SilksongItemRandomizer.Plugin, SilksongItemRandomizer")?.GetProperty("PublicItemRandomEnabled", BindingFlags.Static | BindingFlags.Public);
				}
				return _publicItemRandomProp != null && (bool)_publicItemRandomProp.GetValue(null);
			}
			catch
			{
			}
			return false;
		}

		public void ApplyStartingSettings()
		{
			GivePendingSkillsAndItems();
		}

		public void SetItemRandomEnabled(bool value)
		{
			try
			{
				if (_publicItemRandomProp == null)
				{
					_publicItemRandomProp = Type.GetType("SilksongItemRandomizer.Plugin, SilksongItemRandomizer")?.GetProperty("PublicItemRandomEnabled", BindingFlags.Static | BindingFlags.Public);
				}
				_publicItemRandomProp?.SetValue(null, value);
			}
			catch
			{
			}
		}

		public void SetEnemyRandoAdjustEnabled(bool value)
		{
			EnemyRandoAdjustEnabled.Value = value;
			GlobalConfig.Save();
			try
			{
				Type type = Type.GetType("SilksongItemRandomizer.EnemyRandoAdjuster, SilksongItemRandomizer");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("Enabled", BindingFlags.Static | BindingFlags.Public);
					if (property != null)
					{
						property.SetValue(null, value);
					}
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"设置怪物调整开关失败: {arg}");
			}
		}

		public void SetPanelBackgroundEnabled(bool value)
		{
			PanelBackgroundEnabled.Value = value;
		}
	}
	[HarmonyPatch(typeof(SaveStats), "GetCompletionPercentage")]
	public static class SaveStats_GetCompletionPercentage_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(ref string __result)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && !Plugin.Instance.GetForceCompletionDisplay())
			{
				__result = "";
			}
		}
	}
	[HarmonyPatch(typeof(SaveStats), "get_UnlockedCompletionRate")]
	public static class SaveStats_UnlockedCompletionRate_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(ref bool __result)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && !Plugin.Instance.GetForceCompletionDisplay())
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerData), "CountGameCompletion")]
	public static class PlayerData_CountGameCompletion_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				return Plugin.Instance.GetForceCompletionDisplay();
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ConvertFloatToString), "OnEnter")]
	public static class ConvertFloatToString_Patch
	{
		private static void Postfix(ConvertFloatToString __instance)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && !Plugin.Instance.GetForceCompletionDisplay() && __instance.stringVariable != null && ((NamedVariable)__instance.stringVariable).Name == "Completion Percentage Str")
			{
				__instance.stringVariable.Value = "";
			}
		}
	}
	[HarmonyPatch(typeof(BuildString), "OnEnter")]
	public static class BuildString_Patch
	{
		private static void Postfix(BuildString __instance)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && !Plugin.Instance.GetForceCompletionDisplay() && __instance.storeResult != null && ((NamedVariable)__instanc