Decompiled source of PeakTcnPatch v2.1.0

ue.Peak.TcnPatch.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using ue.Peak.TcnPatch.API;
using ue.Peak.TcnPatch.Adapters;
using ue.Peak.TcnPatch.Core;
using ue.Peak.TcnPatch.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ue.Peak.TcnPatch")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.5.7.0")]
[assembly: AssemblyInformationalVersion("1.5.7+66ae37b0ce94abe7fb3220489ab5e3ad1c3fb0e5")]
[assembly: AssemblyProduct("ue.Peak.TcnPatch")]
[assembly: AssemblyTitle("ue.Peak.TcnPatch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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;
		}
	}
	[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;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class ExtensionMarkerAttribute : Attribute
	{
		private readonly string <Name>k__BackingField;

		public string Name => <Name>k__BackingField;

		public ExtensionMarkerAttribute(string name)
		{
			<Name>k__BackingField = name;
		}
	}
}
namespace ue.Peak.TcnPatch
{
	[BepInPlugin("ue.Peak.TcnPatch", "ue.Peak.TcnPatch", "2.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "ue.Peak.TcnPatch";

		public const string ModName = "ue.Peak.TcnPatch";

		public const string ModVersion = "2.1.0";

		private static FileSystemWatcher _watcher;

		public const string TcnTranslationFileName = "TcnTranslations.json";

		private static readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);

		private static readonly VersionTextUpdater _versionStringUpdater = new VersionTextUpdater();

		[CanBeNull]
		private Harmony _harmony;

		private bool _hasSetTraditionalChineseFont;

		private static readonly HttpClient _httpClient = new HttpClient();

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static TranslationFile CurrentTranslationFile { get; private set; } = new TranslationFile();

		internal static PluginConfig ModConfig { get; private set; }

		[CanBeNull]
		internal static VersionString VersionStringInstance { get; set; }

		internal static Dictionary<string, string> TranslationsLookup { get; } = new Dictionary<string, string>();

		internal static Dictionary<string, string> AdditionalTranslationsLookup { get; } = new Dictionary<string, string>();

		internal static Dictionary<string, string> KeyToUnlocalizedLookup { get; } = new Dictionary<string, string>();

		private void Awake()
		{
			Instance = this;
			ModConfig = new PluginConfig(((BaseUnityPlugin)this).Config);
			ModConfig.EnableAutoDumpLanguage.SettingChanged += delegate
			{
				if (ModConfig.EnableAutoDumpLanguage.Value)
				{
					LocalizedTextPatch.DumpLanguageEntries();
				}
			};
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"正在載入模組 - ue.Peak.TcnPatch");
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "ue.Peak.TcnPatch");
			ue.Peak.TcnPatch.API.TcnPatch internalInstance = ue.Peak.TcnPatch.API.TcnPatch.InternalInstance;
			internalInstance.RegisterLocalizationKey("PeakTcnPatch.Passport.Crabland", "CRABLAND");
			internalInstance.RegisterLocalizationKey("PeakTcnPatch.BoardingPass.CustomExpedition", "CUSTOM EXPEDITION");
			MoreAscentsSupport.RegisterLocalizations();
			Logger.LogInfo((object)"已載入模組 - ue.Peak.TcnPatch");
			Logger.LogInfo((object)"  + 非官方繁體中文翻譯支援模組 -- by悠依");
		}

		private void Start()
		{
			string path = Path.Combine(Paths.ConfigPath, "ue.Peak.TcnPatch");
			Directory.CreateDirectory(path);
			_watcher = new FileSystemWatcher(path, "*.json");
			_watcher.NotifyFilter = NotifyFilters.LastWrite;
			_watcher.Changed += delegate(object _, FileSystemEventArgs args)
			{
				if (args.Name == "TcnTranslations.json")
				{
					Logger.LogInfo((object)"正在更新遊戲內繁體中文翻譯資料...");
					UpdateMainTable();
				}
			};
			if (!ModConfig.DownloadFromRemote.Value)
			{
				UpdateMainTable();
			}
			else
			{
				Task.Run(async delegate
				{
					if (!(await DownloadTranslationsAsync()).IsSuccess)
					{
						UpdateMainTable();
					}
				});
			}
			_watcher.EnableRaisingEvents = true;
		}

		private void Update()
		{
			if (Object.op_Implicit((Object)(object)VersionStringInstance))
			{
				_versionStringUpdater.Update(VersionStringInstance);
			}
			SetTraditionalChineseFont();
		}

		private void SetTraditionalChineseFont()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			if (!_hasSetTraditionalChineseFont && Object.op_Implicit((Object)(object)FontFallbackSwapper.instance))
			{
				_hasSetTraditionalChineseFont = true;
				if ((int)LocalizedText.CURRENT_LANGUAGE == 10)
				{
					FontFallbackSwapper.instance.SwitchToTraditional();
				}
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_lock.Dispose();
		}

		private static async Task SaveTranslationsAsync(string content)
		{
			string dir = Path.Combine(Paths.ConfigPath, "ue.Peak.TcnPatch");
			Directory.CreateDirectory(dir);
			string path = Path.Combine(dir, "TcnTranslations.json");
			await _lock.EnterScopeAsync(async delegate
			{
				await using FileStream targetStream = File.Open(path, FileMode.Create, FileAccess.Write);
				await using StreamWriter writer = new StreamWriter(targetStream);
				await writer.WriteAsync(content);
			});
		}

		private async Task<Result<Unit, Exception>> DownloadTranslationsAsync()
		{
			string url = ModConfig.DownloadUrl.Value;
			for (int i = 0; i < 2; i++)
			{
				Logger.LogInfo((object)"正在從遠端下載翻譯資料... (可以在模組設定停用)");
				Logger.LogInfo((object)("網址:" + url));
				HttpClient client = _httpClient;
				try
				{
					string content = await client.GetStringAsync(url);
					try
					{
						JObject.Parse(content);
					}
					catch (Exception ex)
					{
						Exception e = ex;
						Logger.LogWarning((object)"無效的遠端翻譯資料!將使用本機資料。");
						Logger.LogWarning((object)e);
						return Result.Error(e);
					}
					await SaveTranslationsAsync(content);
					Logger.LogInfo((object)"翻譯資料下載完成!");
					return Result.Success(Unit.Instance);
				}
				catch (HttpRequestException ex2)
				{
					if (i > 0 || ModConfig.DownloadFailureHandling.Value == DownloadFailureHandling.UseLocal)
					{
						Logger.LogError((object)"翻譯資料下載失敗!將使用本機資料。");
						Logger.LogError((object)ex2);
						return Result.Error((Exception)ex2);
					}
					Logger.LogError((object)"翻譯資料下載失敗!將嘗試使用預設的遠端資料。");
					url = (string)((ConfigEntryBase)ModConfig.DownloadUrl).DefaultValue;
				}
				catch (Exception ex3)
				{
					Logger.LogError((object)"翻譯資料下載失敗!將使用本機資料。");
					Logger.LogError((object)ex3);
					return Result.Error(ex3);
				}
			}
			return Result.Error(new Exception("unreachable"));
		}

		internal static Option<string> GetVanilla(string id)
		{
			return TranslationsLookup.GetOptional(id.ToUpperInvariant());
		}

		internal static Option<string> GetRegistered(string id, Language? language)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Language valueOrDefault = language.GetValueOrDefault();
			if (!language.HasValue)
			{
				valueOrDefault = LocalizedText.CURRENT_LANGUAGE;
				language = valueOrDefault;
			}
			return (((int)language.GetValueOrDefault() == 10) ? AdditionalTranslationsLookup.GetOptional(id) : Option<string>.None).OrGet(() => KeyToUnlocalizedLookup.GetOptional(id));
		}

		private static void UpdateMainTable()
		{
			ControlFlow<Unit, Unit> controlFlow = _lock.EnterScope(() => TryReadFromJson("TcnTranslations.json", (Func<JObject>)(() => new JObject())).SelectMany(TranslationFile.TryDeserialize).Select((Func<TranslationFile, ControlFlow<Unit, Unit>>)delegate(TranslationFile f)
			{
				CurrentTranslationFile = f;
				return ControlFlow.Continue();
			}).SelectError((Func<Exception, ControlFlow<Unit, Unit>>)delegate(Exception ex)
			{
				if (ex is TranslationParseException ex2)
				{
					Logger.LogError((object)ex2.UserMessage);
					Logger.LogError((object)"翻譯資料分析失敗!");
				}
				else
				{
					Logger.LogError((object)"翻譯資料分析失敗!");
					Logger.LogError((object)ex);
				}
				return ControlFlow.Break();
			})
				.Branch());
			if (controlFlow.IsBreak)
			{
				return;
			}
			if (CurrentTranslationFile.Authors.Count > 0)
			{
				Logger.LogInfo((object)("翻譯資料作者:" + string.Join("、", CurrentTranslationFile.Authors)));
			}
			else
			{
				Logger.LogInfo((object)"翻譯資料作者:未知");
			}
			Dictionary<string, List<string>> mainTable = LocalizedText.mainTable;
			HashSet<string> hashSet = mainTable.Keys.ToHashSet();
			TranslationsLookup.Clear();
			AdditionalTranslationsLookup.Clear();
			string value;
			string key;
			foreach (KeyValuePair<string, string> translation in CurrentTranslationFile.Translations)
			{
				translation.Deconstruct(out value, out key);
				string text = value;
				string value2 = key;
				string text2 = text.ToUpperInvariant();
				if (TranslationsLookup.ContainsKey(text2))
				{
					Logger.LogInfo((object)("發現重複的翻譯key:「" + text + "」!已存在大寫的同名key!"));
					continue;
				}
				if (!mainTable.ContainsKey(text2) && ModConfig.WarnUnknownTranslationKeys.Value)
				{
					Logger.LogWarning((object)("正在使用未知的翻譯key:「" + text2 + "」!"));
				}
				TranslationsLookup[text2] = value2;
				hashSet.Remove(text2);
			}
			foreach (KeyValuePair<string, string> additionalTranslation in CurrentTranslationFile.AdditionalTranslations)
			{
				additionalTranslation.Deconstruct(out key, out value);
				string text3 = key;
				string value3 = value;
				AdditionalTranslationsLookup[text3] = value3;
				hashSet.Remove(text3);
			}
			HashSet<string> vanillaLocalizationKeys = LocalizedTextPatch.VanillaLocalizationKeys;
			foreach (string item in hashSet)
			{
				if (vanillaLocalizationKeys.Contains(item))
				{
					Logger.LogWarning((object)("缺少「" + item + "」翻譯key,請更新翻譯資料!"));
				}
				else if (ModConfig.WarnMissingAdditionalKeys.Value)
				{
					Logger.LogWarning((object)("*附加翻譯* 缺少「" + item + "」翻譯key!"));
				}
			}
			LocalizedText.RefreshAllText();
		}

		private static Result<T, Exception> TryReadFromJson<T>(string fileName, Func<T> defaultContent) where T : class
		{
			Result<string, Exception> result = Result.Catch(delegate
			{
				string text = Path.Combine(Paths.ConfigPath, "ue.Peak.TcnPatch");
				Directory.CreateDirectory(text);
				string text2 = Path.Combine(text, fileName);
				if (File.Exists(text2))
				{
					return text2;
				}
				string contents = JsonConvert.SerializeObject((object)defaultContent());
				File.WriteAllText(text2, contents);
				return text2;
			});
			return result.IfError(delegate(Exception e)
			{
				Logger.LogError((object)("無法初始化 JSON 設定:" + fileName));
				Logger.LogError((object)e);
			}).SelectMany<T>(DeserializeFromPath);
			Result<T, Exception> DeserializeFromPath(string path)
			{
				return Result.Catch(delegate
				{
					using FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
					using StreamReader streamReader = new StreamReader(stream);
					return JsonConvert.DeserializeObject<T>(streamReader.ReadToEnd());
				}).IfError(delegate(Exception e)
				{
					Logger.LogError((object)("無法讀取 JSON 設定:" + fileName));
					Logger.LogError((object)e);
				});
			}
		}
	}
	public class PluginConfig
	{
		public ConfigEntry<bool> DownloadFromRemote { get; } = config.Bind<bool>("Update", "DownloadFromRemote", true, "是否每次啟動都要從遠端下載最新的翻譯資料? (true: 是, false: 否)");

		public ConfigEntry<string> DownloadUrl { get; } = config.Bind<string>("Update", "DownloadUrl", "https://raw.githubusercontent.com/Yuieii/ue.Peak.TcnPatch/refs/heads/master/TcnTranslations.json", "翻譯資料的 URL");

		public ConfigEntry<DownloadFailureHandling> DownloadFailureHandling { get; } = config.Bind<DownloadFailureHandling>("Update", "DownloadFailureHandling", ue.Peak.TcnPatch.DownloadFailureHandling.UseDefaultRemote, "當設定的 URL 下載失敗時如何處理");

		public ConfigEntry<Language> AutoDumpLanguage { get; } = config.Bind<Language>("Debug", "AutoDumpLanguage", (Language)9, "自動輸出官方參考翻譯時選擇的原始語言");

		public ConfigEntry<bool> EnableAutoDumpLanguage { get; } = config.Bind<bool>("Debug", "EnableAutoDumpLanguage", true, string.Join('\n', "是否自動輸出遊戲內的翻譯表以供參考", " (有 ModConfig 的話即時更改可以重新輸出)"));

		public ConfigEntry<bool> WarnUnknownTranslationKeys { get; } = config.Bind<bool>("Debug", "WarnUnknownTranslationKeys", false, "有未知的非附加翻譯key時是否觸發警告");

		public ConfigEntry<bool> WarnMissingAdditionalKeys { get; } = config.Bind<bool>("Debug", "WarnMissingAdditionalKeys", false, "有缺失的附加翻譯key時是否觸發警告");

		public ConfigEntry<bool> ShowPatchCredit { get; } = config.Bind<bool>("Patch", "ShowPatchCredit", true, "在主畫面版本文字下方顯示本模組作者?");

		public ConfigEntry<bool> ShowTranslatorCredit { get; } = config.Bind<bool>("Patch", "ShowTranslatorCredit", true, "在主畫面版本文字下方顯示翻譯資料的作者?");

		public ConfigEntry<bool> ShowModVersionInPatchCredit { get; } = config.Bind<bool>("Patch", "ShowModVersionInPatchCredit", true, "在主畫面版本文字後面顯示這個模組的版本? (v2.1.0)");

		public PluginConfig(ConfigFile config)
		{
		}
	}
	public enum DownloadFailureHandling
	{
		UseLocal,
		UseDefaultRemote
	}
	internal static class ReflectionExtensions
	{
		[SpecialName]
		public sealed class <G>$8048A6C8BE30A622530249B904B537EB<$T0>
		{
			[SpecialName]
			public static class <M>$B99A874B2F9892B4D9EADD5CC9D40768
			{
			}

			[ExtensionMarker("<M>$B99A874B2F9892B4D9EADD5CC9D40768")]
			public TValue GetReflectionFieldValue<TValue>(TypedFieldInfo<$T0, TValue> fieldInfo)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$B99A874B2F9892B4D9EADD5CC9D40768")]
			public void SetReflectionFieldValue<TValue>(TypedFieldInfo<$T0, TValue> fieldInfo, TValue value)
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$C0F9324A7FB6D595E082877B54F807CC
		{
			[SpecialName]
			public static class <M>$4776623D3010553C7D2AB93E76A250FB
			{
			}

			[ExtensionMarker("<M>$4776623D3010553C7D2AB93E76A250FB")]
			[CanBeNull]
			public TypedFieldInfo<TOwner, TValue> AsTyped<TOwner, TValue>()
			{
				throw new NotSupportedException();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static TValue GetReflectionFieldValue<TOwner, TValue>(this TOwner owner, TypedFieldInfo<TOwner, TValue> fieldInfo)
		{
			return (TValue)fieldInfo.FieldInfo.GetValue(owner);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void SetReflectionFieldValue<TOwner, TValue>(this TOwner owner, TypedFieldInfo<TOwner, TValue> fieldInfo, TValue value)
		{
			fieldInfo.FieldInfo.SetValue(owner, value);
		}

		[CanBeNull]
		public static TypedFieldInfo<TOwner, TValue> AsTyped<TOwner, TValue>([CanBeNull] this FieldInfo field)
		{
			return field;
		}
	}
	public static class Refl
	{
		public static class LoadingScreenAnimation
		{
			public static TypedFieldInfo<LoadingScreenAnimation, string> LoadingString { get; } = AccessTools.Field(typeof(LoadingScreenAnimation), "loadingString");

			public static TypedFieldInfo<LoadingScreenAnimation, float> DefaultLoadingStringLength { get; } = AccessTools.Field(typeof(LoadingScreenAnimation), "defaultLoadingStringLength");
		}

		public static class LocalizedText
		{
			public static TypedFieldInfo<LocalizedText, Language> CurrentLanguage { get; } = AccessTools.Field(typeof(LocalizedText), "CURRENT_LANGUAGE");
		}

		public static class VersionString
		{
			public static TypedFieldInfo<VersionString, TextMeshProUGUI> Text { get; } = AccessTools.Field(typeof(VersionString), "m_text");
		}
	}
	public class TypedFieldInfo<TOwner, TValue>(FieldInfo fieldInfo)
	{
		public FieldInfo FieldInfo { get; } = fieldInfo;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static implicit operator TypedFieldInfo<TOwner, TValue>(FieldInfo fieldInfo)
		{
			return (fieldInfo == null) ? null : new TypedFieldInfo<TOwner, TValue>(fieldInfo);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static implicit operator FieldInfo(TypedFieldInfo<TOwner, TValue> fieldInfo)
		{
			return fieldInfo?.FieldInfo;
		}

		public TValue GetStaticValue()
		{
			return (TValue)FieldInfo.GetValue(null);
		}
	}
	public class TranslationParseException : Exception
	{
		public string UserMessage { get; }

		public TranslationParseException(string message, string userMessage)
			: base(message)
		{
			UserMessage = userMessage;
		}

		public TranslationParseException(string message)
			: base(message)
		{
			UserMessage = message;
		}
	}
	public class TranslationFile
	{
		public const int CurrentFormatVersion = 0;

		public const string FormatVersionKey = "FormatVersion";

		public const string AuthorKey = "Authors";

		public const string TranslationEntriesKey = "Translations";

		public const string AdditionalTranslationEntriesKey = "AdditionalTranslations";

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

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

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

		public static Result<TranslationFile, Exception> TryDeserialize(JObject obj)
		{
			return Result.Catch(() => Deserialize(obj));
		}

		public static TranslationFile Deserialize(JObject obj)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between Unknown and I4
			//IL_0078: 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)
			string[] source = new string[2] { "FormatVersion", "Translations" };
			if (!((IEnumerable<string>)source).All((Func<string, bool>)obj.ContainsKey))
			{
				return InternalDeserializeFromLegacy(obj);
			}
			TranslationFile result = new TranslationFile();
			JToken val = obj["FormatVersion"];
			if ((int)val.Type != 6)
			{
				throw new TranslationParseException($"Format version must be an integer value, found {val.Type}", "無效的格式版本!格式版本必須為一個整數!");
			}
			int num = Extensions.Value<int>((IEnumerable<JToken>)val);
			if (num > 0)
			{
				Plugin.Logger.LogWarning((object)"正在讀取過新版本的翻譯資料!可能會無法正確讀取。");
			}
			((IDictionary<string, JToken>)obj).GetOptional("Authors").IfSome(delegate(JToken authorsToken)
			{
				JArray val6 = (JArray)(object)((authorsToken is JArray) ? authorsToken : null);
				if (val6 != null)
				{
					foreach (JToken item in val6)
					{
						result.Authors.Add(Extensions.Value<string>((IEnumerable<JToken>)item));
					}
					return;
				}
				JValue val7 = (JValue)(object)((authorsToken is JValue) ? authorsToken : null);
				if (val7 != null)
				{
					result.Authors.Add(Extensions.Value<string>((IEnumerable<JToken>)val7));
				}
				else
				{
					Plugin.Logger.LogWarning((object)"無效的翻譯者資料! (Authors)");
				}
			});
			JToken val2 = obj["Translations"];
			JObject val3 = (JObject)(object)((val2 is JObject) ? val2 : null);
			if (val3 == null)
			{
				throw new TranslationParseException($"Translation entries must be an object, found {val2.Type}", "無效的翻譯資料! (Translations)");
			}
			foreach (var (key, val5) in val3)
			{
				result.Translations[key] = Extensions.Value<string>((IEnumerable<JToken>)val5);
			}
			((IDictionary<string, JToken>)obj).GetOptional("AdditionalTranslations").IfSome(delegate(JToken entries)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				JObject val6 = (JObject)(object)((entries is JObject) ? entries : null);
				if (val6 == null)
				{
					throw new TranslationParseException($"Additional translation entries must be an object, found {entries.Type}", "無效的附加翻譯資料! (AdditionalTranslations)");
				}
				List<string> list = new List<string>();
				foreach (var (text3, val8) in val6)
				{
					if (list.Contains<string>(text3, StringComparer.InvariantCultureIgnoreCase))
					{
						Plugin.Logger.LogWarning((object)("翻譯資料出現已註冊過的附加翻譯key「" + text3 + "」!新的同名翻譯將會被忽略。"));
					}
					else
					{
						list.Add(text3);
						result.AdditionalTranslations[text3] = Extensions.Value<string>((IEnumerable<JToken>)val8);
					}
				}
			});
			return result;
		}

		private static TranslationFile InternalDeserializeFromLegacy(JObject obj)
		{
			TranslationFile translationFile = new TranslationFile();
			foreach (var (key, val2) in obj)
			{
				translationFile.Translations[key] = Extensions.Value<string>((IEnumerable<JToken>)val2);
			}
			return translationFile;
		}
	}
	public static class Utils
	{
		public static Option<T> ToOptionUnity<T>(this T obj) where T : Object
		{
			return ((Object)(object)obj == (Object)null) ? ((Option<T>)Option.None) : Option.Some(obj);
		}

		public static Task WaitForFramesAsync(int frames)
		{
			TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
			((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayFramesCoroutine(taskCompletionSource, frames, () => true));
			return taskCompletionSource.Task;
		}

		public static async Task WaitForNextFrameAsync()
		{
			await WaitForFramesAsync(1);
		}

		private static IEnumerator DelayFramesCoroutine<T>(TaskCompletionSource<T> source, int frames, Func<T> resultGetter)
		{
			for (int i = 0; i < frames; i++)
			{
				yield return (object)new WaitForEndOfFrame();
			}
			source.SetResult(resultGetter());
		}
	}
	public enum ReturnFlow
	{
		Continue,
		Break
	}
	public class VersionTextUpdater
	{
		[CanBeNull]
		private string _originalText;

		public void Update(VersionString instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)LocalizedText.CURRENT_LANGUAGE != 10 || !Plugin.ModConfig.ShowPatchCredit.Value)
			{
				return;
			}
			TypedFieldInfo<VersionString, TextMeshProUGUI> text = Refl.VersionString.Text;
			if (text == null)
			{
				return;
			}
			TextMeshProUGUI reflectionFieldValue = instance.GetReflectionFieldValue(text);
			if (_originalText == null)
			{
				_originalText = ((TMP_Text)reflectionFieldValue).text;
			}
			string text2 = "繁中翻譯by: " + string.Join("、", Plugin.CurrentTranslationFile.Authors);
			string text3 = (Plugin.ModConfig.ShowModVersionInPatchCredit.Value ? "繁中支援v2.1.0 by悠依" : "繁中支援by悠依");
			bool flag = Plugin.ModConfig.ShowTranslatorCredit.Value && Plugin.CurrentTranslationFile.Authors.Count > 0;
			string name = ((Object)((Component)((Component)instance).transform.GetParent()).gameObject).name;
			string name2 = ((Object)((Component)instance).gameObject).name;
			((TMP_Text)reflectionFieldValue).text = _originalText;
			if (name2 == "Version" && name == "Logo")
			{
				string text4 = ((flag & (Math.Floor(Time.realtimeSinceStartup / 10f) % 2.0 != 0.0)) ? text2 : text3);
				((TMP_Text)reflectionFieldValue).text = ((TMP_Text)reflectionFieldValue).text + "  (" + text4 + ")";
				return;
			}
			if (name != "MainPage")
			{
				((TMP_Text)reflectionFieldValue).text = ((TMP_Text)reflectionFieldValue).text + "<br><size=70%><alpha=#88>ue.Peak.TcnPatch v2.1.0<alpha=#FF></size>";
				return;
			}
			((TMP_Text)reflectionFieldValue).text = ((TMP_Text)reflectionFieldValue).text + "<br><size=70%>" + text3 + "</size>";
			if (flag)
			{
				((TMP_Text)reflectionFieldValue).text = ((TMP_Text)reflectionFieldValue).text + "<br><size=70%>" + text2 + "</size>";
			}
		}
	}
}
namespace ue.Peak.TcnPatch.Patches
{
	[HarmonyPatch]
	public class CustomOptionsWindowPatch
	{
		[HarmonyPatch(typeof(CustomOptionsWindow), "Initialize")]
		[HarmonyPostfix]
		private static void PatchTitle(CustomOptionsWindow __instance)
		{
			((Component)__instance).transform.Find("CustomOptions/Panel/Title").ToOptionUnity<Transform>().IfNone(delegate
			{
				Plugin.Logger.LogDebug((object)"!!: Failed to find the title text in custom options UI");
			})
				.IfSome(delegate(Transform transform)
				{
					LocalizedText val = ((Component)transform).gameObject.GetComponent<LocalizedText>();
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)transform).gameObject.AddComponent<LocalizedText>();
						val.autoSet = false;
					}
					if (!val.autoSet)
					{
						val.index = "PeakTcnPatch.BoardingPass.CustomExpedition";
						val.autoSet = true;
						val.RefreshText();
					}
				});
		}
	}
	[HarmonyPatch]
	public class GUIManagerPatch
	{
		[HarmonyPatch(typeof(GUIManager), "Awake")]
		[HarmonyPostfix]
		private static void PatchPrompt(GUIManager __instance)
		{
			__instance.strugglePrompt.ToOptionUnity<CanvasGroup>().SelectMany((CanvasGroup g) => ((Component)g).transform.Find("PromptText").ToOptionUnity<Transform>()).SelectMany((Transform c) => ((Component)c).GetComponent<LocalizedText>().ToOptionUnity<LocalizedText>())
				.IfNone(delegate
				{
					Plugin.Logger.LogDebug((object)"!!: Failed to find the text in the Struggle prompt UI");
				})
				.IfSome(delegate(LocalizedText text)
				{
					if (!text.autoSet)
					{
						text.autoSet = true;
						text.RefreshText();
					}
				});
		}
	}
	[HarmonyPatch]
	public class LoadingScreenAnimationPatch
	{
		private static bool _loadingScreenAnimationStartTranspiled;

		[HarmonyPatch(typeof(LoadingScreenAnimation), "Start")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> PatchLoadingAnimationSwitch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			Plugin.Logger.LogInfo((object)"正在修補 LoadingScreenAnimation.Start() 的 IL code...");
			List<CodeInstruction> list = instructions.ToList();
			int num = -1;
			int num2 = -1;
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if (CodeInstructionExtensions.LoadsField(val, (FieldInfo)Refl.LocalizedText.CurrentLanguage, false))
				{
					CodeInstruction val2 = list[i + 1];
					if (!(val2.opcode != OpCodes.Ldc_I4_S) && val2.operand.Equals((sbyte)9))
					{
						num = i;
						num2 = i + 3;
						break;
					}
				}
			}
			if (num == -1 || num2 == -1)
			{
				Plugin.Logger.LogWarning((object)"沒有在 LoadingScreenAnimation.Start() 找到合適的對應 branch!");
				Plugin.Logger.LogWarning((object)"無法以 IL 方式修補 LoadingScreenAnimation.Start()!將會使用 Postfix 方式修補文字。");
				return list;
			}
			Plugin.Logger.LogInfo((object)"正在插入新的 IL code...");
			CodeInstruction val3 = list[num2];
			Label label = generator.DefineLabel();
			val3.labels.Add(label);
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(CodeInstruction.LoadField(typeof(LocalizedText), "CURRENT_LANGUAGE", false));
			list2.Add(new CodeInstruction(OpCodes.Ldc_I4_S, (object)10));
			list2.Add(new CodeInstruction(OpCodes.Beq_S, (object)label));
			List<CodeInstruction> collection = list2;
			list.InsertRange(num, collection);
			_loadingScreenAnimationStartTranspiled = true;
			return list;
		}

		[HarmonyPatch(typeof(LoadingScreenAnimation), "Start")]
		[HarmonyPostfix]
		private static void PatchLoadingAnimation(LoadingScreenAnimation __instance)
		{
			if (!_loadingScreenAnimationStartTranspiled)
			{
				string text = LocalizedText.GetText("LOADING", true);
				if (Refl.LoadingScreenAnimation.LoadingString == null)
				{
					Plugin.Logger.LogWarning((object)"Patcher 找不到欄位: LoadingScreenAnimation.loadingString");
					return;
				}
				if (Refl.LoadingScreenAnimation.DefaultLoadingStringLength == null)
				{
					Plugin.Logger.LogWarning((object)"Patcher 找不到欄位: LoadingScreenAnimation.defaultLoadingStringLength");
					return;
				}
				Plugin.Logger.LogInfo((object)"正在修正載入中動畫的文字 @ LoadingScreenAnimation.Start()...");
				string text2 = text + "..." + text + "..." + text + "..." + text + "...";
				__instance.SetReflectionFieldValue(Refl.LoadingScreenAnimation.LoadingString, text2);
				__instance.SetReflectionFieldValue(Refl.LoadingScreenAnimation.DefaultLoadingStringLength, text2.Length);
			}
		}
	}
	[HarmonyPatch]
	public class LocalizedTextPatch
	{
		private class AutoDumpRecord
		{
			public int FormatVersion { get; set; } = 0;

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

			public Dictionary<string, string> Translations { get; }

			public Dictionary<string, string> AdditionalTranslations { get; }

			public AutoDumpRecord(Dictionary<string, string> translations, Dictionary<string, string> additionalTranslations)
			{
				Translations = translations;
				AdditionalTranslations = additionalTranslations;
				base..ctor();
			}
		}

		private static bool _autoDumpedMainTable;

		private static readonly Lazy<Unit> _readIfTooLate = new Lazy<Unit>(delegate
		{
			if (_earlyEnough)
			{
				return Unit.Instance;
			}
			Plugin.Logger.LogWarning((object)"正在重新讀取 PEAK 官方翻譯表...");
			Dictionary<string, List<string>>.KeyCollection keyCollection = Resources.Load<TextAsset>("Localization/SerializedTermsData").ToOptionUnity<TextAsset>().Select(delegate(TextAsset t)
			{
				string text = t.text;
				return JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(text).Keys;
			})
				.OrElseGet(delegate
				{
					Plugin.Logger.LogWarning((object)"找不到 PEAK 官方翻譯表: 無法讀取 TextAsset @ Localization/SerializedTermsData");
					Plugin.Logger.LogWarning((object)"所有的現有翻譯將會被視為原版翻譯。");
					return LocalizedText.mainTable.Keys;
				});
			foreach (string item in keyCollection)
			{
				VanillaLocalizationKeys.Add(item);
			}
			if (!_autoDumpedMainTable)
			{
				PatchLoadMainTable();
			}
			return Unit.Instance;
		});

		private static readonly Lazy<int> _languageCountLazy = new Lazy<int>(() => Enum.GetNames(typeof(Language)).Length);

		private static bool _earlyEnough;

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

		[HarmonyPatch(typeof(LocalizedText), "GetText", new Type[]
		{
			typeof(string),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static void PatchGetText(string id, ref string __result, ref bool __runOriginal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PatchGetText(id, LocalizedText.CURRENT_LANGUAGE, ref __result, ref __runOriginal);
		}

		[HarmonyPatch(typeof(LocalizedText), "GetText", new Type[]
		{
			typeof(string),
			typeof(Language)
		})]
		[HarmonyPrefix]
		private static void PatchGetText(string id, Language language, ref string __result, ref bool __runOriginal)
		{
			//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)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			_ = _readIfTooLate.Value;
			(bool, string result) tuple = (from result in (from result in (from result in Plugin.GetRegistered(id, language)
						where !string.IsNullOrEmpty(result.Trim())
						select result).OrGet(() => Plugin.GetRegistered(id.ToUpperInvariant(), language))
					where !string.IsNullOrEmpty(result.Trim())
					select result).OrGet(() => ((int)language != 10) ? ((Option<string>)Option.None) : Plugin.GetVanilla(id))
				where !string.IsNullOrEmpty(result.Trim())
				select (false, result: result)).OrElse((true, null));
			bool item = tuple.Item1;
			string item2 = tuple.result;
			__runOriginal = item;
			__result = item2;
			if (__runOriginal && LocalizedText.mainTable.TryGetValue(id.ToUpperInvariant(), out var value))
			{
				FixLanguageList(value);
			}
		}

		private static List<string> FixLanguageList(List<string> list)
		{
			while (list.Count < _languageCountLazy.Value)
			{
				list.Add(string.Empty);
			}
			return list;
		}

		[HarmonyPatch(typeof(LocalizedText), "LoadMainTable")]
		[HarmonyPriority(800)]
		[HarmonyPostfix]
		private static void PatchLoadMainTableFirstChance()
		{
			_earlyEnough = true;
			foreach (string key in LocalizedText.mainTable.Keys)
			{
				VanillaLocalizationKeys.Add(key);
			}
		}

		[HarmonyPatch(typeof(LocalizedText), "LoadMainTable")]
		[HarmonyPriority(0)]
		[HarmonyPostfix]
		private static void PatchLoadMainTable()
		{
			if (!_autoDumpedMainTable)
			{
				_autoDumpedMainTable = true;
				if (Plugin.ModConfig.EnableAutoDumpLanguage.Value)
				{
					DumpLanguageEntries();
				}
			}
		}

		internal static void DumpLanguageEntries()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Logger.LogInfo((object)"正在自動輸出翻譯表至 _AutoTcnTranslations.json...");
			string text = Path.Combine(Paths.ConfigPath, "ue.Peak.TcnPatch");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			string path = Path.Combine(text, "_AutoTcnTranslations.json");
			Language language = Plugin.ModConfig.AutoDumpLanguage.Value;
			Dictionary<string, string> translations = LocalizedText.mainTable.Where((KeyValuePair<string, List<string>> p) => VanillaLocalizationKeys.Contains(p.Key)).ToDictionary((KeyValuePair<string, List<string>> p) => p.Key, (KeyValuePair<string, List<string>> p) => FixLanguageList(p.Value)[(int)language]);
			Dictionary<string, string> dictionary = LocalizedText.mainTable.Where((KeyValuePair<string, List<string>> p) => !VanillaLocalizationKeys.Contains(p.Key)).ToDictionary((KeyValuePair<string, List<string>> p) => p.Key, (KeyValuePair<string, List<string>> p) => FixLanguageList(p.Value)[(int)language]);
			foreach (KeyValuePair<string, string> item in Plugin.KeyToUnlocalizedLookup)
			{
				item.Deconstruct(out var key, out var value);
				string key2 = key;
				string value2 = value;
				dictionary[key2] = value2;
			}
			string contents = JsonConvert.SerializeObject((object)new AutoDumpRecord(translations, dictionary), (Formatting)1);
			File.WriteAllText(path, contents);
		}
	}
	[HarmonyPatch]
	public class PassportManagerPatch
	{
		[HarmonyPatch(typeof(PassportManager), "Awake")]
		[HarmonyPostfix]
		private static void PatchCrabland(PassportManager __instance)
		{
			((Component)__instance).transform.Find("PassportUI/Canvas/Panel/Panel/BG/Text/Nationality/Text").ToOptionUnity<Transform>().IfNone(delegate
			{
				Plugin.Logger.LogDebug((object)"!!: Failed to find the Crabland text in passport UI");
			})
				.IfSome(delegate(Transform transform)
				{
					LocalizedText val = ((Component)transform).gameObject.GetComponent<LocalizedText>();
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)transform).gameObject.AddComponent<LocalizedText>();
						val.autoSet = false;
					}
					if (!val.autoSet)
					{
						val.index = "PeakTcnPatch.Passport.Crabland";
						val.autoSet = true;
						val.RefreshText();
					}
				});
		}
	}
	[HarmonyPatch]
	public class VersionStringPatch
	{
		private static bool _versionTextMissingWarned;

		[HarmonyPatch(typeof(VersionString), "Start")]
		[HarmonyPostfix]
		private static void PatchVersionStringWarnOnStart(VersionString __instance)
		{
			//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_009e: Unknown result type (might be due to invalid IL or missing references)
			if (Refl.VersionString.Text == null)
			{
				if (!_versionTextMissingWarned)
				{
					_versionTextMissingWarned = true;
					Plugin.Logger.LogWarning((object)"VersionString: 找不到版本資訊的 m_text 欄位!");
				}
				return;
			}
			string name = ((Object)((Component)((Component)__instance).transform.GetParent()).gameObject).name;
			string name2 = ((Object)((Component)__instance).gameObject).name;
			if (name2 == "Version" && name == "MainPage")
			{
				RectTransform component = ((Component)__instance).GetComponent<RectTransform>();
				Vector2 anchoredPosition = component.anchoredPosition;
				anchoredPosition.y -= 10f;
				component.anchoredPosition = anchoredPosition;
				TypedFieldInfo<VersionString, TextMeshProUGUI> text = Refl.VersionString.Text;
				TextMeshProUGUI reflectionFieldValue = __instance.GetReflectionFieldValue(text);
				((TMP_Text)reflectionFieldValue).verticalAlignment = (VerticalAlignmentOptions)256;
			}
			Plugin.VersionStringInstance = __instance;
		}
	}
}
namespace ue.Peak.TcnPatch.Core
{
	public static class ControlFlow
	{
		public class PartialWithBreak<T>(T value)
		{
			internal T Value { get; } = value;

