plugins/RiskofThunder-R2API_Language/R2API.Language/R2API.Language.dll

Decompiled 2 weeks ago
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