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+f18aa2db01aa6a7fdec69e36501c754efe6d1844")]
[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]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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]
[Microsoft.CodeAnalysis.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
{
public ExtensionMarkerAttribute(string name)
{
}
}
}
namespace ue.Peak.TcnPatch
{
[BepInPlugin("ue.Peak.TcnPatch", "ue.Peak.TcnPatch", "1.5.9")]
[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 = "1.5.9";
private static FileSystemWatcher _watcher;
public const string TcnTranslationFileName = "TcnTranslations.json";
private static readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
[CanBeNull]
private Harmony _harmony;
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; }
internal static bool HasOfficialTcn { get; private 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");
if (Enum.GetValues(typeof(Language)).Cast<int>().Any((int values) => values == 10))
{
HasOfficialTcn = true;
}
if (ModConfig.DownloadFromRemote.Value)
{
DownloadTranslationsAsync();
}
_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");
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();
}
};
UpdateMainTable();
_watcher.EnableRaisingEvents = true;
}
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
{
FileStream targetStream = File.Open(path, FileMode.Create, FileAccess.Write);
try
{
StreamWriter writer = new StreamWriter(targetStream);
try
{
await writer.WriteAsync(content);
}
finally
{
if (writer != null)
{
await writer.DisposeAsync();
}
}
}
finally
{
if (targetStream != null)
{
await targetStream.DisposeAsync();
}
}
});
}
private async Task DownloadTranslationsAsync()
{
string url = ModConfig.DownloadUrl.Value;
Logger.LogInfo((object)"正在從遠端下載翻譯資料... (可以在模組設定停用)");
Logger.LogInfo((object)("網址:" + url));
using HttpClient client = new HttpClient();
try
{
string content = await client.GetStringAsync(url);
try
{
JObject.Parse(content);
}
catch (Exception ex)
{
Exception e2 = ex;
Logger.LogWarning((object)"無效的遠端翻譯資料!將使用本機資料。");
Logger.LogWarning((object)e2);
return;
}
await SaveTranslationsAsync(content);
Logger.LogInfo((object)"翻譯資料下載完成!");
}
catch (Exception ex)
{
Exception e = ex;
Logger.LogError((object)"翻譯資料下載失敗!將使用本機資料。");
Logger.LogError((object)e);
}
}
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 key;
string value;
foreach (KeyValuePair<string, string> translation in CurrentTranslationFile.Translations)
{
translation.Deconstruct(out key, out value);
string text = key;
string value2 = value;
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 value, out key);
string text3 = value;
string value3 = key;
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<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<LanguagePatchMode> LanguagePatchMode { get; } = config.Bind<LanguagePatchMode>("Patch", "LanguagePatchMode", ue.Peak.TcnPatch.LanguagePatchMode.InsertAfterSimplifiedChinese, "設定如何修正設定中的語言清單");
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, "在主畫面版本文字後面顯示這個模組的版本? (v1.5.9)");
public PluginConfig(ConfigFile config)
{
}
}
public enum LanguagePatchMode
{
InsertAfterSimplifiedChinese,
ReplaceEnglish,
ReplaceSimplifiedChinese,
Append,
TraditionalChineseOnly
}
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 null;
}
[ExtensionMarker("<M>$B99A874B2F9892B4D9EADD5CC9D40768")]
public void SetReflectionFieldValue<TValue>(TypedFieldInfo<$T0, TValue> fieldInfo, TValue value)
{
throw null;
}
}
[SpecialName]
public sealed class <G>$C0F9324A7FB6D595E082877B54F807CC
{
[SpecialName]
public static class <M>$4776623D3010553C7D2AB93E76A250FB
{
}
[ExtensionMarker("<M>$4776623D3010553C7D2AB93E76A250FB")]
[CanBeNull]
public TypedFieldInfo<TOwner, TValue> AsTyped<TOwner, TValue>()
{
throw null;
}
}
[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>
{
public FieldInfo FieldInfo { get; }
public TypedFieldInfo(FieldInfo fieldInfo)
{
FieldInfo = fieldInfo;
base..ctor();
}
[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 val9 = (JArray)(object)((authorsToken is JArray) ? authorsToken : null);
if (val9 != null)
{
foreach (JToken item in val9)
{
result.Authors.Add(Extensions.Value<string>((IEnumerable<JToken>)item));
}
return;
}
JValue val10 = (JValue)(object)((authorsToken is JValue) ? authorsToken : null);
if (val10 != null)
{
result.Authors.Add(Extensions.Value<string>((IEnumerable<JToken>)val10));
}
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
{
[CompilerGenerated]
private sealed class <DelayFramesCoroutine>d__3<T> : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public TaskCompletionSource<T> source;
public int frames;
public Func<T> resultGetter;
private int <i>5__1;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayFramesCoroutine>d__3(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<i>5__1 = 0;
break;
case 1:
<>1__state = -1;
<i>5__1++;
break;
}
if (<i>5__1 < frames)
{
<>2__current = (object)new WaitForEndOfFrame();
<>1__state = 1;
return true;
}
source.SetResult(resultGetter());
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public 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);
}
[IteratorStateMachine(typeof(<DelayFramesCoroutine>d__3<>))]
private static IEnumerator DelayFramesCoroutine<T>(TaskCompletionSource<T> source, int frames, Func<T> resultGetter)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayFramesCoroutine>d__3<T>(0)
{
source = source,
frames = frames,
resultGetter = resultGetter
};
}
}
public enum ReturnFlow
{
Continue,
Break
}
}
namespace ue.Peak.TcnPatch.Patches
{
[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)
{
text.autoSet = true;
text.RefreshText();
});
}
}
[HarmonyPatch]
public class LanguageSettingPatch
{
[HarmonyPatch(typeof(LanguageSetting), "GetCustomLocalizedChoices")]
[HarmonyPostfix]
private static void PatchLanguageChoices(LanguageSetting __instance, ref List<string> __result)
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.HasOfficialTcn)
{
switch (Plugin.ModConfig.LanguagePatchMode.Value)
{
case LanguagePatchMode.ReplaceEnglish:
case LanguagePatchMode.ReplaceSimplifiedChinese:
break;
case LanguagePatchMode.InsertAfterSimplifiedChinese:
case LanguagePatchMode.Append:
{
int num = Enum.GetNames(typeof(Language)).Length;
string text = LocalizedText.GetText("CURRENT_LANGUAGE", __instance.ValueToLanguage(num));
Plugin.Logger.LogInfo((object)"正在修正設定中的語言清單...");
__result.Add(text);
break;
}
case LanguagePatchMode.TraditionalChineseOnly:
__result = __result.Take(1).ToList();
break;
}
}
}
[HarmonyPatch(typeof(LanguageSetting), "ValueToLanguage")]
[HarmonyPostfix]
private static void PatchValueToLanguage(int val, ref Language __result)
{
if (Plugin.HasOfficialTcn)
{
return;
}
switch (Plugin.ModConfig.LanguagePatchMode.Value)
{
case LanguagePatchMode.InsertAfterSimplifiedChinese:
__result = (Language)val;
break;
case LanguagePatchMode.ReplaceEnglish:
if (val == 0)
{
__result = (Language)10;
}
break;
case LanguagePatchMode.ReplaceSimplifiedChinese:
if (val == 9)
{
__result = (Language)10;
}
break;
case LanguagePatchMode.Append:
{
int length = Enum.GetValues(typeof(Language)).Length;
if (val == length)
{
__result = (Language)10;
}
break;
}
case LanguagePatchMode.TraditionalChineseOnly:
__result = (Language)10;
break;
}
}
}
[HarmonyPatch]
public class LoadingScreenAnimationPatch
{
private static bool _loadingScreenAnimationStartTranspiled;
[HarmonyPatch(typeof(LoadingScreenAnimation), "Start")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> PatchLoadingAnimationSwitch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
{
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Expected O, but got Unknown
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Expected O, but got Unknown
if (Plugin.HasOfficialTcn)
{
_loadingScreenAnimationStartTranspiled = true;
return instructions;
}
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; } = 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<int> _languageCountLazy = new Lazy<int>(() => Enum.GetNames(typeof(Language)).Length);
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_001c: Unknown result type (might be due to invalid IL or missing references)
(bool, string) 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)).OrElse((true, null));
bool item = tuple.Item1;
string item2 = tuple.Item2;
__runOriginal = item;
__result = item2;
if (__runOriginal && LocalizedText.mainTable.TryGetValue(id.ToUpperInvariant(), out var value))
{
while (value.Count < _languageCountLazy.Value)
{
value.Add(string.Empty);
}
}
}
[HarmonyPatch(typeof(LocalizedText), "LoadMainTable")]
[HarmonyPriority(800)]
[HarmonyPostfix]
private static void PatchLoadMainTableFirstChance()
{
if (VanillaLocalizationKeys.Count > 0)
{
foreach (string item in LocalizedText.mainTable.Keys.Where((string key) => !VanillaLocalizationKeys.Contains(key)))
{
LocalizedText.mainTable.Remove(item);
}
return;
}
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) => 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) => 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.AddComponent<LocalizedText>();
val.index = "PeakTcnPatch.Passport.Crabland";
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;
}
}
[HarmonyPatch(typeof(VersionString), "Update")]
[HarmonyPostfix]
private static void PatchVersionString(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);
string text2 = "繁中翻譯by: " + string.Join("、", Plugin.CurrentTranslationFile.Authors);
string text3 = (Plugin.ModConfig.ShowModVersionInPatchCredit.Value ? "繁中支援v1.5.9 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;
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 v1.5.9<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.Core
{
public static class ControlFlow
{
public class PartialWithBreak<T>
{
internal T Value { get; }
public PartialWithBreak(T value)
{
Value = value;
base..ctor();
}
public ControlFlow<T, TContinue> FulfillContinueType<TContinue>()
{
return ControlFlow<T, TContinue>.Break(Value);
}
}
public class PartialWithContinue<T>
{
internal T Value { get; }
public PartialWithContinue(T value)
{
Value = value;
base..ctor();
}
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 null;
}
}
[ExtensionMarker("<M>$5DACCD576B731A5595F442DFA5E8AE24")]
public int GetBitCount()
{
throw null;
}
}
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 null;
}
[ExtensionMarker("<M>$BD89945CA7648600A6623ED9B0D34B66")]
public $T0 OrElseGet(Func<$T0> other)
{
throw null;
}
[ExtensionMarker("<M>$BD89945CA7648600A6623ED9B0D34B66")]
public Option<$T0> SafeUnbox()
{
throw null;
}
}
[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 null;
}
}
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
{
[CompilerGenerated]
private sealed class <AsEnumerable>d__25 : IEnumerable<T>, IEnumerable, IEnumerator<T>, IEnumerator, IDisposable
{
private int <>1__state;
private T <>2__current;
private int <>l__initialThreadId;
public Option<T> <>4__this;
public Option<T> <>3__<>4__this;
T IEnumerator<T>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <AsEnumerable>d__25(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (<>4__this.IsSome)
{
<>2__current = <>4__this.ValueUnsafe;
<>1__state = 1;
return true;
}
break;
case 1:
<>1__state = -1;
break;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
<AsEnumerable>d__25 <AsEnumerable>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<AsEnumerable>d__ = this;
}
else
{
<AsEnumerable>d__ = new <AsEnumerable>d__25(0);
}
<AsEnumerable>d__.<>4__this = <>3__<>4__this;
return <AsEnumerable>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<T>)this).GetEnumerator();
}
}
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)
{
Func<T, IOption<TResult>> selector2 = selector;
return SelectMany((T t) => selector2(t).Select(Option.Some).OrElse(Option.None));
}
public Option<TResult> SelectMany<TSelectMany, TResult>(Func<T, Option<TSelectMany>> selector, Func<Option<T>, TSelectMany, TResult> resultSelector)
{
Func<Option<T>, TSelectMany, TResult> resultSelector2 = resultSelector;
T valueUnsafe = ValueUnsafe;
Option<T> self = this;
return IsSome ? (from v in selector(valueUnsafe)
select resultSelector2(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;
}
[IteratorStateMachine(typeof(Option<>.<AsEnumerable>d__25))]
public IEnumerable<T> AsEnumerable()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <AsEnumerable>d__25(-2)
{
<>3__<>4__this = this
};
}
public Result<T, TError> ToSuccessOr<TError>(TError error)
{
TError error2 = error;
return Select((Func<T, Result<T, TError>>)((T x) => Result.Success(x))).OrElseGet(() => Result.Error(error2));
}
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;
Option<TOut> result;
if (valueUnsafe is TOut)
{
object obj = valueUnsafe;
TOut value = (TOut)((obj is TOut) ? obj : null);
result = Option.Some(value);
}
else
{
result = Option.None;
}
return result;
}
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 ((object)self is Result<T, TError> result)
{
return result;
}
ref TResult reference = ref self;
TResult val2 = default(TResult);
if (val2 == null)
{
val2 = reference;
reference = ref val2;
}
return reference.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)
{
Func<Result<T, TError>, TMiddle, TResult> resultSelector2 = resultSelector;
return IsError ? ((Result<TResult, TError>)Result.Error(ErrUnsafe)) : (from m in func(ValueUnsafe)
select resultSelector2(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 null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public IDisposable CreateScope()
{
throw null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public void EnterScope(Action action)
{
throw null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public T EnterScope<T>(Func<T> func)
{
throw null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public Task EnterScopeAsync(Action action)
{
throw null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public Task<T> EnterScopeAsync<T>(Func<T> func)
{
throw null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public Task EnterScopeAsync(Func<Task> action)
{
throw null;
}
[ExtensionMarker("<M>$9A581DD593152A881C02B7BBD540726C")]
public Task<T> EnterScopeAsync<T>(Func<Task<T>> action)
{
throw null;
}
}
[SpecialName]
public sealed class <G>$6A188C7A03CB85FC44DF3FD030EA0664
{
[SpecialName]
public static class <M>$438D5453E0DFEE874C985587A0074FB9
{
}
[ExtensionMarker("<M>$438D5453E0DFEE874C985587A0074FB9")]
[DoesNotReturn]
public Never Rethrow()
{
throw null;
}
[ExtensionMarker("<M>$438D5453E0DFEE874C985587A0074FB9")]
[DoesNotReturn]
public T Rethrow<T>()
{
throw null;
}
}
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 ((Delegate?)self == (Delegate?)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)
{
T arg2 = arg;
return SafeInvokeInternal(self, delegate(Action<T> a)
{
a(arg2);
});
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Result<Unit, AggregateException> SafeInvoke<T1, T2>(this Action<T1, T2>? self, T1 arg1, T2 arg2)
{
T1 arg3 = arg1;
T2 arg4 = arg2;
return SafeInvokeInternal(self, delegate(Action<T1, T2> a)
{
a(arg3, arg4);
});
}
[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
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Action <showWarning>P;
public ReflectionFailedError(Action showWarning)
{
<showWarning>P = showWarning;
base..ctor();
}
public void ShowWarning()
{
<showWarning>P();
}
}
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 type2 = AccessTools.TypeByName(typeName);
if (type2 != null)
{
return Result.Success(type2);
}
return Result.Error(new ReflectionFailedError(delegate
{
Plugin.Logger.LogWarning((object)("無法找到 " + typeName + " 類型!無法為 MoreAscents 提供繁中支援... x_x"));
}));
}
}
}
}