			public ControlFlow<T, TContinue> FulfillContinueType<TContinue>()
			{
				return ControlFlow<T, TContinue>.Break(Value);
			}
		}

		public class PartialWithContinue<T>(T value)
		{
			internal T Value { get; } = value;

			public ControlFlow<TBreak, T> FulfillBreakType<TBreak>()
			{
				return ControlFlow<TBreak, T>.Continue(Value);
			}
		}

		public static PartialWithBreak<T> Break<T>(T value)
		{
			return new PartialWithBreak<T>(value);
		}

		public static PartialWithBreak<Unit> Break()
		{
			return new PartialWithBreak<Unit>(Unit.Instance);
		}

		public static PartialWithContinue<T> Continue<T>(T value)
		{
			return new PartialWithContinue<T>(value);
		}

		public static PartialWithContinue<Unit> Continue()
		{
			return new PartialWithContinue<Unit>(Unit.Instance);
		}
	}
	public abstract class ControlFlow<TBreak, TContinue>
	{
		private class BreakBranch : ControlFlow<TBreak, TContinue>
		{
			private readonly TBreak _value;

			public override bool IsBreak => true;

			public override bool IsContinue => false;

			public BreakBranch(TBreak value)
			{
				_value = value;
			}

			public override Option<TContinue> GetContinueValue()
			{
				return Option.None;
			}

