Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PELE v1.0.2
plugins/RiskofThunder-R2API_Language/R2API.Language/R2API.Language.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Timers; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using On.RoR2; using On.RoR2.UI; using RoR2; using RoR2.ConVar; using RoR2.UI; using SimpleJSON; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("R2API.Language")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+98b9ba9d40257e1878ab962f3cd1841a2a995892")] [assembly: AssemblyProduct("R2API.Language")] [assembly: AssemblyTitle("R2API.Language")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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; } } } namespace R2API { internal static class ConsoleCommands { [CompilerGenerated] private static class <>O { public static hook_InitConVarsCoroutine <0>__OnConsoleInit; } private static bool _registered; internal static void Init() { //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_001b: Expected O, but got Unknown object obj = <>O.<0>__OnConsoleInit; if (obj == null) { hook_InitConVarsCoroutine val = OnConsoleInit; <>O.<0>__OnConsoleInit = val; obj = (object)val; } Console.InitConVarsCoroutine += (hook_InitConVarsCoroutine)obj; } internal static void Cleanup() { //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_001b: Expected O, but got Unknown object obj = <>O.<0>__OnConsoleInit; if (obj == null) { hook_InitConVarsCoroutine val = OnConsoleInit; <>O.<0>__OnConsoleInit = val; obj = (object)val; } Console.InitConVarsCoroutine -= (hook_InitConVarsCoroutine)obj; } private static IEnumerator OnConsoleInit(orig_InitConVarsCoroutine orig, Console self) { yield return orig.Invoke(self); RegisterCommands(); } private static void RegisterCommands() { //IL_0155: Unknown result type (might be due to invalid IL or missing references) if (_registered) { return; } _registered = true; Console instance = Console.instance; if ((Object)(object)instance == (Object)null) { return; } FieldInfo field = typeof(Console).GetField("concommandCatalog", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogWarning((object)"concommandCatalog field not found via reflection"); } return; } Type nestedType = typeof(Console).GetNestedType("ConCommand", BindingFlags.NonPublic); if (nestedType == null) { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)"ConCommand nested type not found"); } return; } if (!(field.GetValue(instance) is IDictionary dictionary)) { ManualLogSource logger3 = LanguagePlugin.Logger; if (logger3 != null) { logger3.LogWarning((object)"concommandCatalog is null"); } return; } FieldInfo field2 = nestedType.GetField("flags"); FieldInfo field3 = nestedType.GetField("helpText"); FieldInfo field4 = nestedType.GetField("action", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field4 == null) { ManualLogSource logger4 = LanguagePlugin.Logger; if (logger4 != null) { logger4.LogWarning((object)"ConCommand.action field not found"); } return; } Type fieldType = field4.FieldType; int num = 0; Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { ConCommandAttribute customAttribute = ((MemberInfo)methodInfo).GetCustomAttribute<ConCommandAttribute>(); if (customAttribute == null) { continue; } try { object obj = Activator.CreateInstance(nestedType); field2?.SetValue(obj, customAttribute.flags); field3?.SetValue(obj, customAttribute.helpText); field4.SetValue(obj, Delegate.CreateDelegate(fieldType, methodInfo)); dictionary[customAttribute.commandName.ToLower()] = obj; num++; } catch (Exception ex) { ManualLogSource logger5 = LanguagePlugin.Logger; if (logger5 != null) { logger5.LogWarning((object)("Falha ao registrar comando '" + customAttribute.commandName + "': " + ex.Message)); } } } } if (num > 0) { ManualLogSource logger6 = LanguagePlugin.Logger; if (logger6 != null) { logger6.LogInfo((object)$"Console commands registered ({num}): /reloadlang, /langdebug, /langstatus"); } } } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CC_ReloadLang(ConCommandArgs args) { LanguageAPI.InvalidateDiskCache(); LanguageAPI.ReloadAllLanguageFiles(Paths.PluginPath); LanguagePlugin.ReloadPeleJsonFiles(); Debug.Log((object)"[R2API.Language] /reloadlang: todos os arquivos recarregados."); } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CC_LangDebug(ConCommandArgs args) { if (!LanguagePlugin.EnableDebugMenu) { Debug.Log((object)"[R2API.Language] /langdebug: EnableDebugMenu=false no config."); return; } LanguageDebugUI.Toggle(); Debug.Log((object)"[R2API.Language] /langdebug: janela de debug alternada."); } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CC_LangStatus(ConCommandArgs args) { string text = string.Join(", ", LanguagePlugin.GetRegisteredCustomLangs()); string text2 = string.Join(", ", LanguagePlugin.GetFallbackLangs()); string currentLanguageName = Language.currentLanguageName; int totalCustomTokens = LanguageAPI.GetTotalCustomTokens(); int languageFileCount = LanguageAPI.GetLanguageFileCount(); int peleJsonFileCount = LanguageAPI.GetPeleJsonFileCount(); string text3 = string.Join(", ", LanguageAPI.GetPeleLanguageFolders()); string text4 = (LanguageAPI.IsHotReloadEnabled ? "ativo" : "inativo"); Debug.Log((object)"[R2API.Language] === Status ==="); Debug.Log((object)(" Current language: " + currentLanguageName)); Debug.Log((object)(" Custom langs: " + text)); Debug.Log((object)(" Fallback (en): " + text2)); Debug.Log((object)(" Hot-Reload: " + text4)); Debug.Log((object)$" .language files: {languageFileCount}"); Debug.Log((object)$" PELE JSON files: {peleJsonFileCount}"); Debug.Log((object)(" PELE language folders: " + text3)); Debug.Log((object)$" API tokens: {totalCustomTokens}"); Debug.Log((object)"[R2API.Language] ==============="); } } internal static class CustomLanguageRegistration { private static readonly string[] CustomLangs = new string[3] { "la", "eo", "uk" }; private static readonly string[] CultureFallbackLangs = new string[2] { "la", "eo" }; internal static string[] GetRegisteredCustomLangs() { return (string[])CustomLangs.Clone(); } internal static string[] GetFallbackLangs() { return (string[])CultureFallbackLangs.Clone(); } internal static string FixCultureName(string name) { if (Array.IndexOf(CultureFallbackLangs, name) >= 0) { return "en"; } return name; } [HarmonyPostfix] [HarmonyPatch(typeof(Language), "FindLanguageByName")] private static void FindLanguageByNamePostfix(string __0, ref Language __result) { if (__result != null || Array.IndexOf(CustomLangs, __0) < 0) { return; } Dictionary<string, Language> languagesByName = GetLanguagesByName(); if (languagesByName == null) { return; } if (languagesByName.TryGetValue(__0, out var value)) { __result = value; return; } Language val = CreateLanguage(__0); if (val != null) { languagesByName[__0] = val; __result = val; LanguagePlugin.LogVerbose("Lazy-registrado: " + __0); } } private static Dictionary<string, Language> GetLanguagesByName() { return (Dictionary<string, Language>)(typeof(Language).GetField("languagesByName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null)); } private static Language CreateLanguage(string lang) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown try { ConstructorInfo constructor = typeof(Language).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (constructor == null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogError((object)("CreateLanguage: Construtor Language(string) nao encontrado para " + lang)); } return null; } Language val = (Language)constructor.Invoke(new object[1] { lang }); FieldInfo fieldInfo = typeof(Language).GetField("name", BindingFlags.Instance | BindingFlags.Public) ?? typeof(Language).GetField("_name", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Language).GetField("name", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Language).GetField("<name>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (fieldInfo == null) { FieldInfo[] fields = typeof(Language).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { if (!(fieldInfo2.FieldType != typeof(string)) && (string)fieldInfo2.GetValue(val) == lang) { fieldInfo = fieldInfo2; break; } } } fieldInfo?.SetValue(val, lang); MethodInfo method = typeof(Language).GetMethod("SetFolders", BindingFlags.Instance | BindingFlags.NonPublic); string text = Path.Combine(Path.Combine(Paths.PluginPath, "PELE", "Language"), lang); if (Directory.Exists(text)) { method?.Invoke(val, new object[1] { new string[1] { text } }); } string text2 = ((fieldInfo != null) ? ((string)fieldInfo.GetValue(val)) : "(field not found)"); LanguagePlugin.LogVerbose("CreateLanguage: '" + lang + "' ok (nameField='" + text2 + "')"); return val; } catch (Exception ex) { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogError((object)("CreateLanguage falhou para " + lang + ": " + (ex.InnerException?.Message ?? ex.Message))); } ManualLogSource logger3 = LanguagePlugin.Logger; if (logger3 != null) { logger3.LogError((object)(" Stack: " + (ex.InnerException?.StackTrace ?? ex.StackTrace))); } return null; } } [HarmonyPrefix] [HarmonyPatch(typeof(Language), "SetCurrentLanguage")] private static bool SetCurrentLanguagePrefix(string newCurrentLanguageName) { if (Array.IndexOf(CustomLangs, newCurrentLanguageName) < 0) { return true; } try { Language val = Language.FindLanguageByName(newCurrentLanguageName); if (val == null) { return true; } if (Language.currentLanguage != null && Language.currentLanguage != Language.english) { Language.currentLanguage.UnloadStrings(); } (typeof(Language).GetField("<currentLanguageName>k__BackingField", BindingFlags.Static | BindingFlags.NonPublic) ?? typeof(Language).GetField("currentLanguageName", BindingFlags.Static | BindingFlags.NonPublic) ?? typeof(Language).GetField("_currentLanguageName", BindingFlags.Static | BindingFlags.NonPublic))?.SetValue(null, newCurrentLanguageName); (typeof(Language).GetField("<currentLanguage>k__BackingField", BindingFlags.Static | BindingFlags.NonPublic) ?? typeof(Language).GetField("currentLanguage", BindingFlags.Static | BindingFlags.NonPublic) ?? typeof(Language).GetField("_currentLanguage", BindingFlags.Static | BindingFlags.NonPublic) ?? typeof(Language).GetField("currentLanguage", BindingFlags.Static | BindingFlags.Public))?.SetValue(null, val); CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(FixCultureName(val.name)); val.LoadStrings(); (typeof(Language).GetField("onCurrentLanguageChanged", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as Action)?.Invoke(); LanguagePlugin.LogVerbose("SetCurrentLanguage interceptado: '" + newCurrentLanguageName + "' (CultureInfo='" + CultureInfo.CurrentCulture.Name + "')"); } catch (Exception ex) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogError((object)("SetCurrentLanguagePrefix falhou: " + (ex.InnerException?.Message ?? ex.Message))); } return true; } return false; } } internal static class CyrillicFontSupport { private static TMP_FontAsset _cachedEmbeddedFont; private static AssetBundle _cachedEmbeddedFontBundle; private static TMP_FontAsset _vanillaDefaultFont; private static TMP_FontAsset _cyrillicFont; private static TMP_FontAsset _bombardierDefaultFont; private static AssetBundle _cyrillicFontBundle; private static bool _cyrillicFontProbeDone; [HarmonyPostfix] [HarmonyPatch(typeof(HGTextMeshProUGUI), "OnCurrentLanguageChanged")] private static void OnLanguageChanged() { if (_vanillaDefaultFont == null) { _vanillaDefaultFont = HGTextMeshProUGUI.defaultLanguageFont; } HGTextMeshProUGUI.defaultLanguageFont = GetCustomFontForCurrentLanguage() ?? _vanillaDefaultFont; ApplyCurrentFontToActiveText(); } [HarmonyPostfix] [HarmonyPatch(typeof(TextMeshProUGUI), "LoadFontAsset")] private static void TextMeshProUGUI_LoadFontAsset_Postfix(TextMeshProUGUI __instance) { TMP_FontAsset cyrillicFont = GetCyrillicFont(); if ((Object)(object)cyrillicFont == (Object)null || (Object)(object)__instance == (Object)null) { return; } TMP_FontAsset font = ((TMP_Text)__instance).font; if (!((Object)(object)font == (Object)null)) { TMP_FontAsset val = _bombardierDefaultFont ?? _vanillaDefaultFont; if ((Object)(object)font == (Object)(object)val || ((Object)font).name.IndexOf("Bomb", StringComparison.OrdinalIgnoreCase) >= 0) { ((TMP_Text)__instance).font = cyrillicFont; } } } internal static TMP_FontAsset GetCyrillicFont() { if (_cyrillicFontProbeDone) { return _cyrillicFont; } _cyrillicFontProbeDone = true; _cyrillicFont = TryLoadCyrillicFontBundle() ?? TryGetExternalCyrillicFont() ?? TryLoadEmbeddedFont("ukrainianfont"); if ((Object)(object)_cyrillicFont != (Object)null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogInfo((object)"Fonte cirilica do PELE ativa."); } } else { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)"Nenhuma fonte cirilica encontrada; caracteres ucranianos podem aparecer como '?'."); } } return _cyrillicFont; } private static TMP_FontAsset GetCustomFontForCurrentLanguage() { string currentLanguageName = Language.currentLanguageName; if (currentLanguageName == null) { return null; } if (!"uk".Equals(currentLanguageName, StringComparison.OrdinalIgnoreCase)) { return null; } return GetCyrillicFont(); } private static TMP_FontAsset TryGetExternalCyrillicFont() { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("AnotherOneCyrillicFont.AnotherOneCyrillicFont", throwOnError: false); if (!(type == null)) { FieldInfo field = type.GetField("fontBomb", BindingFlags.Static | BindingFlags.Public); FieldInfo? field2 = type.GetField("fontBombDefault", BindingFlags.Static | BindingFlags.Public); object? obj = field?.GetValue(null); TMP_FontAsset val = (TMP_FontAsset)((obj is TMP_FontAsset) ? obj : null); object? obj2 = field2?.GetValue(null); TMP_FontAsset val2 = (TMP_FontAsset)((obj2 is TMP_FontAsset) ? obj2 : null); if ((Object)(object)val2 != (Object)null) { _bombardierDefaultFont = val2; } if ((Object)(object)val != (Object)null) { return val; } } } } catch (Exception ex) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogWarning((object)("TryGetExternalCyrillicFont falhou: " + ex.Message)); } } return null; } private static TMP_FontAsset TryLoadCyrillicFontBundle() { try { string text = FindCyrillicFontBundlePath(); if (text == null) { return null; } _cyrillicFontBundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_cyrillicFontBundle == (Object)null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogWarning((object)"TryLoadCyrillicFontBundle: AssetBundle retornou null."); } return null; } TMP_FontAsset obj = _cyrillicFontBundle.LoadAsset<TMP_FontAsset>("Assets/CyrillicFont/tmpBombDropshadow.asset") ?? _cyrillicFontBundle.LoadAllAssets<TMP_FontAsset>().FirstOrDefault(); if ((Object)(object)obj != (Object)null) { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogInfo((object)"Fonte cirilica carregada de bundle PELE."); } } return obj; } catch (Exception ex) { ManualLogSource logger3 = LanguagePlugin.Logger; if (logger3 != null) { logger3.LogWarning((object)("TryLoadCyrillicFontBundle falhou: " + ex.Message)); } return null; } } private static string FindCyrillicFontBundlePath() { string[] array = new string[2] { Path.Combine(Paths.PluginPath, "PELE", "Fonts", "cyrillicfont"), Path.Combine(Paths.PluginPath, "PELE", "cyrillicfont") }; foreach (string text in array) { if (File.Exists(text)) { return text; } } return Directory.GetFiles(Paths.PluginPath, "cyrillicfont", SearchOption.AllDirectories).FirstOrDefault(); } private static TMP_FontAsset TryLoadEmbeddedFont(string resourceName) { if ((Object)(object)_cachedEmbeddedFont != (Object)null) { return _cachedEmbeddedFont; } try { if ((Object)(object)_cachedEmbeddedFontBundle == (Object)null) { Stream stream = TryGetResourceStream(resourceName); if (stream == null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogWarning((object)("TryLoadEmbeddedFont: recurso embutido nao encontrado: " + resourceName)); } return null; } using (stream) { _cachedEmbeddedFontBundle = AssetBundle.LoadFromStream(stream); } if ((Object)(object)_cachedEmbeddedFontBundle == (Object)null) { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogWarning((object)("TryLoadEmbeddedFont: AssetBundle retornou null: " + resourceName)); } return null; } } TMP_FontAsset val = _cachedEmbeddedFontBundle.LoadAsset<TMP_FontAsset>("Assets/PELE-Font.asset") ?? _cachedEmbeddedFontBundle.LoadAsset<TMP_FontAsset>("PELE-Font") ?? _cachedEmbeddedFontBundle.LoadAsset<TMP_FontAsset>("ukrainianfont") ?? _cachedEmbeddedFontBundle.LoadAllAssets<TMP_FontAsset>().FirstOrDefault(); if ((Object)(object)val == (Object)null) { ManualLogSource logger3 = LanguagePlugin.Logger; if (logger3 != null) { logger3.LogWarning((object)("TryLoadEmbeddedFont: TMP_FontAsset nao encontrado no bundle '" + resourceName + "'")); } return null; } _cachedEmbeddedFont = val; ManualLogSource logger4 = LanguagePlugin.Logger; if (logger4 != null) { logger4.LogInfo((object)"Fonte cirilica embutida carregada."); } return _cachedEmbeddedFont; } catch (Exception ex) { ManualLogSource logger5 = LanguagePlugin.Logger; if (logger5 != null) { logger5.LogWarning((object)("TryLoadEmbeddedFont falhou: " + ex.Message)); } return null; } } private static void ApplyCurrentFontToActiveText() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) TMP_FontAsset defaultLanguageFont = HGTextMeshProUGUI.defaultLanguageFont; if ((Object)(object)defaultLanguageFont == (Object)null) { return; } HGTextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll<HGTextMeshProUGUI>(); foreach (HGTextMeshProUGUI val in array) { if (!((Object)(object)val == (Object)null)) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { ((TMP_Text)val).font = defaultLanguageFont; ((Graphic)val).SetAllDirty(); } } } } private static Stream TryGetResourceStream(string resourceName) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); return executingAssembly.GetManifestResourceStream("R2API.Language." + resourceName) ?? executingAssembly.GetManifestResourceStream("PELE." + resourceName); } } public class DuplicateTokenDetector { public List<DuplicateEntry> FindDuplicateTokens(string directory) { string[] languageFiles; try { languageFiles = LanguageFileHelper.GetLanguageFiles(directory); } catch (DirectoryNotFoundException) { return new List<DuplicateEntry>(); } Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); string[] array = languageFiles; foreach (string text in array) { Dictionary<string, Dictionary<string, string>> dictionary2; try { dictionary2 = LanguageFileHelper.ParseTokensFromFile(text); } catch { continue; } string fileName = Path.GetFileName(text); foreach (KeyValuePair<string, Dictionary<string, string>> item in dictionary2) { string key = item.Key; foreach (string key3 in item.Value.Keys) { string key2 = key + ":" + key3; if (!dictionary.TryGetValue(key2, out var value)) { value = (dictionary[key2] = new List<string>()); } if (!value.Contains<string>(fileName, StringComparer.OrdinalIgnoreCase)) { value.Add(fileName); } } } } return (from d in dictionary.Where((KeyValuePair<string, List<string>> kvp) => kvp.Value.Count > 1).Select(delegate(KeyValuePair<string, List<string>> kvp) { string[] array2 = kvp.Key.Split(new char[1] { ':' }, 2); return new DuplicateEntry { Language = ((array2.Length > 1) ? array2[0] : ""), TokenName = ((array2.Length > 1) ? array2[1] : kvp.Key), Files = kvp.Value, Count = kvp.Value.Count }; }) orderby d.Count descending select d).ToList(); } public bool HasDuplicates(string tokenName, string directory) { return FindDuplicateTokens(directory).Any((DuplicateEntry d) => d.TokenName.Equals(tokenName, StringComparison.OrdinalIgnoreCase)); } } public class DuplicateEntry { public string TokenName { get; set; } public string Language { get; set; } public List<string> Files { get; set; } public int Count { get; set; } } public static class LanguageAPI { public class LanguageOverlay { private readonly List<OverlayTokenData> _overlayTokenDatas; public readonly ReadOnlyCollection<OverlayTokenData> readOnlyOverlays; internal LanguageOverlay(List<OverlayTokenData> data) { _overlayTokenDatas = data; readOnlyOverlays = data.AsReadOnly(); Apply(); temporaryOverlays.Add(this); } private void Apply() { _rwLock.EnterWriteLock(); try { ApplyUnderLock(); } finally { _rwLock.ExitWriteLock(); } } private void ApplyUnderLock() { foreach (OverlayTokenData readOnlyOverlay in readOnlyOverlays) { if (!OverlayLanguage.TryGetValue(readOnlyOverlay.lang, out Dictionary<string, string> value)) { value = new Dictionary<string, string>(); OverlayLanguage[readOnlyOverlay.lang] = value; } value[readOnlyOverlay.key] = readOnlyOverlay.value; } } public void Remove() { SetHooks(); temporaryOverlays.Remove(this); _rwLock.EnterWriteLock(); try { OverlayLanguage.Clear(); foreach (LanguageOverlay temporaryOverlay in temporaryOverlays) { temporaryOverlay.ApplyUnderLock(); } } finally { _rwLock.ExitWriteLock(); } } } public struct OverlayTokenData { public string key; public string value; public string lang; internal OverlayTokenData(string _key, string _value, string _lang) { key = _key; value = _value; lang = _lang; } internal OverlayTokenData(string _key, string _value) { key = _key; value = _value; lang = "generic"; } } [CompilerGenerated] private static class <>O { public static hook_GetLocalizedStringByToken <0>__Language_GetLocalizedStringByToken; public static hook_TokenIsRegistered <1>__Language_TokenIsRegistered; public static Func<string, string> <2>__GetFileName; } public const string PluginGUID = "com.bepis.r2api.language"; public const string PluginName = "R2API.Language (Jaosnake fork)"; public const string PluginVersion = "2.0.0"; private static readonly Dictionary<string, Dictionary<string, string>> CustomLanguage = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Dictionary<string, string>> OverlayLanguage = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); private static readonly List<LanguageOverlay> temporaryOverlays = new List<LanguageOverlay>(); private static readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); private static LanguageHotReload _hotReload; private static Dictionary<string, int> _peleTokenCountCache; private static DateTime _peleTokenCacheTime = DateTime.MinValue; private static int _cachedLanguageFileCount; private static int _cachedPeleJsonFileCount; private static string[] _cachedPeleFolders; private static Dictionary<string, List<string>> _cachedModFiles; private static DateTime _diskCacheTime = DateTime.MinValue; private const string GenericLanguage = "generic"; private const string GenericLegacyName = "strings"; private static bool _hooksEnabled = false; public static bool Loaded => true; internal static ManualLogSource Log { get; set; } internal static bool IsHotReloadEnabled => _hotReload?.IsEnabled ?? false; internal static void SetHooks() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown if (!_hooksEnabled) { _hooksEnabled = true; LoadLanguageFilesFromPluginFolder(); object obj = <>O.<0>__Language_GetLocalizedStringByToken; if (obj == null) { hook_GetLocalizedStringByToken val = Language_GetLocalizedStringByToken; <>O.<0>__Language_GetLocalizedStringByToken = val; obj = (object)val; } Language.GetLocalizedStringByToken += (hook_GetLocalizedStringByToken)obj; object obj2 = <>O.<1>__Language_TokenIsRegistered; if (obj2 == null) { hook_TokenIsRegistered val2 = Language_TokenIsRegistered; <>O.<1>__Language_TokenIsRegistered = val2; obj2 = (object)val2; } Language.TokenIsRegistered += (hook_TokenIsRegistered)obj2; } } private static void LoadLanguageFilesFromPluginFolder() { string[] files = Directory.GetFiles(Paths.PluginPath, "*.language", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { AddPath(files[i]); } } internal static void UnsetHooks() { //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_001b: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown object obj = <>O.<0>__Language_GetLocalizedStringByToken; if (obj == null) { hook_GetLocalizedStringByToken val = Language_GetLocalizedStringByToken; <>O.<0>__Language_GetLocalizedStringByToken = val; obj = (object)val; } Language.GetLocalizedStringByToken -= (hook_GetLocalizedStringByToken)obj; object obj2 = <>O.<1>__Language_TokenIsRegistered; if (obj2 == null) { hook_TokenIsRegistered val2 = Language_TokenIsRegistered; <>O.<1>__Language_TokenIsRegistered = val2; obj2 = (object)val2; } Language.TokenIsRegistered -= (hook_TokenIsRegistered)obj2; _hooksEnabled = false; } internal static void DisposeLock() { } private static bool TryGetToken(Dictionary<string, Dictionary<string, string>> dict, string lang, string token, out string value) { _rwLock.EnterReadLock(); try { if (dict.TryGetValue(lang, out Dictionary<string, string> value2) && value2.TryGetValue(token, out value)) { return true; } if (dict.TryGetValue("generic", out Dictionary<string, string> value3) && value3.TryGetValue(token, out value)) { return true; } value = null; return false; } finally { _rwLock.ExitReadLock(); } } private static bool TokenExists(Dictionary<string, Dictionary<string, string>> dict, string lang, string token) { _rwLock.EnterReadLock(); try { Dictionary<string, string> value; Dictionary<string, string> value2; return (dict.TryGetValue(lang, out value) && value.ContainsKey(token)) || (dict.TryGetValue("generic", out value2) && value2.ContainsKey(token)); } finally { _rwLock.ExitReadLock(); } } private static bool Language_TokenIsRegistered(orig_TokenIsRegistered orig, Language self, string token) { string name = self.name; if (TokenExists(OverlayLanguage, name, token)) { return true; } if (TokenExists(CustomLanguage, name, token)) { return true; } return orig.Invoke(self, token); } private static string Language_GetLocalizedStringByToken(orig_GetLocalizedStringByToken orig, Language self, string token) { string name = self.name; if (TryGetToken(OverlayLanguage, name, token, out string value)) { return value; } if (TryGetToken(CustomLanguage, name, token, out value)) { return value; } return orig.Invoke(self, token); } private static Dictionary<string, Dictionary<string, string>> LoadFile(string fileContent) { Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(); try { JSONNode val = JSON.Parse(fileContent); if (val == (object)null) { return null; } foreach (string key2 in val.Keys) { JSONNode val2 = val[key2]; if (val2 == (object)null) { continue; } string key = ((key2 == "strings") ? "generic" : key2); if (!dictionary.TryGetValue(key, out var value)) { value = (dictionary[key] = new Dictionary<string, string>()); } foreach (string key3 in val2.Keys) { value[key3] = val2[key3].Value; } } } catch (Exception ex) { Debug.LogFormat("Parsing error in language file, Error: {0}", new object[1] { ex }); return null; } if (dictionary.Count <= 0) { return null; } return dictionary; } public static void Add(string key, string value) { SetHooks(); Add(key, value, "generic"); } public static void Add(string key, string value, string language) { SetHooks(); if (key == null) { throw new ArgumentNullException("key"); } if (value == null) { throw new ArgumentNullException("value"); } if (language == null) { throw new ArgumentNullException("language"); } _rwLock.EnterWriteLock(); try { if (!CustomLanguage.TryGetValue(language, out Dictionary<string, string> value2)) { value2 = new Dictionary<string, string>(); CustomLanguage[language] = value2; } if (!value2.ContainsKey(key)) { value2[key] = value; } } finally { _rwLock.ExitWriteLock(); } } public static void AddPath(string path) { SetHooks(); if (path == null) { throw new ArgumentNullException("path"); } Add(File.ReadAllText(path)); } public static void Add(string file) { SetHooks(); if (file == null) { throw new ArgumentNullException("file"); } Dictionary<string, Dictionary<string, string>> dictionary = LoadFile(file); if (dictionary != null) { Add(dictionary); } } public static void Add(Dictionary<string, string> tokenDictionary) { SetHooks(); Add(tokenDictionary, "generic"); } public static void Add(Dictionary<string, string> tokenDictionary, string language) { SetHooks(); if (tokenDictionary == null) { throw new ArgumentNullException("tokenDictionary"); } foreach (KeyValuePair<string, string> item in tokenDictionary) { if (item.Value != null) { Add(item.Key, item.Value, language); } } } public static void Add(Dictionary<string, Dictionary<string, string>> languageDictionary) { SetHooks(); if (languageDictionary == null) { throw new ArgumentNullException("languageDictionary"); } foreach (KeyValuePair<string, Dictionary<string, string>> item in languageDictionary) { if (item.Value != null) { Add(item.Value, item.Key); } } } public static void AddOrUpdateToken(string key, string value) { SetHooks(); AddOrUpdateToken(key, value, "generic"); } public static void AddOrUpdateToken(string key, string value, string language) { SetHooks(); if (string.IsNullOrEmpty(key)) { throw new ArgumentNullException("key"); } if (value == null) { throw new ArgumentNullException("value"); } if (string.IsNullOrEmpty(language)) { language = "generic"; } _rwLock.EnterWriteLock(); try { if (!CustomLanguage.TryGetValue(language, out Dictionary<string, string> value2)) { value2 = new Dictionary<string, string>(); CustomLanguage[language] = value2; } value2[key] = value; } finally { _rwLock.ExitWriteLock(); } } public static void RemoveToken(string key, string language = null) { SetHooks(); if (string.IsNullOrEmpty(key)) { return; } string key2 = language ?? "generic"; _rwLock.EnterWriteLock(); try { if (CustomLanguage.TryGetValue(key2, out Dictionary<string, string> value)) { value.Remove(key); } } finally { _rwLock.ExitWriteLock(); } } public static void ClearAllTokens() { SetHooks(); _rwLock.EnterWriteLock(); try { CustomLanguage.Clear(); } finally { _rwLock.ExitWriteLock(); } } public static void EnableHotReload(string directory) { SetHooks(); if (_hotReload == null) { _hotReload = LanguageHotReload.Instance; } _hotReload.Enable(directory); } public static void DisableHotReload() { _hotReload?.Disable(); } public static void ReloadAllLanguageFiles(string directory) { SetHooks(); ClearAllTokens(); string[] languageFiles = LanguageFileHelper.GetLanguageFiles(directory); foreach (string text in languageFiles) { try { foreach (KeyValuePair<string, Dictionary<string, string>> item in LanguageFileHelper.ParseTokensFromFile(text)) { foreach (KeyValuePair<string, string> item2 in item.Value) { AddOrUpdateToken(item2.Key, item2.Value, item.Key); } } } catch (Exception ex) { Debug.LogError((object)("[LanguageAPI] Erro ao recarregar " + text + ": " + ex.Message)); } } } public static ValidationResult ValidateLanguageFile(string filePath) { SetHooks(); return new LanguageFileValidator().ValidateFile(filePath); } public static List<DuplicateEntry> FindDuplicateTokens(string directory) { SetHooks(); return new DuplicateTokenDetector().FindDuplicateTokens(directory); } public static List<string> FindUnusedTokens(string directory) { SetHooks(); return new TokenUsageAnalyzer().FindUnusedTokens(directory); } public static void CompileLanguageFiles(string sourceDirectory, string outputDirectory) { SetHooks(); new LanguageFileCompiler().CompileLanguageFiles(sourceDirectory, outputDirectory); } public static LanguageOverlay AddOverlay(string key, string value) { SetHooks(); return AddOverlay(key, value, "generic"); } public static LanguageOverlay AddOverlay(string key, string value, string lang) { SetHooks(); if (key == null) { throw new ArgumentNullException("key"); } if (value == null) { throw new ArgumentNullException("value"); } if (lang == null) { throw new ArgumentNullException("lang"); } return new LanguageOverlay(new List<OverlayTokenData>(1) { new OverlayTokenData(key, value, lang) }); } public static LanguageOverlay AddOverlayPath(string path) { SetHooks(); if (path == null) { throw new ArgumentNullException("path"); } return AddOverlay(File.ReadAllText(path)); } public static LanguageOverlay AddOverlay(string file) { SetHooks(); if (file == null) { throw new ArgumentNullException("file"); } Dictionary<string, Dictionary<string, string>> dictionary = LoadFile(file); if (dictionary == null) { return null; } return AddOverlay(dictionary); } public static LanguageOverlay AddOverlay(Dictionary<string, string> tokenDictionary) { SetHooks(); return AddOverlay(tokenDictionary, "generic"); } public static LanguageOverlay AddOverlay(Dictionary<string, string> tokenDictionary, string language) { SetHooks(); if (tokenDictionary == null) { throw new ArgumentNullException("tokenDictionary"); } if (language == null) { throw new ArgumentNullException("language"); } List<OverlayTokenData> list = new List<OverlayTokenData>(tokenDictionary.Count); foreach (KeyValuePair<string, string> item in tokenDictionary) { if (item.Value != null) { list.Add(new OverlayTokenData(item.Key, item.Value, language)); } } return new LanguageOverlay(list); } public static LanguageOverlay AddOverlay(Dictionary<string, Dictionary<string, string>> languageDictionary) { SetHooks(); if (languageDictionary == null) { throw new ArgumentNullException("languageDictionary"); } List<OverlayTokenData> list = new List<OverlayTokenData>(); foreach (KeyValuePair<string, Dictionary<string, string>> item in languageDictionary) { item.Deconstruct(out var key, out var value); string lang = key; Dictionary<string, string> dictionary = value; if (dictionary == null) { continue; } foreach (KeyValuePair<string, string> item2 in dictionary) { item2.Deconstruct(out key, out var value2); string key2 = key; string text = value2; if (text != null) { list.Add(new OverlayTokenData(key2, text, lang)); } } } return new LanguageOverlay(list); } internal static Dictionary<string, int> GetCustomTokenCounts() { _rwLock.EnterReadLock(); try { Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (KeyValuePair<string, Dictionary<string, string>> item in CustomLanguage) { dictionary[item.Key] = item.Value.Count; } foreach (KeyValuePair<string, Dictionary<string, string>> item2 in OverlayLanguage) { dictionary[item2.Key] = dictionary.GetValueOrDefault(item2.Key) + item2.Value.Count; } return dictionary; } finally { _rwLock.ExitReadLock(); } } internal static int GetTotalCustomTokens() { _rwLock.EnterReadLock(); try { return CustomLanguage.Sum<KeyValuePair<string, Dictionary<string, string>>>((KeyValuePair<string, Dictionary<string, string>> kvp) => kvp.Value.Count) + OverlayLanguage.Sum<KeyValuePair<string, Dictionary<string, string>>>((KeyValuePair<string, Dictionary<string, string>> kvp) => kvp.Value.Count); } finally { _rwLock.ExitReadLock(); } } internal static IEnumerable<string> GetCustomLanguages() { _rwLock.EnterReadLock(); try { return (from x in CustomLanguage.Keys.Union(OverlayLanguage.Keys).Distinct<string>(StringComparer.OrdinalIgnoreCase) orderby x select x).ToList(); } finally { _rwLock.ExitReadLock(); } } internal static void InvalidateDiskCache() { _diskCacheTime = DateTime.MinValue; _peleTokenCacheTime = DateTime.MinValue; } internal static void RefreshDiskCache() { _diskCacheTime = DateTime.UtcNow; try { _cachedLanguageFileCount = Directory.GetFiles(Paths.PluginPath, "*.language", SearchOption.AllDirectories).Length; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("GetLanguageFileCount: " + ex.Message)); } _cachedLanguageFileCount = 0; } string path = Path.Combine(Paths.PluginPath, "PELE", "Language"); try { _cachedPeleJsonFileCount = (Directory.Exists(path) ? Directory.GetFiles(path, "*.json", SearchOption.AllDirectories).Length : 0); } catch (Exception ex2) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("GetPeleJsonFileCount: " + ex2.Message)); } _cachedPeleJsonFileCount = 0; } try { _cachedPeleFolders = (Directory.Exists(path) ? Directory.GetDirectories(path).Select(Path.GetFileName).ToArray() : Array.Empty<string>()); } catch (Exception ex3) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)("GetPeleLanguageFolders: " + ex3.Message)); } _cachedPeleFolders = Array.Empty<string>(); } try { _cachedModFiles = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase); string[] files = Directory.GetFiles(Paths.PluginPath, "*.language", SearchOption.AllDirectories); foreach (string text in files) { DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(text)); string key = directoryInfo.Parent?.Name ?? directoryInfo.Name; if (!_cachedModFiles.TryGetValue(key, out List<string> value)) { value = new List<string>(); _cachedModFiles[key] = value; } value.Add(text); } } catch (Exception ex4) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)("GetModFiles: " + ex4.Message)); } if (_cachedModFiles == null) { _cachedModFiles = new Dictionary<string, List<string>>(); } } } internal static int GetLanguageFileCount() { if (_diskCacheTime < DateTime.UtcNow.AddSeconds(-5.0)) { RefreshDiskCache(); } return _cachedLanguageFileCount; } internal static int GetPeleJsonFileCount() { if (_diskCacheTime < DateTime.UtcNow.AddSeconds(-5.0)) { RefreshDiskCache(); } return _cachedPeleJsonFileCount; } internal static string[] GetPeleLanguageFolders() { if (_diskCacheTime < DateTime.UtcNow.AddSeconds(-5.0)) { RefreshDiskCache(); } return _cachedPeleFolders ?? Array.Empty<string>(); } internal static Dictionary<string, List<string>> GetModFileGroups() { if (_diskCacheTime < DateTime.UtcNow.AddSeconds(-5.0)) { RefreshDiskCache(); } return _cachedModFiles ?? new Dictionary<string, List<string>>(); } internal static Dictionary<string, int> GetPeleTokenCounts() { if (_peleTokenCacheTime > DateTime.UtcNow.AddSeconds(-5.0)) { return _peleTokenCountCache ?? new Dictionary<string, int>(); } Dictionary<string, int> dictionary = new Dictionary<string, int>(); try { string path = Path.Combine(Paths.PluginPath, "PELE", "Language"); if (!Directory.Exists(path)) { return dictionary; } string[] directories = Directory.GetDirectories(path); foreach (string path2 in directories) { string fileName = Path.GetFileName(path2); int num = 0; string[] files = Directory.GetFiles(path2, "*.json"); foreach (string text in files) { try { JSONNode val = JSON.Parse(File.ReadAllText(text)); if (val != (object)null) { num += CountPeleJsonTokens(val); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Erro ao ler " + text + ": " + ex.Message)); } } } if (num > 0) { dictionary[fileName] = num; } } } catch (Exception ex2) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("GetPeleTokenCounts: " + ex2.Message)); } } _peleTokenCountCache = dictionary; _peleTokenCacheTime = DateTime.UtcNow; return dictionary; } private static int CountPeleJsonTokens(JSONNode json) { if (json == (object)null) { return 0; } JSONNode val = json["strings"]; if (val != (object)null && val.Count > 0) { return CountTokenObject(val); } return CountTokenObject(json, skipManifestKeys: true); } private static int CountTokenObject(JSONNode node, bool skipManifestKeys = false) { int num = 0; foreach (string key in node.Keys) { if ((!skipManifestKeys || !string.Equals(key, "language", StringComparison.OrdinalIgnoreCase)) && (!skipManifestKeys || !string.Equals(key, "strings", StringComparison.OrdinalIgnoreCase)) && !key.StartsWith("_", StringComparison.Ordinal) && node[key] != (object)null && node[key].Count == 0) { num++; } } return num; } } internal class LanguageDebugUI : MonoBehaviour { private static LanguageDebugUI _instance; private bool _visible; private Rect _windowRect; private int _activeTab; private Vector2 _scrollPos; private readonly string[] _tabs = new string[5] { "Linguas", "PELE", "Mods", "Status", "Duplicatas" }; private const string PrefsKeyX = "R2APILang_DebugX"; private const string PrefsKeyY = "R2APILang_DebugY"; private const string PrefsKeyW = "R2APILang_DebugW"; private const string PrefsKeyH = "R2APILang_DebugH"; private List<DuplicateEntry> _duplicates; private bool _duplicatesDirty = true; private bool _scanning; private readonly Queue<Action> _mainThreadQueue = new Queue<Action>(); private int _errorCount = -1; private static MethodInfo _setCurrentLanguageMethod; internal static void Create() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null)) { GameObject val = new GameObject("LanguageDebugUI", new Type[1] { typeof(LanguageDebugUI) }); Object.DontDestroyOnLoad((Object)val); _instance = val.GetComponent<LanguageDebugUI>(); _setCurrentLanguageMethod = typeof(Language).GetMethod("SetCurrentLanguage", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } internal static void DestroyInstance() { if ((Object)(object)_instance != (Object)null) { Object.Destroy((Object)(object)((Component)_instance).gameObject); _instance = null; } } internal static void Toggle() { if ((Object)(object)_instance != (Object)null) { _instance._visible = !_instance._visible; } } private void Awake() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) _windowRect = new Rect(PlayerPrefs.GetFloat("R2APILang_DebugX", 50f), PlayerPrefs.GetFloat("R2APILang_DebugY", 50f), PlayerPrefs.GetFloat("R2APILang_DebugW", 600f), PlayerPrefs.GetFloat("R2APILang_DebugH", 400f)); } private void Update() { if (Input.GetKeyDown((KeyCode)287)) { _visible = !_visible; } ProcessMainThreadQueue(); } private void OnGUI() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (_visible) { _windowRect = GUILayout.Window(999, _windowRect, new WindowFunction(DrawWindow), "R2API.Language Debug", (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.MinWidth(400f), GUILayout.MinHeight(200f) }); } } private void DrawWindow(int _) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Invalid comparison between Unknown and I4 _activeTab = GUILayout.Toolbar(_activeTab, _tabs, Array.Empty<GUILayoutOption>()); _scrollPos = GUILayout.BeginScrollView(_scrollPos, Array.Empty<GUILayoutOption>()); switch (_activeTab) { case 0: DrawLanguagesTab(); break; case 1: DrawPeleTab(); break; case 2: DrawModsTab(); break; case 3: DrawStatusTab(); break; case 4: DrawDuplicatesTab(); break; } GUILayout.EndScrollView(); if ((int)Event.current.type == 1) { SaveWindowRect(); } GUI.DragWindow(); } private void SaveWindowRect() { PlayerPrefs.SetFloat("R2APILang_DebugX", ((Rect)(ref _windowRect)).x); PlayerPrefs.SetFloat("R2APILang_DebugY", ((Rect)(ref _windowRect)).y); PlayerPrefs.SetFloat("R2APILang_DebugW", ((Rect)(ref _windowRect)).width); PlayerPrefs.SetFloat("R2APILang_DebugH", ((Rect)(ref _windowRect)).height); PlayerPrefs.Save(); } private void InvokeSetCurrentLanguage(string lang) { if (_setCurrentLanguageMethod == null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogError((object)"SetCurrentLanguage method not found"); } return; } try { _setCurrentLanguageMethod.Invoke(null, new object[1] { lang }); } catch (Exception ex) { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogError((object)("Falha ao trocar lingua: " + (ex.InnerException?.Message ?? ex.Message))); } } } private void DrawLanguagesTab() { GUILayout.Label("Linguas registradas no jogo — clique Ativar para trocar:", GUI.skin.label, Array.Empty<GUILayoutOption>()); string currentLanguageName = Language.currentLanguageName; List<string> availableLanguages = LanguageNames.GetAvailableLanguages(); if (availableLanguages.Count == 0) { GUILayout.Label(" (nenhuma)", Array.Empty<GUILayoutOption>()); } else { foreach (string item in availableLanguages) { string friendlyName = LanguageNames.GetFriendlyName(item); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(" " + item + " - " + friendlyName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(250f) }); if (item == currentLanguageName) { GUILayout.Label("[ATIVO]", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }); } else if (GUILayout.Button("Ativar", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) })) { InvokeSetCurrentLanguage(item); } GUILayout.EndHorizontal(); } } GUILayout.Space(10f); GUILayout.Label("Tokens customizados por lingua (API):", GUI.skin.label, Array.Empty<GUILayoutOption>()); Dictionary<string, int> customTokenCounts = LanguageAPI.GetCustomTokenCounts(); if (customTokenCounts.Count == 0) { GUILayout.Label(" (nenhum)", Array.Empty<GUILayoutOption>()); } else { foreach (KeyValuePair<string, int> item2 in customTokenCounts.OrderBy((KeyValuePair<string, int> x) => x.Key)) { GUILayout.Label($" {item2.Key}: {item2.Value} tokens", Array.Empty<GUILayoutOption>()); } } GUILayout.Space(5f); GUILayout.Label("Total de tokens via API: " + LanguageAPI.GetTotalCustomTokens(), Array.Empty<GUILayoutOption>()); } private void DrawPeleTab() { string[] peleLanguageFolders = LanguageAPI.GetPeleLanguageFolders(); if (peleLanguageFolders.Length == 0) { GUILayout.Label("Pasta PELE/Language/ nao encontrada.", Array.Empty<GUILayoutOption>()); return; } GUILayout.Label("Pastas de idioma encontradas:", GUI.skin.label, Array.Empty<GUILayoutOption>()); string[] array = peleLanguageFolders; foreach (string text in array) { GUILayout.Label(" " + text, Array.Empty<GUILayoutOption>()); } GUILayout.Space(5f); GUILayout.Label("Arquivos JSON: " + LanguageAPI.GetPeleJsonFileCount(), Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); GUILayout.Label("Tokens por lingua (PELE JSONs):", GUI.skin.label, Array.Empty<GUILayoutOption>()); Dictionary<string, int> peleTokenCounts = LanguageAPI.GetPeleTokenCounts(); if (peleTokenCounts.Count == 0) { GUILayout.Label(" (nenhum token)", Array.Empty<GUILayoutOption>()); return; } foreach (KeyValuePair<string, int> item in peleTokenCounts.OrderBy((KeyValuePair<string, int> x) => x.Key)) { GUILayout.Label($" {item.Key}: {item.Value} tokens", Array.Empty<GUILayoutOption>()); } } private void DrawModsTab() { GUILayout.Label("Mods com arquivos .language:", GUI.skin.label, Array.Empty<GUILayoutOption>()); Dictionary<string, List<string>> modFileGroups = LanguageAPI.GetModFileGroups(); if (modFileGroups.Count == 0) { GUILayout.Label(" (nenhum encontrado)", Array.Empty<GUILayoutOption>()); return; } foreach (KeyValuePair<string, List<string>> item in modFileGroups.OrderBy((KeyValuePair<string, List<string>> x) => x.Key)) { GUILayout.Label($" {item.Key}: {item.Value.Count} arquivo(s)", Array.Empty<GUILayoutOption>()); foreach (string item2 in item.Value.Take(5)) { GUILayout.Label(" " + Path.GetFileName(item2), Array.Empty<GUILayoutOption>()); } if (item.Value.Count > 5) { GUILayout.Label($" ... e mais {item.Value.Count - 5}", Array.Empty<GUILayoutOption>()); } } } private void DrawStatusTab() { GUILayout.Label("Status do Plugin", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUILayout.Label(" DLL: com.bepis.r2api.language v2.0.0", Array.Empty<GUILayoutOption>()); GUILayout.Label(" Hot-Reload: " + (LanguageAPI.IsHotReloadEnabled ? "ATIVO" : "INATIVO"), Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); GUILayout.Label("Diretorios monitorados:", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUILayout.Label(" *.language: " + Paths.PluginPath, Array.Empty<GUILayoutOption>()); GUILayout.Label(" *.json: " + Path.Combine(Paths.PluginPath, "PELE", "Language"), Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); GUILayout.Label("Arquivos carregados:", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUILayout.Label($" .language: {LanguageAPI.GetLanguageFileCount()}", Array.Empty<GUILayoutOption>()); GUILayout.Label($" .json: {LanguageAPI.GetPeleJsonFileCount()}", Array.Empty<GUILayoutOption>()); GUILayout.Label($" Tokens: {LanguageAPI.GetTotalCustomTokens()}", Array.Empty<GUILayoutOption>()); GUILayout.Label(" Erros de sintaxe: " + ((_errorCount >= 0) ? _errorCount.ToString() : "?"), Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); GUILayout.Label("Custom langs:", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUILayout.Label(" " + string.Join(", ", LanguagePlugin.GetRegisteredCustomLangs()), Array.Empty<GUILayoutOption>()); GUILayout.Label(" Com fallback: " + string.Join(", ", LanguagePlugin.GetFallbackLangs()), Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); if (GUILayout.Button("Refresh cache", Array.Empty<GUILayoutOption>())) { LanguageAPI.InvalidateDiskCache(); LanguageAPI.RefreshDiskCache(); _errorCount = CountFileErrors(); _duplicatesDirty = true; } if (GUILayout.Button("Recarregar tudo (F5)", Array.Empty<GUILayoutOption>())) { LanguageAPI.InvalidateDiskCache(); LanguageAPI.ReloadAllLanguageFiles(Paths.PluginPath); LanguagePlugin.ReloadPeleJsonFiles(); _errorCount = CountFileErrors(); _duplicatesDirty = true; } GUILayout.Space(5f); GUILayout.Label("F6 - Alternar esta janela", GUI.skin.label, Array.Empty<GUILayoutOption>()); } private void DrawDuplicatesTab() { if (_duplicatesDirty && !_scanning) { _scanning = true; _duplicates = null; ThreadPool.QueueUserWorkItem(delegate { try { List<DuplicateEntry> result = new DuplicateTokenDetector().FindDuplicateTokens(Paths.PluginPath); _mainThreadQueue.Enqueue(delegate { _duplicates = result; _duplicatesDirty = false; _scanning = false; }); } catch (Exception ex) { Exception ex2 = ex; Exception ex3 = ex2; _mainThreadQueue.Enqueue(delegate { _duplicates = new List<DuplicateEntry>(); _duplicatesDirty = false; _scanning = false; Debug.LogError((object)("Erro ao escanear duplicatas: " + ex3.Message)); }); } }); } if (_scanning) { GUILayout.Label("Escaneando arquivos .language...", Array.Empty<GUILayoutOption>()); return; } if (_duplicates == null || _duplicates.Count == 0) { GUILayout.Label("Nenhum token duplicado encontrado.", Array.Empty<GUILayoutOption>()); return; } GUILayout.Label($"{_duplicates.Count} token(s) duplicado(s):", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUILayout.Space(5f); int count = Math.Min(_duplicates.Count, 50); foreach (DuplicateEntry item in _duplicates.OrderByDescending((DuplicateEntry d) => d.Count).Take(count)) { string arg = (string.IsNullOrEmpty(item.Language) ? "" : ("[" + item.Language + "] ")); GUILayout.Label($" {arg}{item.TokenName} ({item.Count}x)", Array.Empty<GUILayoutOption>()); foreach (string file in item.Files) { GUILayout.Label(" " + file, Array.Empty<GUILayoutOption>()); } GUILayout.Space(3f); } if (_duplicates.Count > 50) { GUILayout.Label($" ... e mais {_duplicates.Count - 50} token(s)", Array.Empty<GUILayoutOption>()); } } private void ProcessMainThreadQueue() { while (_mainThreadQueue.Count > 0) { try { _mainThreadQueue.Dequeue()?.Invoke(); } catch (Exception ex) { Debug.LogError((object)("Error processing main thread queue: " + ex.Message)); } } } private static int CountFileErrors() { int num = 0; try { LanguageFileValidator languageFileValidator = new LanguageFileValidator(); string[] files = Directory.GetFiles(Paths.PluginPath, "*.language", SearchOption.AllDirectories); foreach (string filePath in files) { ValidationResult validationResult = languageFileValidator.ValidateFile(filePath); if (!validationResult.IsValid) { num += validationResult.Errors.Count; } } } catch { } return num; } } public class LanguageFileCompiler { public void CompileLanguageFiles(string sourceDir, string outputDir) { if (!Directory.Exists(sourceDir)) { throw new DirectoryNotFoundException("Origem nao encontrada: " + sourceDir); } if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } string[] languageFiles = LanguageFileHelper.GetLanguageFiles(sourceDir); List<string> list = new List<string>(); string[] array = languageFiles; foreach (string text in array) { try { string contents = CompileFile(text); string relativePath = Path.GetRelativePath(sourceDir, text); string path = Path.Combine(outputDir, relativePath + ".compiled"); string directoryName = Path.GetDirectoryName(path); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(path, contents, Encoding.UTF8); } catch (Exception ex) { list.Add(Path.GetFileName(text) + ": " + ex.Message); } } if (list.Count > 0) { throw new AggregateException("Erros na compilacao:", list.Select((string e) => new Exception(e))); } } private static string CompileFile(string filePath) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("// COMPILED"); stringBuilder.AppendLine("// " + Path.GetFileName(filePath)); stringBuilder.AppendLine(); foreach (KeyValuePair<string, Dictionary<string, string>> item in LanguageFileHelper.ParseTokensFromFile(filePath)) { string key = item.Key; foreach (KeyValuePair<string, string> item2 in item.Value) { stringBuilder.AppendLine(key + "." + item2.Key + "=" + item2.Value); } } return stringBuilder.ToString().TrimEnd(); } } internal static class LanguageFileHelper { public static string[] GetLanguageFiles(string directory) { if (!Directory.Exists(directory)) { throw new DirectoryNotFoundException("Diretorio nao encontrado: " + directory); } return Directory.GetFiles(directory, "*.language", SearchOption.AllDirectories); } public static Dictionary<string, Dictionary<string, string>> ParseTokensFromFile(string filePath) { string text = File.ReadAllText(filePath).TrimStart(); if (text.StartsWith("{")) { return ParseJsonTokens(text); } return ParseSimpleTokens(text, DetectLanguageFromFileName(filePath)); } private static Dictionary<string, Dictionary<string, string>> ParseJsonTokens(string content) { Dictionary<string, Dictionary<string, string>> dictionary = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); JSONNode val = JSON.Parse(content); if (val == (object)null) { return dictionary; } foreach (string key2 in val.Keys) { JSONNode val2 = val[key2]; if (val2 == (object)null) { continue; } string key = (key2.Equals("strings", StringComparison.OrdinalIgnoreCase) ? "generic" : key2); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); foreach (string key3 in val2.Keys) { dictionary2[key3] = val2[key3].Value; } dictionary[key] = dictionary2; } return dictionary; } private static Dictionary<string, Dictionary<string, string>> ParseSimpleTokens(string content, string language) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); string[] array = content.Split('\n'); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (string.IsNullOrWhiteSpace(text) || text.StartsWith("//") || text.StartsWith("@")) { continue; } int num = text.IndexOf('='); if (num >= 1) { string text2 = text.Substring(0, num).Trim(); string text3 = text.Substring(num + 1).Trim(); if (text3.StartsWith("\"") && text3.EndsWith("\"") && text3.Length >= 2) { text3 = text3.Substring(1, text3.Length - 2); } if (!string.IsNullOrEmpty(text2)) { dictionary[text2] = text3; } } } return new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase) { { language, dictionary } }; } internal static string DetectLanguageFromFileName(string filePath) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); if (fileNameWithoutExtension == null) { return "generic"; } if (fileNameWithoutExtension.EndsWith("_eo", StringComparison.OrdinalIgnoreCase)) { return "eo"; } if (fileNameWithoutExtension.EndsWith("_la", StringComparison.OrdinalIgnoreCase)) { return "la"; } if (fileNameWithoutExtension.EndsWith("_uk", StringComparison.OrdinalIgnoreCase)) { return "uk"; } if (fileNameWithoutExtension.EndsWith("_pt-BR", StringComparison.OrdinalIgnoreCase)) { return "pt-BR"; } if (fileNameWithoutExtension.EndsWith("_en", StringComparison.OrdinalIgnoreCase)) { return "en"; } if (fileNameWithoutExtension.EndsWith("_de", StringComparison.OrdinalIgnoreCase)) { return "de"; } if (fileNameWithoutExtension.EndsWith("_fr", StringComparison.OrdinalIgnoreCase)) { return "fr"; } if (fileNameWithoutExtension.EndsWith("_es", StringComparison.OrdinalIgnoreCase)) { return "es-ES"; } if (fileNameWithoutExtension.EndsWith("_ru", StringComparison.OrdinalIgnoreCase)) { return "ru"; } if (fileNameWithoutExtension.EndsWith("_ja", StringComparison.OrdinalIgnoreCase)) { return "ja"; } if (fileNameWithoutExtension.EndsWith("_ko", StringComparison.OrdinalIgnoreCase)) { return "ko"; } if (fileNameWithoutExtension.EndsWith("_zh", StringComparison.OrdinalIgnoreCase)) { return "zh-CN"; } if (fileNameWithoutExtension.EndsWith("_tr", StringComparison.OrdinalIgnoreCase)) { return "tr"; } if (fileNameWithoutExtension.EndsWith("_it", StringComparison.OrdinalIgnoreCase)) { return "it"; } return "generic"; } public static string[] GetCodeFiles(string directory) { if (!Directory.Exists(directory)) { return Array.Empty<string>(); } return Directory.GetFiles(directory, "*.cs", SearchOption.AllDirectories); } } public class LanguageFileValidator { private static readonly Regex TokenPattern = new Regex("^[A-Za-z0-9_.]+\\s*=", RegexOptions.Compiled); private static readonly Regex CommentPattern = new Regex("^\\s*//", RegexOptions.Compiled); private static readonly Regex TokenNameRegex = new Regex("^[A-Za-z0-9_.]+$", RegexOptions.Compiled); public ValidationResult ValidateFile(string filePath) { if (!File.Exists(filePath)) { return ValidationResult.Error("Arquivo nao encontrado: " + filePath); } string[] array = File.ReadAllLines(filePath); List<string> list = new List<string>(); List<string> list2 = new List<string>(); for (int i = 0; i < array.Length; i++) { string text = array[i]; int num = i + 1; if (string.IsNullOrWhiteSpace(text) || CommentPattern.IsMatch(text)) { continue; } string text2 = text.Trim(); if (!(text2 == "{") && !(text2 == "}")) { if (!TokenPattern.IsMatch(text2)) { list.Add($"Linha {num}: Sintaxe invalida: '{text}'"); } if (HasPotentialIssues(text)) { list2.Add($"Linha {num}: Possivel problema de espacos: '{text}'"); } } } return new ValidationResult { IsValid = (list.Count == 0), Errors = list, Warnings = list2, FilePath = filePath }; } public bool ValidateTokenSyntax(string token) { if (string.IsNullOrWhiteSpace(token)) { return false; } int num = token.IndexOf('='); if (num < 1) { return false; } string text = token.Substring(0, num).Trim(); string value = token.Substring(num + 1).Trim(); if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(value)) { return IsValidTokenName(text); } return false; } private static bool IsValidTokenName(string tokenName) { if (TokenNameRegex.IsMatch(tokenName)) { return !tokenName.StartsWith("//"); } return false; } private static bool HasPotentialIssues(string line) { if (!line.Contains(" ") && !line.StartsWith(" ")) { return line.EndsWith(" "); } return true; } } public class ValidationResult { public bool IsValid { get; set; } public List<string> Errors { get; set; } = new List<string>(); public List<string> Warnings { get; set; } = new List<string>(); public string FilePath { get; set; } public static ValidationResult Error(string message) { return new ValidationResult { IsValid = false, Errors = new List<string> { message } }; } } public class LanguageHotReload : IDisposable { private static LanguageHotReload _instance; private FileSystemWatcher _languageWatcher; private FileSystemWatcher _jsonWatcher; private readonly Dictionary<string, DateTime> _lastModified = new Dictionary<string, DateTime>(); private readonly Queue<string> _pending = new Queue<string>(); private readonly object _pendingLock = new object(); private System.Timers.Timer _debounceTimer; private SynchronizationContext _unityContext; public static LanguageHotReload Instance => _instance ?? (_instance = new LanguageHotReload()); public bool IsEnabled { get; private set; } public string WatchDirectory { get; private set; } public event Action<string, string> OnTokenReloaded; public event Action<string> OnFileReloaded; public event Action<IEnumerable<string>> OnBatchReloaded; public event Action OnBeforeReload; public event Action OnAfterReload; public void Enable(string directory) { if (IsEnabled) { Disable(); } if (!Directory.Exists(directory)) { Debug.LogError((object)("[LanguageAPI] Diretorio nao encontrado: " + directory)); return; } _unityContext = SynchronizationContext.Current; WatchDirectory = directory; try { _languageWatcher = new FileSystemWatcher(directory) { Filter = "*.language", IncludeSubdirectories = true, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.LastWrite) }; _languageWatcher.Changed += OnChanged; _languageWatcher.Created += OnChanged; _languageWatcher.Deleted += OnChanged; _languageWatcher.EnableRaisingEvents = true; string path = Path.Combine(directory, "PELE", "Language"); if (Directory.Exists(path)) { _jsonWatcher = new FileSystemWatcher(path) { Filter = "*.json", IncludeSubdirectories = true, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.LastWrite) }; _jsonWatcher.Changed += OnChanged; _jsonWatcher.Created += OnChanged; _jsonWatcher.Deleted += OnChanged; _jsonWatcher.EnableRaisingEvents = true; } _debounceTimer = new System.Timers.Timer(500.0) { AutoReset = false }; _debounceTimer.Elapsed += delegate { ProcessPending(); }; IsEnabled = true; } catch (Exception ex) { Debug.LogError((object)("[LanguageAPI] Erro ao iniciar FileSystemWatcher: " + ex.Message)); } } public void Disable() { IsEnabled = false; if (_languageWatcher != null) { _languageWatcher.EnableRaisingEvents = false; _languageWatcher.Changed -= OnChanged; _languageWatcher.Created -= OnChanged; _languageWatcher.Deleted -= OnChanged; _languageWatcher.Dispose(); _languageWatcher = null; } if (_jsonWatcher != null) { _jsonWatcher.EnableRaisingEvents = false; _jsonWatcher.Changed -= OnChanged; _jsonWatcher.Created -= OnChanged; _jsonWatcher.Deleted -= OnChanged; _jsonWatcher.Dispose(); _jsonWatcher = null; } _debounceTimer?.Stop(); _debounceTimer?.Dispose(); _debounceTimer = null; lock (_pendingLock) { _pending.Clear(); _lastModified.Clear(); } } public void Dispose() { Disable(); } private void OnChanged(object sender, FileSystemEventArgs e) { lock (_pendingLock) { try { DateTime lastWriteTime = File.GetLastWriteTime(e.FullPath); if (_lastModified.TryGetValue(e.FullPath, out var value) && value == lastWriteTime) { return; } _lastModified[e.FullPath] = lastWriteTime; } catch { return; } if (!_pending.Contains(e.FullPath)) { _pending.Enqueue(e.FullPath); } _debounceTimer?.Stop(); _debounceTimer?.Start(); } } private void ProcessPending() { if (!IsEnabled) { return; } List<string> files; lock (_pendingLock) { files = new List<string>(_pending); _pending.Clear(); } if (files.Count == 0) { return; } SynchronizationContext unityContext = _unityContext; if (unityContext != null) { unityContext.Post(delegate { FireEvents(); }, null); } else { FireEvents(); } void FireEvents() { try { this.OnBeforeReload?.Invoke(); } catch (Exception ex) { Debug.LogError((object)("[LanguageAPI] OnBeforeReload: " + ex.Message)); } LanguageAPI.ClearAllTokens(); string[] languageFiles = LanguageFileHelper.GetLanguageFiles(WatchDirectory); foreach (string text in languageFiles) { try { foreach (KeyValuePair<string, Dictionary<string, string>> item in LanguageFileHelper.ParseTokensFromFile(text)) { foreach (KeyValuePair<string, string> item2 in item.Value) { LanguageAPI.AddOrUpdateToken(item2.Key, item2.Value, item.Key); try { this.OnTokenReloaded?.Invoke(item.Key, item2.Key); } catch (Exception ex2) { Debug.LogError((object)("[LanguageAPI] OnTokenReloaded: " + ex2.Message)); } } } try { this.OnFileReloaded?.Invoke(text); } catch (Exception ex3) { Debug.LogError((object)("[LanguageAPI] OnFileReloaded: " + ex3.Message)); } } catch (Exception ex4) { Debug.LogError((object)("[LanguageAPI] Erro ao recarregar " + text + ": " + ex4.Message)); } } try { this.OnAfterReload?.Invoke(); } catch (Exception ex5) { Debug.LogError((object)("[LanguageAPI] OnAfterReload: " + ex5.Message)); } try { this.OnBatchReloaded?.Invoke(files); } catch (Exception ex6) { Debug.LogError((object)("[LanguageAPI] OnBatchReloaded: " + ex6.Message)); } } } } internal static class LanguageNames { private static readonly Dictionary<string, string> Map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "en", "English" }, { "pt-BR", "Portuguese (Brazil)" }, { "es-ES", "Spanish (Spain)" }, { "de", "German" }, { "fr", "French" }, { "it", "Italian" }, { "ja", "Japanese" }, { "ko", "Korean" }, { "ru", "Russian" }, { "tr", "Turkish" }, { "uk", "Ukrainian" }, { "zh-CN", "Chinese (Simplified)" }, { "es-419", "Spanish (Latin America)" }, { "la", "Latin" }, { "eo", "Esperanto" } }; internal static string GetFriendlyName(string langCode) { if (!Map.TryGetValue(langCode, out string value)) { return langCode; } return value; } internal static List<string> GetAvailableLanguages(bool includeCustom = true) { try { if (typeof(Language).GetField("languagesByName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) is Dictionary<string, Language> dictionary) { HashSet<string> hashSet = new HashSet<string>(dictionary.Keys, StringComparer.OrdinalIgnoreCase); if (includeCustom) { string[] array = new string[3] { "uk", "la", "eo" }; foreach (string text in array) { if (!hashSet.Contains(text)) { Language.FindLanguageByName(text); hashSet.Add(text); } } } return hashSet.OrderBy<string, string>((string x) => x, StringComparer.OrdinalIgnoreCase).ToList(); } } catch { } return new List<string>(); } } internal static class LanguagePauseMenu { private class LanguageDialogCloseWatcher : MonoBehaviour { private float _delay = 0.4f; public SimpleDialogBox dialog; private bool _closing; private void Update() { if (!_closing) { _delay -= Time.unscaledDeltaTime; if (!(_delay > 0f) && (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown((KeyCode)331))) { _closing = true; CloseDialog(dialog); } } } } private class LanguageInputLegendController : MonoBehaviour { public MPEventSystem eventSystem; public InputBindingDisplayController applyGlyph; public InputBindingDisplayController cancelGlyph; private void Update() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 bool visible = (Object)(object)eventSystem != (Object)null && (int)eventSystem.currentInputSource == 1; SetGlyphVisible(applyGlyph, visible); SetGlyphVisible(cancelGlyph, visible); } private static void SetGlyphVisible(InputBindingDisplayController glyph, bool visible) { if (!((Object)(object)glyph == (Object)null)) { HGTextMeshProUGUI component = ((Component)glyph).GetComponent<HGTextMeshProUGUI>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = visible; } Transform val = ((Component)glyph).transform.parent.Find("KeyFallback"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(!visible); } } } } [CompilerGenerated] private static class <>O { public static hook_Awake <0>__OnPauseAwake; } private static bool _hooksActive; private static MethodInfo _setCurrentLanguageMethod; internal static void Init() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (!_hooksActive) { _hooksActive = true; _setCurrentLanguageMethod = typeof(Language).GetMethod("SetCurrentLanguage", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = <>O.<0>__OnPauseAwake; if (obj == null) { hook_Awake val = OnPauseAwake; <>O.<0>__OnPauseAwake = val; obj = (object)val; } PauseScreenController.Awake += (hook_Awake)obj; } } internal static void Cleanup() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (_hooksActive) { _hooksActive = false; object obj = <>O.<0>__OnPauseAwake; if (obj == null) { hook_Awake val = OnPauseAwake; <>O.<0>__OnPauseAwake = val; obj = (object)val; } PauseScreenController.Awake -= (hook_Awake)obj; } } private static void OnPauseAwake(orig_Awake orig, PauseScreenController self) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown orig.Invoke(self); try { RegisterUiTokens(); RectTransform mainPanel = self.mainPanel; if ((Object)(object)mainPanel == (Object)null || ((Transform)mainPanel).childCount == 0) { return; } Transform child = ((Transform)mainPanel).GetChild(0).GetChild(1); if (!((Object)(object)child == (Object)null)) { Transform obj = Object.Instantiate<Transform>(child, ((Transform)mainPanel).GetChild(0)); ((Object)obj).name = "LanguageSwitcherButton"; LanguageTextMeshController componentInChildren = ((Component)obj).GetComponentInChildren<LanguageTextMeshController>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.token = "PELE_LANGUAGE_BUTTON"; } HGTextMeshProUGUI componentInChildren2 = ((Component)obj).GetComponentInChildren<HGTextMeshProUGUI>(); if ((Object)(object)componentInChildren2 != (Object)null) { ((TMP_Text)componentInChildren2).text = Language.GetString("PELE_LANGUAGE_BUTTON"); } HGButton component = ((Component)obj).GetComponent<HGButton>(); ((Button)component).onClick = new ButtonClickedEvent(); ((UnityEvent)((Button)component).onClick).AddListener((UnityAction)delegate { ShowLanguageDialog(self); }); ((Component)obj).transform.SetAsLastSibling(); } } catch (Exception ex) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogError((object)("Falha no botao de idiomas: " + ex.Message)); } } } private static void RegisterUiTokens() { LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Language"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Idioma", "pt-BR"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Lingua", "la"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Lingvo", "eo"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Мова", "uk"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Sprache", "de"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Idioma", "es-ES"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Idioma", "es-419"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Langue", "fr"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Lingua", "it"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "言語", "ja"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "언어", "ko"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Язык", "ru"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "Dil", "tr"); LanguageAPI.AddOrUpdateToken("PELE_LANGUAGE_BUTTON", "语言", "zh-CN"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_TITLE", "Select Language"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_TITLE", "Selecionar idioma", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_TITLE", "Elige linguam", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_TITLE", "Elekti lingvon", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_TITLE", "Вибрати мову", "uk"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_DESC", "Choose a language below. The change applies immediately."); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_DESC", "Escolha um idioma abaixo. A troca e aplicada imediatamente.", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_DESC", "Elige linguam infra. Mutatio statim fit.", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_DESC", "Elektu lingvon sube. La sxangxo validas tuj.", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_DESC", "Оберіть мову нижче. Зміна застосовується одразу.", "uk"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL", "Cancel"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL", "Cancelar", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL", "Abrogare", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL", "Nuligi", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL", "Скасувати", "uk"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_APPLY_HINT", "Apply"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_APPLY_HINT", "Aplicar", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_APPLY_HINT", "Applicare", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_APPLY_HINT", "Apliki", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_APPLY_HINT", "Застосувати", "uk"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL_HINT", "Cancel"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL_HINT", "Cancelar", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL_HINT", "Abrogare", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL_HINT", "Nuligi", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_CANCEL_HINT", "Скасувати", "uk"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_MOUSE_APPLY_HINT", "Left click"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_MOUSE_APPLY_HINT", "Clique esquerdo", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_MOUSE_APPLY_HINT", "Clic sinistro", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_MOUSE_APPLY_HINT", "Maldekstra klako", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_MOUSE_APPLY_HINT", "Ліва кнопка", "uk"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_ESC_HINT", "Esc"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_ESC_HINT", "Esc", "pt-BR"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_ESC_HINT", "Esc", "la"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_ESC_HINT", "Esc", "eo"); LanguageAPI.AddOrUpdateToken("SWITCH_LANGUAGE_ESC_HINT", "Esc", "uk"); } private static void SetLanguage(string lang) { if (_setCurrentLanguageMethod == null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogError((object)"SetCurrentLanguage method not found via reflection"); } return; } try { if (LanguageConVar.instance != null) { ((BaseConVar)LanguageConVar.instance).SetString(lang); return; } _setCurrentLanguageMethod.Invoke(null, new object[1] { lang }); } catch (Exception ex) { string text = ex.InnerException?.Message ?? ex.Message; string text2 = ex.InnerException?.StackTrace ?? ex.StackTrace; ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogError((object)("Falha ao trocar lingua para '" + lang + "': " + text)); } ManualLogSource logger3 = LanguagePlugin.Logger; if (logger3 != null) { logger3.LogError((object)(" Stack: " + text2)); } } } private static void ShowLanguageDialog(PauseScreenController pause) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown RegisterUiTokens(); List<string> availableLanguages = LanguageNames.GetAvailableLanguages(); foreach (string item in availableLanguages) { LanguageAPI.AddOrUpdateToken("LANG_SEL_" + item, LanguageNames.GetFriendlyName(item)); } EventSystem current2 = EventSystem.current; SimpleDialogBox val = SimpleDialogBox.Create((MPEventSystem)(object)((current2 is MPEventSystem) ? current2 : null)); if ((Object)(object)val == (Object)null) { return; } val.headerToken = new TokenParamsPair { token = "SWITCH_LANGUAGE_TITLE" }; val.descriptionToken = new TokenParamsPair { token = "SWITCH_LANGUAGE_DESC" }; foreach (string item2 in availableLanguages) { string captured = item2; val.AddActionButton((UnityAction)delegate { SetLanguage(captured); }, "LANG_SEL_" + item2, true, Array.Empty<object>()); } (((Object)(object)val.rootObject != (Object)null) ? val.rootObject : ((Component)val).gameObject).AddComponent<LanguageDialogCloseWatcher>().dialog = val; MonoBehaviour component = ((Component)pause).GetComponent<MonoBehaviour>(); if ((Object)(object)component != (Object)null) { component.StartCoroutine(DelayedGridLayout(val)); } else { ApplyGridLayout(val); } } private static void CloseDialog(SimpleDialogBox dialog) { if (!((Object)(object)dialog == (Object)null)) { Object.Destroy((Object)(object)(((Object)(object)dialog.rootObject != (Object)null) ? dialog.rootObject : ((Component)dialog).gameObject)); } } private static IEnumerator DelayedGridLayout(SimpleDialogBox dialog) { yield return null; ApplyGridLayout(dialog); } private static void ApplyGridLayout(SimpleDialogBox dialog) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) try { RectTransform buttonContainer = dialog.buttonContainer; if ((Object)(object)buttonContainer == (Object)null) { ManualLogSource logger = LanguagePlugin.Logger; if (logger != null) { logger.LogWarning((object)"ApplyGridLayout: buttonContainer e null"); } return; } LayoutGroup[] components = ((Component)buttonContainer).GetComponents<LayoutGroup>(); foreach (LayoutGroup obj in components) { ((Behaviour)obj).enabled = false; Object.DestroyImmediate((Object)(object)obj, true); } GridLayoutGroup obj2 = ((Component)buttonContainer).gameObject.AddComponent<GridLayoutGroup>(); obj2.constraint = (Constraint)1; obj2.constraintCount = 3; obj2.cellSize = new Vector2(200f, 40f); obj2.spacing = new Vector2(8f, 6f); obj2.startAxis = (Axis)0; ContentSizeFitter obj3 = ((Component)buttonContainer).GetComponent<ContentSizeFitter>() ?? ((Component)buttonContainer).gameObject.AddComponent<ContentSizeFitter>(); obj3.verticalFit = (FitMode)2; obj3.horizontalFit = (FitMode)2; AddInputLegend(dialog); LayoutRebuilder.ForceRebuildLayoutImmediate(buttonContainer); WrapGridNavigation(buttonContainer); LanguagePlugin.LogVerbose($"ApplyGridLayout: grid aplicado com {((Transform)buttonContainer).childCount} botoes"); } catch (Exception ex) { ManualLogSource logger2 = LanguagePlugin.Logger; if (logger2 != null) { logger2.LogError((object)("Falha ao aplicar grid layout: " + ex.Message)); } } } private static void WrapGridNavigation(RectTransform container) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) List<MPButton> list = new List<MPButton>(); MPButton[] componentsInChildren = ((Component)container).GetComponentsInChildren<MPButton>(); foreach (MPButton val in componentsInChildren) { if (!((Object)(object)((Component)val).GetComponentInParent<LanguageInputLegendController>() != (Object)null)) { list.Add(val); } } if (list.Count == 0) { return; } int num = Mathf.Min(3, list.Count); int num2 = (list.Count + num - 1) / num; for (int j = 0; j < list.Count; j++) { Navigation val2 = default(Navigation); ((Navigation)(ref val2)).mode = (Mode)4; Navigation navigation = val2; int num3 = j % num; int num4 = j / num; int num5 = ((num3 > 0) ? (j - 1) : (j + num - 1)); int num6 = ((num3 < num - 1) ? (j + 1) : (j - num3)); int num7 = ((num4 > 0) ? (j - num) : ((num2 - 1) * num + Mathf.Min(num3, list.Count - (num2 - 1) * num - 1))); int num8 = ((num4 < num2 - 1) ? Mathf.Min(j + num, list.Count - 1) : num3); if (num5 >= 0 && num5 < list.Count) { ((Navigation)(ref navigation)).selectOnLeft = (Selectable)(object)list[num5]; } if (num6 >= 0 && num6 < list.Count) { ((Navigation)(ref navigation)).selectOnRight = (Selectable)(object)list[num6]; } if (num7 >= 0 && num7 < list.Count) { ((Navigation)(ref navigation)).selectOnUp = (Selectable)(object)list[num7]; } if (num8 >= 0 && num8 < list.Count) { ((Navigation)(ref navigation)).selectOnDown = (Selectable)(object)list[num8]; } ((Selectable)list[j]).navigation = navigation; } } private static void AddInputLegend(SimpleDialogBox dialog) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Expected O, but got Unknown RectTransform val = dialog?.buttonContainer; if (!((Object)(object)val == (Object)null) && !((Object)(object)((Transform)val).Find("PELELanguageInputLegend") != (Object)null)) { GameObject val2 = new GameObject("PELELanguageInputLegend", new Type[3] { typeof(RectTransform), typeof(HorizontalLayoutGroup), typeof(LanguageInputLegendController) }); RectTransform component = val2.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)val, false); component.sizeDelta = new Vector2(616f, 42f); LayoutElement obj = val2.AddComponent<LayoutElement>(); obj.minWidth = 616f; obj.preferredWidth = 616f; obj.minHeight = 42f; obj.preferredHeight = 42f; obj.flexibleWidth = 0f; obj.flexibleHeight = 0f; HorizontalLayoutGroup component2 = val2.GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component2).spacing = 58f; ((LayoutGroup)component2).padding = new RectOffset(8, 0, 8, 0); ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false; LanguageInputLegendController component3 = val2.GetComponent<LanguageInputLegendController>(); ref MPEventSystem eventSystem = ref component3.eventSystem; EventSystem current = EventSystem.current; eventSystem = (MPEventSystem)(object)((current is MPEventSystem) ? current : null); component3.applyGlyph = AddLegendItem(component, "UISubmit", "SWITCH_LANGUAGE_MOUSE_APPLY_HINT", "SWITCH_LANGUAGE_APPLY_HINT"); component3.cancelGlyph = AddLegendItem(component, "UICancel", "SWITCH_LANGUAGE_ESC_HINT", "SWITCH_LANGUAGE_CANCEL_HINT"); } } private static InputBindingDisplayController AddLegendItem(RectTransform parent, string actionName, string keyToken, string textToken) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(actionName + "Legend", new Type[2] { typeof(RectTransform), typeof(HorizontalLayoutGroup) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); component.sizeDelta = new Vector2(270f, 30f); HorizontalLayoutGroup component2 = val.GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component2).spacing = 7f; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false; LayoutElement obj = val.AddComponent<LayoutElement>(); obj.minWidth = 270f; obj.preferredWidth = 270f; obj.minHeight = 30f; obj.preferredHeight = 30f; GameObject val2 = new GameObject("Glyph", new Type[1] { typeof(RectTransform) }); val2.SetActive(false); RectTransform component3 = val2.GetComponent<RectTransform>(); ((Transform)component3).SetParent((Transform)(object)component, false); component3.sizeDelta = new Vector2(28f, 28f); HGTextMeshProUGUI obj2 = val2.AddComponent<HGTextMeshProUGUI>(); ((TMP_Text)obj2).fontSize = 18f; ((TMP_Text)obj2).alignment = (TextAlignmentOptions)514; InputBindingDisplayController val3 = val2.AddComponent<InputBindingDisplayController>(); val3.actionName = actionName; val3.useExplicitInputSource = true; val3.explicitInputSource = (InputSource)1; val2.SetActive(true); GameObject val4 = new GameObject("KeyFallback", new Type[1] { typeof(RectTransform) }); val4.SetActive(false); RectTransform component4 = val4.GetComponent<RectTransform>(); ((Transform)component4).SetParent((Transform)(object)component, false); component4.sizeDelta = new Vector2(158f, 28f); HGTextMeshProUGUI obj3 = val4.AddComponent<HGTextMeshProUGUI>(); ((TMP_Text)obj3).fontSize = 14f; ((TMP_Text)obj3).alignment = (TextAlignmentOptions)4097; ((TMP_Text)obj3).enableWordWrapping = false; val4.AddComponent<LanguageTextMeshController>().token = keyToken; val4.SetActive(true); GameObject val5 = new GameObject("Label", new Type[1] { typeof(RectTransform) }); val5.SetActive(false); RectTransform component5 = val5.GetComponent<RectTransform>(); ((Transform)component5).SetParent((Transform)(object