			public override Result<TContinue, TBreak> ToContinueSuccess()
			{
				return Result.Error(_value);
			}

			public override ControlFlow<TBreak, TResult> SelectContinue<TResult>(Func<TContinue, TResult> transform)
			{
				return ControlFlow.Break(_value);
			}

			public override Option<TBreak> GetBreakValue()
			{
				return Option.Some(_value);
			}

			public override Result<TBreak, TContinue> ToBreakSuccess()
			{
				return Result.Success(_value);
			}

			public override ControlFlow<TResult, TContinue> SelectBreak<TResult>(Func<TBreak, TResult> transform)
			{
				return ControlFlow.Break(transform(_value));
			}
		}

		private class ContinueBranch : ControlFlow<TBreak, TContinue>
		{
			private readonly TContinue _value;

			public override bool IsBreak => false;

			public override bool IsContinue => true;

			public ContinueBranch(TContinue value)
			{
				_value = value;
			}

			public override Option<TContinue> GetContinueValue()
			{
				return Option.Some(_value);
			}

			public override Result<TContinue, TBreak> ToContinueSuccess()
			{
				return Result.Success(_value);
			}

			public override ControlFlow<TBreak, TResult> SelectContinue<TResult>(Func<TContinue, TResult> transform)
			{
				return ControlFlow.Continue(transform(_value));
			}

			public override Option<TBreak> GetBreakValue()
			{
				return Option.None;
			}

			public override Result<TBreak, TContinue> ToBreakSuccess()
			{
				return Result.Error(_value);
			}

			public override ControlFlow<TResult, TContinue> SelectBreak<TResult>(Func<TBreak, TResult> transform)
			{
				return ControlFlow.Continue(_value);
			}
		}

		public abstract bool IsBreak { get; }

		public abstract bool IsContinue { get; }

		public static ControlFlow<TBreak, TContinue> Continue(TContinue value)
		{
			return new ContinueBranch(value);
		}

		public static ControlFlow<TBreak, TContinue> Break(TBreak value)
		{
			return new BreakBranch(value);
		}

		public static implicit operator ControlFlow<TBreak, TContinue>(ControlFlow.PartialWithContinue<TContinue> part)
		{
			return new ContinueBranch(part.Value);
		}

		public static implicit operator ControlFlow<TBreak, TContinue>(ControlFlow.PartialWithBreak<TBreak> part)
		{
			return new BreakBranch(part.Value);
		}

		public abstract Option<TContinue> GetContinueValue();

		public abstract Result<TContinue, TBreak> ToContinueSuccess();

		public abstract ControlFlow<TBreak, TResult> SelectContinue<TResult>(Func<TContinue, TResult> transform);

		public abstract Option<TBreak> GetBreakValue();

		public abstract Result<TBreak, TContinue> ToBreakSuccess();

		public abstract ControlFlow<TResult, TContinue> SelectBreak<TResult>(Func<TBreak, TResult> transform);
	}
	public static class NumberExtensions
	{
		[SpecialName]
		public sealed class <G>$BA41CFE2B5EDAEB8C1B9062F59ED4D69
		{
			[SpecialName]
			public static class <M>$5DACCD576B731A5595F442DFA5E8AE24
			{
			}

			[ExtensionMarker("<M>$5DACCD576B731A5595F442DFA5E8AE24")]
			public int BitCount
			{
				[ExtensionMarker("<M>$5DACCD576B731A5595F442DFA5E8AE24")]
				get
				{
					throw new NotSupportedException();
				}
			}

			[ExtensionMarker("<M>$5DACCD576B731A5595F442DFA5E8AE24")]
			public int GetBitCount()
			{
				throw new NotSupportedException();
			}
		}

		public static int get_BitCount(int self)
		{
			self -= (self >>> 1) & 0x55555555;
			self = (self & 0x33333333) + ((self >>> 2) & 0x33333333);
			self = (self + (self >>> 4)) & 0xF0F0F0F;
			self += self >>> 8;
			self += self >>> 16;
			return self & 0x3F;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int GetBitCount(this int self)
		{
			return get_BitCount(self);
		}
	}
	public interface IOption
	{
		bool IsSome { get; }

		bool IsNone { get; }

		IOption<T> Cast<T>();
	}
	public interface IOption<out T> : IOption
	{
		T Unwrap();

		T Expect(string message);

		T Expect(Exception ex);

		T Expect(Func<Exception> ex);

		IOption<TResult> Select<TResult>(Func<T, TResult> selector);

		IOption<TResult> SelectMany<TResult>(Func<T, IOption<TResult>> selector);

		IOption<T> Where(Func<T, bool> predicate);
	}
	public static class Option
	{
		[StructLayout(LayoutKind.Sequential, Size = 1)]
		public struct NoneValuePlaceholder
		{
			public Option<T> FulfillType<T>()
			{
				return Option<T>.None;
			}

			public IOption FulfillType(Type type)
			{
				Type type2 = typeof(Option<>).MakeGenericType(type);
				return (IOption)Activator.CreateInstance(type2);
			}
		}

		[SpecialName]
		public sealed class <G>$74CAB2AE3CF21190BB3801A1AE8B218F<$T0>
		{
			[SpecialName]
			public static class <M>$BD89945CA7648600A6623ED9B0D34B66
			{
			}

			[ExtensionMarker("<M>$BD89945CA7648600A6623ED9B0D34B66")]
			public $T0 OrElse($T0 other)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$BD89945CA7648600A6623ED9B0D34B66")]
			public $T0 OrElseGet(Func<$T0> other)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$BD89945CA7648600A6623ED9B0D34B66")]
			public Option<$T0> SafeUnbox()
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$89F335C99AD8D0EADD6CEDDA8A8F68D2<$T0, $T1>
		{
			[SpecialName]
			public static class <M>$FB1CE76455089A4956A6AB3011B003C7
			{
			}

			[ExtensionMarker("<M>$FB1CE76455089A4956A6AB3011B003C7")]
			public (Option<$T0> First, Option<$T1> Second) Unzip()
			{
				throw new NotSupportedException();
			}
		}

		public static NoneValuePlaceholder None => default(NoneValuePlaceholder);

		public static Option<T> Some<T>(T value)
		{
			return Option<T>.Some(value);
		}

		public static Option<T> ToOption<T>(this T? value) where T : class
		{
			return (value == null) ? Option<T>.None : Option<T>.Some(value);
		}

		public static Option<T> ToOption<T>(this T? value) where T : struct
		{
			return (!value.HasValue) ? Option<T>.None : Option<T>.Some(value.Value);
		}

		public static IOption<T> Cast<T>(this IOption self)
		{
			return (IOption<T>)self;
		}

		public static TOption Or<TOption, TValue>(this TOption self, TOption other) where TOption : IOption<TValue>
		{
			return self.IsSome ? self : other;
		}

		public static Option<T> GetOptional<T>(this IReadOnlyList<T> self, int index)
		{
			if (index < 0 || index >= self.Count)
			{
				return None;
			}
			return Some(self[index]);
		}

		public static T OrElse<T>(this IOption<T> self, T other)
		{
			return self.IsSome ? self.Unwrap() : other;
		}

		public static T OrElseGet<T>(this IOption<T> self, Func<T> other)
		{
			return self.IsSome ? self.Unwrap() : other();
		}

		public static Option<T> SafeUnbox<T>(this IOption<T> self)
		{
			if (self is Option<T> result)
			{
				return result;
			}
			return self.Select<Option<T>>(Option<T>.Some).OrElse(Option<T>.None);
		}

		public static (Option<TFirst> First, Option<TSecond> Second) Unzip<TFirst, TSecond>(this IOption<(TFirst, TSecond)> self)
		{
			return self.Select(((TFirst, TSecond) t) => (Some(t.Item1), Some(t.Item2))).OrElse((None, None));
		}
	}
	public readonly struct Option<T> : IOption<T>, IOption
	{
		public bool IsSome { get; }

		private T ValueUnsafe { get; }

		public static Option<T> None => default(Option<T>);

		public bool IsNone => !IsSome;

		private Option(T value)
		{
			IsSome = true;
			ValueUnsafe = value;
		}

		public static implicit operator Option<T>(Option.NoneValuePlaceholder _)
		{
			return None;
		}

		public static Option<T> Some(T value)
		{
			return new Option<T>(value);
		}

		public T Unwrap()
		{
			return Expect("Cannot unwrap a None value.");
		}

		public T Expect(string message)
		{
			if (!IsSome)
			{
				throw new InvalidOperationException(message);
			}
			return ValueUnsafe;
		}

		public T Expect(Exception ex)
		{
			return IsSome ? ValueUnsafe : ex.Rethrow<T>();
		}

		public T Expect(Func<Exception> ex)
		{
			return IsSome ? ValueUnsafe : ex().Rethrow<T>();
		}

		public Option<TResult> Select<TResult>(Func<T, TResult> selector)
		{
			return IsSome ? Option<TResult>.Some(selector(ValueUnsafe)) : Option<TResult>.None;
		}

		IOption<TResult> IOption<T>.Select<TResult>(Func<T, TResult> selector)
		{
			return Select(selector);
		}

		public Option<TResult> SelectMany<TResult>(Func<T, Option<TResult>> selector)
		{
			return IsSome ? selector(ValueUnsafe) : Option<TResult>.None;
		}

		IOption<TResult> IOption<T>.SelectMany<TResult>(Func<T, IOption<TResult>> selector)
		{
			return SelectMany((T t) => selector(t).Select(Option.Some).OrElse(Option.None));
		}

		public Option<TResult> SelectMany<TSelectMany, TResult>(Func<T, Option<TSelectMany>> selector, Func<Option<T>, TSelectMany, TResult> resultSelector)
		{
			T valueUnsafe = ValueUnsafe;
			Option<T> self = this;
			return IsSome ? (from v in selector(valueUnsafe)
				select resultSelector(self, v)) : Option<TResult>.None;
		}

		public Option<T> IfSome(Action<T> action)
		{
			if (IsSome)
			{
				action(ValueUnsafe);
			}
			return this;
		}

		public Option<T> IfNone(Action action)
		{
			if (!IsSome)
			{
				action();
			}
			return this;
		}

		public Option<T> Match(Action? None = null, Action<T>? Some = null)
		{
			if (IsSome)
			{
				Some?.Invoke(ValueUnsafe);
			}
			else
			{
				None?.Invoke();
			}
			return this;
		}

		public IEnumerable<T> AsEnumerable()
		{
			if (IsSome)
			{
				yield return ValueUnsafe;
			}
		}

		public Result<T, TError> ToSuccessOr<TError>(TError error)
		{
			return Select((Func<T, Result<T, TError>>)((T x) => Result.Success(x))).OrElseGet(() => Result.Error(error));
		}

		public Option<T> Or(Option<T> other)
		{
			return IsSome ? this : other;
		}

		public Option<T> Where(Func<T, bool> predicate)
		{
			return (!IsSome) ? this : (predicate(ValueUnsafe) ? this : None);
		}

		IOption<T> IOption<T>.Where(Func<T, bool> predicate)
		{
			return Where(predicate);
		}

		public T OrElse(T other)
		{
			return (T)(IsSome ? ((object)ValueUnsafe) : ((object)other));
		}

		public Option<T> OrGet(Func<Option<T>> other)
		{
			return IsSome ? this : other();
		}

		public T OrElseGet(Func<T> other)
		{
			return IsSome ? ValueUnsafe : other();
		}

		public Option<TOut> CastOrThrow<TOut>()
		{
			return IsSome ? Option.Some((TOut)(object)ValueUnsafe) : Option<TOut>.None;
		}

		public Option<TOut> Cast<TOut>()
		{
			if (!IsSome)
			{
				return Option<TOut>.None;
			}
			T valueUnsafe = ValueUnsafe;
			return (valueUnsafe is TOut value) ? Option.Some(value) : ((Option<TOut>)Option.None);
		}

		IOption<TOut> IOption.Cast<TOut>()
		{
			return Cast<TOut>();
		}

		public Option<T> Xor(Option<T> other)
		{
			if (IsSome == other.IsSome)
			{
				return Option.None;
			}
			return IsSome ? this : other;
		}

		public Option<(T, TOther)> Zip<TOther>(Option<TOther> other)
		{
			if (!IsSome || !other.IsSome)
			{
				return Option.None;
			}
			return Option.Some((ValueUnsafe, other.ValueUnsafe));
		}

		public Option<TZipped> Zip<TOther, TZipped>(Option<TOther> other, Func<T, TOther, TZipped> zip)
		{
			if (!IsSome || !other.IsSome)
			{
				return Option.None;
			}
			return Option.Some(zip(ValueUnsafe, other.ValueUnsafe));
		}
	}
	public interface IResult
	{
		bool IsSuccess { get; }

		bool IsError { get; }
	}
	public interface IResultSuccess<T> : IResult
	{
		Option<T> Value { get; }

		T Unwrap();

		IResultSuccess<TResult> Select<TResult>(Func<T, TResult> transform);
	}
	public interface IResultError<T> : IResult
	{
		Option<T> Error { get; }

		T UnwrapError();

		IResultError<TResult> SelectError<TResult>(Func<T, TResult> transform);
	}
	public interface IResult<T, TError> : IResultSuccess<T>, IResult, IResultError<TError>
	{
		new IResult<TResult, TError> Select<TResult>(Func<T, TResult> transform);

		new IResult<T, TResult> SelectError<TResult>(Func<TError, TResult> transform);

		IResultSuccess<TResult> IResultSuccess<T>.Select<TResult>(Func<T, TResult> transform)
		{
			return Select(transform);
		}

		IResultError<TResult> IResultError<TError>.SelectError<TResult>(Func<TError, TResult> transform)
		{
			return SelectError(transform);
		}
	}
	public static class Result
	{
		public class PartialWithSuccess<T>
		{
			private readonly T _value;

			internal PartialWithSuccess(T value)
			{
				_value = value;
			}

			public Result<T, TError> FulfillErrorType<TError>()
			{
				return Result<T, TError>.Success(_value);
			}
		}

		public class PartialWithError<T>
		{
			private readonly T _error;

			internal PartialWithError(T error)
			{
				_error = error;
			}

			public Result<TSuccess, T> FulfillSuccessType<TSuccess>()
			{
				return Result<TSuccess, T>.Error(_error);
			}
		}

		public static PartialWithSuccess<T> Success<T>(T value)
		{
			return new PartialWithSuccess<T>(value);
		}

		public static PartialWithError<T> Error<T>(T error)
		{
			return new PartialWithError<T>(error);
		}

		public static Result<T, Exception> Catch<T>(Func<T> func)
		{
			try
			{
				return Success(func());
			}
			catch (Exception error)
			{
				return Error(error);
			}
		}

		public static T Branch<T>(this IResult<T, T> self)
		{
			return self.IsSuccess ? self.Unwrap() : self.UnwrapError();
		}

		public static Result<T, TError> SafeUnbox<T, TError, TResult>(this TResult self) where TResult : IResult<T, TError>
		{
			if (self is Result<T, TError> result)
			{
				return result;
			}
			return self.Select((T val) => Success(val).FulfillErrorType<TError>()).SelectError((TError val) => Error(val).FulfillSuccessType<T>()).Branch();
		}

		public static T UnwrapOrThrow<T, TError>(this Result<T, TError> result) where TError : Exception
		{
			Option<T> value = result.Value;
			return value.IsSome ? value.Unwrap() : result.UnwrapError().Rethrow<T>();
		}

		public static T Branch<T>(this Result<T, T> result)
		{
			return result.IsSuccess ? result.Unwrap() : result.UnwrapError();
		}

		public static T FastUnwrap<T>(this Result<T, Never> self)
		{
			return self.ValueUnsafe;
		}

		public static T FastUnwrapError<T>(this Result<Never, T> self)
		{
			return self.ErrUnsafe;
		}

		public static Result<T, TError> Flatten<T, TError>(this Result<Result<T, TError>, TError> self)
		{
			return self.SelectMany((Result<T, TError> s) => s);
		}

		public static Result<IEnumerable<TItem>, TError> Process<TItem, TError>(this IEnumerable<Result<TItem, TError>> enumerable)
		{
			IEnumerable<TItem> enumerable2 = Enumerable.Empty<TItem>();
			foreach (Result<TItem, TError> item in enumerable)
			{
				if (item.IsError)
				{
					return Error(item.UnwrapError());
				}
				enumerable2 = enumerable2.Append(item.Unwrap());
			}
			return Success(enumerable2);
		}
	}
	public abstract class Result<T, TError> : IResult<T, TError>, IResultSuccess<T>, IResult, IResultError<TError>, IEquatable<Result<T, TError>>
	{
		private class SuccessBranch : Result<T, TError>
		{
			public new T Value { get; }

			internal SuccessBranch(T value)
			{
				Value = value;
			}

			public override Result<TResult, TError> Select<TResult>(Func<T, TResult> func)
			{
				return Result.Success(func(Value));
			}

			public override Result<TResult, TError> SelectMany<TResult>(Func<T, Result<TResult, TError>> func)
			{
				return func(Value);
			}

			public override Result<T, TErrorResult> SelectError<TErrorResult>(Func<TError, TErrorResult> func)
			{
				return Result.Success(Value);
			}

			public override Result<T, TError> IfSuccess(Action<T> action)
			{
				action(Value);
				return this;
			}

			public override Result<T, TError> IfError(Action<TError> action)
			{
				return this;
			}
		}

		private class ErrorBranch : Result<T, TError>
		{
			public new TError Error { get; }

			internal ErrorBranch(TError error)
			{
				Error = error;
			}

			public override Result<TResult, TError> Select<TResult>(Func<T, TResult> func)
			{
				return Result.Error(Error);
			}

			public override Result<TResult, TError> SelectMany<TResult>(Func<T, Result<TResult, TError>> func)
			{
				return Result.Error(Error);
			}

			public override Result<T, TErrorResult> SelectError<TErrorResult>(Func<TError, TErrorResult> func)
			{
				return Result.Error(func(Error));
			}

			public override Result<T, TError> IfSuccess(Action<T> action)
			{
				return this;
			}

			public override Result<T, TError> IfError(Action<TError> action)
			{
				action(Error);
				return this;
			}
		}

		public bool IsSuccess => this is SuccessBranch;

		public bool IsError => this is ErrorBranch;

		internal T ValueUnsafe => ((SuccessBranch)this).Value;

		internal TError ErrUnsafe => ((ErrorBranch)this).Error;

		public Option<T> Value => (this is SuccessBranch successBranch) ? Option<T>.Some(successBranch.Value) : Option<T>.None;

		public Option<TError> Err => (this is ErrorBranch errorBranch) ? Option<TError>.Some(errorBranch.Error) : Option<TError>.None;

		Option<TError> IResultError<TError>.Error => Err;

		internal Result()
		{
		}

		public static implicit operator Result<T, TError>(Result.PartialWithSuccess<T> partial)
		{
			return partial.FulfillErrorType<TError>();
		}

		public static implicit operator Result<T, TError>(Result.PartialWithError<TError> partial)
		{
			return partial.FulfillSuccessType<T>();
		}

		public T Unwrap()
		{
			return Value.Expect("Cannot unwrap a success value from an Error branch.");
		}

		public TError UnwrapError()
		{
			return Err.Expect("Cannot unwrap an error value from a Success branch.");
		}

		public abstract Result<TResult, TError> Select<TResult>(Func<T, TResult> func);

		IResult<TResult, TError> IResult<T, TError>.Select<TResult>(Func<T, TResult> transform)
		{
			return Select(transform);
		}

		public abstract Result<TResult, TError> SelectMany<TResult>(Func<T, Result<TResult, TError>> func);

		public Result<TResult, TError> SelectMany<TMiddle, TResult>(Func<T, Result<TMiddle, TError>> func, Func<Result<T, TError>, TMiddle, TResult> resultSelector)
		{
			return IsError ? ((Result<TResult, TError>)Result.Error(ErrUnsafe)) : (from m in func(ValueUnsafe)
				select resultSelector(this, m));
		}

		public abstract Result<T, TErrorResult> SelectError<TErrorResult>(Func<TError, TErrorResult> func);

		IResult<T, TResult> IResult<T, TError>.SelectError<TResult>(Func<TError, TResult> transform)
		{
			return SelectError(transform);
		}

		public abstract Result<T, TError> IfSuccess(Action<T> action);

		public abstract Result<T, TError> IfError(Action<TError> action);

		public IEnumerable<T> AsEnumerable()
		{
			return Value.AsEnumerable();
		}

		public bool TryUnwrap([MaybeNullWhen(false)] out T value)
		{
			if (IsSuccess)
			{
				value = ValueUnsafe;
				return true;
			}
			value = default(T);
			return false;
		}

		public bool TryUnwrapError([MaybeNullWhen(false)] out TError error)
		{
			if (IsError)
			{
				error = ErrUnsafe;
				return true;
			}
			error = default(TError);
			return false;
		}

		public static Result<T, TError> Success(T value)
		{
			return new SuccessBranch(value);
		}

		public static Result<T, TError> Error(TError error)
		{
			return new ErrorBranch(error);
		}

		public bool Equals(Result<T, TError>? other)
		{
			if ((object)other == null)
			{
				return false;
			}
			if (IsSuccess != other.IsSuccess)
			{
				return false;
			}
			return IsSuccess ? ValueUnsafe.Equals(other.ValueUnsafe) : ErrUnsafe.Equals(other.ErrUnsafe);
		}

		public override bool Equals(object? obj)
		{
			return this == obj || (obj is Result<T, TError> other && Equals(other));
		}

		public override int GetHashCode()
		{
			return IsSuccess ? HashCode.Combine(value1: true, ValueUnsafe) : HashCode.Combine(value1: false, ErrUnsafe);
		}

		public static bool operator ==(Result<T, TError>? left, Result<T, TError>? right)
		{
			return object.Equals(left, right);
		}

		public static bool operator !=(Result<T, TError>? left, Result<T, TError>? right)
		{
			return !object.Equals(left, right);
		}
	}
	public abstract class ScopeGuard : IDisposable
	{
		protected virtual bool ShouldEndScope => true;

		protected abstract void EndScope();

		public void Dispose()
		{
			if (ShouldEndScope)
			{
				EndScope();
			}
		}
	}
	public class DelegateScopeGuard : ScopeGuard
	{
		private readonly Action _endScope;

		private DelegateScopeGuard(Action endScope)
		{
			_endScope = endScope;
		}

		protected override void EndScope()
		{
			_endScope();
		}
	}
	public class SemaphoreSlimGuard : ScopeGuard
	{
		private readonly SemaphoreSlim _semaphore;

		private SemaphoreSlimGuard(SemaphoreSlim semaphore)
		{
			_semaphore = semaphore;
		}

		public static SemaphoreSlimGuard Create(SemaphoreSlim semaphore)
		{
			semaphore.Wait();
			return new SemaphoreSlimGuard(semaphore);
		}

		public static async Task<SemaphoreSlimGuard> CreateAsync(SemaphoreSlim semaphore)
		{
			await semaphore.WaitAsync();
			return new SemaphoreSlimGuard(semaphore);
		}

		protected override void EndScope()
		{
			_semaphore.Release();
		}
	}
	public enum Never
	{

	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct Unit
	{
		public static Unit Instance => default(Unit);
	}
	public static class Utils
	{
		[SpecialName]
		public sealed class <G>$B121A579F9C62187B81C2CC9A1D05898
		{
			[SpecialName]
			public static class <M>$9A581DD593152A881C02B7BBD540726C
			{
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public Task<IDisposable> CreateScopeAsync()
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public IDisposable CreateScope()
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public void EnterScope(Action action)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public T EnterScope<T>(Func<T> func)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public Task EnterScopeAsync(Action action)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public Task<T> EnterScopeAsync<T>(Func<T> func)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public Task EnterScopeAsync(Func<Task> action)
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
			public Task<T> EnterScopeAsync<T>(Func<Task<T>> action)
			{
				throw new NotSupportedException();
			}
		}

		[SpecialName]
		public sealed class <G>$6A188C7A03CB85FC44DF3FD030EA0664
		{
			[SpecialName]
			public static class <M>$438D5453E0DFEE874C985587A0074FB9
			{
			}

			[ExtensionMarker("<M>$438D5453E0DFEE874C985587A0074FB9")]
			[DoesNotReturn]
			public Never Rethrow()
			{
				throw new NotSupportedException();
			}

			[ExtensionMarker("<M>$438D5453E0DFEE874C985587A0074FB9")]
			[DoesNotReturn]
			public T Rethrow<T>()
			{
				throw new NotSupportedException();
			}
		}

		public static Option<TValue> GetOptional<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
		{
			TValue value;
			return dict.TryGetValue(key, out value) ? Option.Some(value) : Option<TValue>.None;
		}

		private static Result<Unit, AggregateException> SafeInvokeInternal<T>(T? self, Action<T> invoke) where T : Delegate
		{
			if (self == null)
			{
				return Result.Success(Unit.Instance);
			}
			Lazy<List<Exception>> lazy = new Lazy<List<Exception>>(() => new List<Exception>());
			foreach (T item2 in self.GetInvocationList().Cast<T>())
			{
				try
				{
					invoke(item2);
				}
				catch (Exception item)
				{
					lazy.Value.Add(item);
				}
			}
			if (lazy.IsValueCreated)
			{
				return Result.Error(new AggregateException("One or more exceptions occured while safe-invoking the delegate.", lazy.Value));
			}
			return Result.Success(Unit.Instance);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Result<Unit, AggregateException> SafeInvoke(this Action? self)
		{
			return SafeInvokeInternal(self, delegate(Action a)
			{
				a();
			});
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Result<Unit, AggregateException> SafeInvoke<T>(this Action<T>? self, T arg)
		{
			return SafeInvokeInternal(self, delegate(Action<T> a)
			{
				a(arg);
			});
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Result<Unit, AggregateException> SafeInvoke<T1, T2>(this Action<T1, T2>? self, T1 arg1, T2 arg2)
		{
			return SafeInvokeInternal(self, delegate(Action<T1, T2> a)
			{
				a(arg1, arg2);
			});
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static async Task<IDisposable> CreateScopeAsync(this SemaphoreSlim semaphore)
		{
			return await SemaphoreSlimGuard.CreateAsync(semaphore);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static IDisposable CreateScope(this SemaphoreSlim semaphore)
		{
			return SemaphoreSlimGuard.Create(semaphore);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void EnterScope(this SemaphoreSlim semaphore, Action action)
		{
			using (semaphore.CreateScope())
			{
				action();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static T EnterScope<T>(this SemaphoreSlim semaphore, Func<T> func)
		{
			using (semaphore.CreateScope())
			{
				return func();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static async Task EnterScopeAsync(this SemaphoreSlim semaphore, Action action)
		{
			using (await semaphore.CreateScopeAsync())
			{
				action();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static async Task<T> EnterScopeAsync<T>(this SemaphoreSlim semaphore, Func<T> func) where T : notnull
		{
			using (await semaphore.CreateScopeAsync())
			{
				return func();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static async Task EnterScopeAsync(this SemaphoreSlim semaphore, Func<Task> action)
		{
			using (await semaphore.CreateScopeAsync())
			{
				await action();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static async Task<T> EnterScopeAsync<T>(this SemaphoreSlim semaphore, Func<Task<T>> action) where T : notnull
		{
			using (await semaphore.CreateScopeAsync())
			{
				return await action();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[DoesNotReturn]
		public static Never Rethrow(this Exception ex)
		{
			return ex.Rethrow<Never>();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		[DoesNotReturn]
		public static T Rethrow<T>(this Exception ex)
		{
			ExceptionDispatchInfo.Capture(ex).Throw();
			return default(T);
		}
	}
}
namespace ue.Peak.TcnPatch.API
{
	public interface ITcnPatch
	{
		void RegisterLocalizationKey(string key, string unlocalized);
	}
	public class TcnPatch : ITcnPatch
	{
		public static ITcnPatch Instance => InternalInstance;

		internal static TcnPatch InternalInstance { get; } = new TcnPatch();

		public void RegisterLocalizationKey(string key, string unlocalized)
		{
			Plugin.KeyToUnlocalizedLookup[key] = unlocalized;
		}
	}
}
namespace ue.Peak.TcnPatch.Adapters
{
	public static class MoreAscentsSupport
	{
		private class ReflectionFailedError(Action showWarning)
		{
			public void ShowWarning()
			{
				showWarning();
			}
		}

		private static readonly Lazy<Type> _gimmickHandlerType = new Lazy<Type>(() => Type.GetType("MoreAscents.AscentGimmickHandler"));

		private static bool _addedSupport;

		public static bool IsMoreAscentsInstalled => _gimmickHandlerType.Value != null;

		private static Type GimmickHandlerType => _gimmickHandlerType.Value;

		public static void RegisterLocalizations()
		{
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Expected O, but got Unknown
			if (!IsMoreAscentsInstalled)
			{
				return;
			}
			TypedFieldInfo<object, bool> typedFieldInfo = AccessTools.Field(GimmickHandlerType, "HasInitialized").AsTyped<object, bool>();
			if (typedFieldInfo == null)
			{
				return;
			}
			if (!typedFieldInfo.GetStaticValue())
			{
				Plugin.Logger.LogWarning((object)"MoreAscents 還沒初始化!?");
			}
			else
			{
				if (_addedSupport)
				{
					return;
				}
				_addedSupport = true;
				Plugin.Logger.LogInfo((object)"偵測到 MoreAscents!正在為 MoreAscents 提供繁中支援...");
				try
				{
					if (!FindType("MoreAscents.AscentGimmick").IfError(delegate(ReflectionFailedError e)
					{
						e.ShowWarning();
					}).TryUnwrap(out var value) || !FindMethod(value, "GetTitle").IfError(delegate(ReflectionFailedError e)
					{
						e.ShowWarning();
					}).TryUnwrap(out var gimmickGetTitleMethod) || !FindMethod(value, "GetDescription").IfError(delegate(ReflectionFailedError e)
					{
						e.ShowWarning();
					}).TryUnwrap(out var gimmickGetDescriptionMethod) || !FindMethod(value, "GetTitleReward").IfError(delegate(ReflectionFailedError e)
					{
						e.ShowWarning();
					}).TryUnwrap(out var value2) || !FindField(GimmickHandlerType, "gimmicks").IfError(delegate(ReflectionFailedError e)
					{
						e.ShowWarning();
					}).TryUnwrap(out var value3))
					{
						return;
					}
					IReadOnlyList<object> readOnlyList = (IReadOnlyList<object>)value3.GetValue(null);
					MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(AscentData), "Instance");
					AscentData val = (AscentData)methodInfo.Invoke(null, Array.Empty<object>());
					List<AscentInstanceData> ascents = val.ascents;
					foreach (object gimmick in readOnlyList)
					{
						AscentInstanceData val2 = ((IEnumerable<AscentInstanceData>)ascents).FirstOrDefault((Func<AscentInstanceData, bool>)((AscentInstanceData d) => d.title == (string)gimmickGetTitleMethod.Invoke(gimmick, Array.Empty<object>()) && d.description == (string)gimmickGetDescriptionMethod.Invoke(gimmick, Array.Empty<object>())));
						if (val2 != null)
						{
							string text = (val2.title = "MoreAscent." + gimmick.GetType().Name);
							val2.titleReward = text + ".Reward";
							ue.Peak.TcnPatch.API.TcnPatch.Instance.RegisterLocalizationKey(text ?? "", (string)gimmickGetTitleMethod.Invoke(gimmick, Array.Empty<object>()));
							ue.Peak.TcnPatch.API.TcnPatch.Instance.RegisterLocalizationKey(LocalizedText.GetDescriptionIndex(text), (string)gimmickGetDescriptionMethod.Invoke(gimmick, Array.Empty<object>()));
							ue.Peak.TcnPatch.API.TcnPatch.Instance.RegisterLocalizationKey(text + ".Reward", (string)value2.Invoke(gimmick, Array.Empty<object>()));
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogError((object)"無法為 MoreAscents 提供繁中支援... x_x");
					Plugin.Logger.LogError((object)ex);
				}
			}
			static Result<FieldInfo, ReflectionFailedError> FindField(Type type, string fieldName)
			{
				FieldInfo fieldInfo = AccessTools.Field(type, fieldName);
				if (fieldInfo != null)
				{
					return Result.Success(fieldInfo);
				}
				return Result.Error(new ReflectionFailedError(delegate
				{
					Plugin.Logger.LogWarning((object)("無法找到 " + type.Name + "." + fieldName + " 欄位!無法為 MoreAscents 提供繁中支援... x_x"));
				}));
			}
			static Result<MethodInfo, ReflectionFailedError> FindMethod(Type type, string methodName)
			{
				MethodInfo methodInfo2 = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					return Result.Success(methodInfo2);
				}
				return Result.Error(new ReflectionFailedError(delegate
				{
					Plugin.Logger.LogWarning((object)("無法找到 " + type.Name + "." + methodName + "() 方法!無法為 MoreAscents 提供繁中支援... x_x"));
				}));
			}
			static Result<Type, ReflectionFailedError> FindType(string typeName)
			{
				Type type = AccessTools.TypeByName(typeName);
				if (type != null)
				{
					return Result.Success(type);
				}
				return Result.Error(new ReflectionFailedError(delegate
				{
					Plugin.Logger.LogWarning((object)("無法找到 " + typeName + " 類型!無法為 MoreAscents 提供繁中支援... x_x"));
				}));
			}
		}
	}
}