Decompiled source of WKTranslator v1.0.0

plugins/galfarious.WKTranslator.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("galfarious.WKTranslator")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c8dcc757480585d2b4721d830e1bf6aa9945195b")]
[assembly: AssemblyProduct("WKTranslator")]
[assembly: AssemblyTitle("galfarious.WKTranslator")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WKTranslator
{
	public static class DynamicTranslation
	{
		private static readonly Regex PlaceholderPattern = new Regex("\\{(\\d+)\\}", RegexOptions.Compiled);

		private static readonly List<(Regex Matcher, string Template)> _entries = new List<(Regex, string)>();

		public static int Count => _entries.Count;

		public static void Clear()
		{
			_entries.Clear();
		}

		public static bool TryRegister(string key, string value)
		{
			if (string.IsNullOrEmpty(key) || !PlaceholderPattern.IsMatch(key))
			{
				return false;
			}
			StringBuilder stringBuilder = new StringBuilder("^");
			int num = 0;
			foreach (Match item2 in PlaceholderPattern.Matches(key))
			{
				stringBuilder.Append(Regex.Escape(key.Substring(num, item2.Index - num)));
				int num2 = int.Parse(item2.Groups[1].Value);
				stringBuilder.Append($"(?<arg{num2}>.+?)");
				num = item2.Index + item2.Length;
			}
			stringBuilder.Append(Regex.Escape(key.Substring(num)));
			stringBuilder.Append('$');
			Regex item;
			try
			{
				item = new Regex(stringBuilder.ToString(), RegexOptions.Compiled | RegexOptions.Singleline);
			}
			catch (Exception ex)
			{
				LogManager.Error("Failed to build dynamic translation pattern for '" + key + "': " + ex.Message);
				return false;
			}
			_entries.Add((item, value));
			return true;
		}

		public static bool TryTranslate(string original, out string translated)
		{
			translated = null;
			if (string.IsNullOrEmpty(original))
			{
				return false;
			}
			foreach (var entry in _entries)
			{
				Regex item = entry.Matcher;
				string item2 = entry.Template;
				Match match = item.Match(original);
				if (!match.Success)
				{
					continue;
				}
				translated = PlaceholderPattern.Replace(item2, delegate(Match m)
				{
					Group obj = match.Groups["arg" + m.Groups[1].Value];
					return obj.Success ? obj.Value : m.Value;
				});
				return true;
			}
			return false;
		}
	}
	public static class FontLoader
	{
		private static readonly Dictionary<string, TMP_FontAsset> _tmpCache = new Dictionary<string, TMP_FontAsset>(StringComparer.OrdinalIgnoreCase);

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

		public static TMP_FontAsset CustomFont;

		public static void LoadCustomFont(string folderPath)
		{
			_tmpCache.Clear();
			_legacyCache.Clear();
			CustomFont = null;
			if (!TryLoadFromBundle(folderPath))
			{
				LoadFromTrueTypeFile(folderPath);
			}
		}

		private static bool TryLoadFromBundle(string folderPath)
		{
			string text = Path.Combine(folderPath, "customfonts");
			if (!File.Exists(text))
			{
				return false;
			}
			AssetBundle val = AssetBundle.LoadFromFile(text);
			if ((Object)(object)val == (Object)null)
			{
				LogManager.Error("Failed to load font bundle at '" + text + "'.");
				return false;
			}
			TMP_FontAsset[] array = val.LoadAllAssets<TMP_FontAsset>();
			foreach (TMP_FontAsset val2 in array)
			{
				string text2 = ((Object)val2).name.Trim();
				_tmpCache[text2] = val2;
				LogManager.Info("Loaded TMP font from bundle: " + text2);
			}
			Font[] array2 = val.LoadAllAssets<Font>();
			foreach (Font val3 in array2)
			{
				string text3 = ((Object)val3).name.Trim();
				_legacyCache[text3] = val3;
				LogManager.Info("Loaded Legacy font from bundle: " + text3);
			}
			val.Unload(false);
			if (_tmpCache.Count == 0 && _legacyCache.Count == 0)
			{
				LogManager.Warn("Font bundle at '" + text + "' contained no usable TMP_FontAsset or Font assets.");
				return false;
			}
			if (!_tmpCache.TryGetValue("default", out CustomFont) && _tmpCache.Count > 0)
			{
				using Dictionary<string, TMP_FontAsset>.ValueCollection.Enumerator enumerator = _tmpCache.Values.GetEnumerator();
				if (enumerator.MoveNext())
				{
					TMP_FontAsset current = enumerator.Current;
					CustomFont = current;
				}
			}
			RegisterFallback(CustomFont);
			return true;
		}

		private static void LoadFromTrueTypeFile(string folderPath)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			string[] files = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly);
			string text = null;
			string[] array = files;
			foreach (string text2 in array)
			{
				if (text2.EndsWith(".ttf") || text2.EndsWith(".otf"))
				{
					text = text2;
					break;
				}
			}
			if (!string.IsNullOrEmpty(text))
			{
				Font val = new Font(text);
				CustomFont = TMP_FontAsset.CreateFontAsset(val, 90, 9, (GlyphRenderMode)4165, 1024, 1024, (AtlasPopulationMode)1, true);
				((Object)CustomFont).name = "WK_CustomFont";
				_tmpCache["default"] = CustomFont;
				RegisterFallback(CustomFont);
				LogManager.Info("Loaded custom font: " + Path.GetFileName(text));
			}
		}

		private static void RegisterFallback(TMP_FontAsset font)
		{
			if ((Object)(object)font == (Object)null)
			{
				return;
			}
			TMP_FontAsset defaultFontAsset = TMP_Settings.defaultFontAsset;
			if (!((Object)(object)defaultFontAsset == (Object)null) && !((Object)(object)defaultFontAsset == (Object)(object)font))
			{
				TMP_FontAsset val = defaultFontAsset;
				if (val.fallbackFontAssetTable == null)
				{
					List<TMP_FontAsset> list = (val.fallbackFontAssetTable = new List<TMP_FontAsset>());
				}
				if (!defaultFontAsset.fallbackFontAssetTable.Contains(font))
				{
					defaultFontAsset.fallbackFontAssetTable.Add(font);
				}
			}
		}

		public static void TryReplace(TMP_Text text)
		{
			if ((Object)(object)text == (Object)null)
			{
				return;
			}
			string key = (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name.Trim() : "");
			if (_tmpCache.TryGetValue(key, out var value) || _tmpCache.TryGetValue("default", out value))
			{
				if ((Object)(object)text.font != (Object)(object)value)
				{
					text.font = value;
				}
			}
			else if ((Object)(object)CustomFont != (Object)null && (Object)(object)text.font != (Object)(object)CustomFont)
			{
				text.font = CustomFont;
			}
		}

		public static void TryReplace(Text text)
		{
			if (!((Object)(object)text == (Object)null) && _legacyCache.Count != 0)
			{
				string key = (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name.Trim() : "");
				if ((_legacyCache.TryGetValue(key, out var value) || _legacyCache.TryGetValue("default", out value)) && (Object)(object)text.font != (Object)(object)value)
				{
					text.font = value;
				}
			}
		}
	}
	public static class LogManager
	{
		private static ManualLogSource _logSource;

		public static void Initialize(ManualLogSource logger)
		{
			_logSource = logger;
		}

		public static void Info(object message)
		{
			_logSource.LogInfo(message);
		}

		public static void Warn(object message)
		{
			_logSource.LogWarning(message);
		}

		public static void Error(object message)
		{
			_logSource.LogError(message);
		}

		public static void Debug(object message)
		{
			_logSource.LogDebug(message);
		}
	}
	[BepInPlugin("galfarious.WKTranslator", "WKTranslator", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(Resources))]
		public static class ResourcesPatches
		{
			[HarmonyPatch("Load", new Type[]
			{
				typeof(string),
				typeof(Type)
			})]
			public static bool LoadPatch(string path, Type systemTypeInstance, ref Object __result)
			{
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Expected O, but got Unknown
				if (systemTypeInstance == typeof(TextAsset) && path.Contains("en") && CustomSubtitleAsset != null)
				{
					__result = (Object)(object)CustomSubtitleAsset;
					return false;
				}
				if (systemTypeInstance == typeof(Material))
				{
					LogManager.Warn($"this is spriteRegistry Keys: {TextureRegistry.Keys}");
					Material val = (Material)__result;
					LogManager.Warn("This is the material that was loaded: " + ((Object)val).name);
					if (TextureRegistry.TryGetValue(((Object)val.mainTexture).name, out var value))
					{
						LogManager.Error("Trying to replace the texture with new material idk...");
						val.mainTexture = (Texture)(object)value;
						__result = (Object)(object)val;
						return false;
					}
				}
				return true;
			}
		}

		public static Plugin Instance;

		private ConfigEntry<string> _langKey;

		public static readonly Dictionary<string, string> Translations = new Dictionary<string, string>();

		public static readonly Dictionary<string, Texture2D> TextureRegistry = new Dictionary<string, Texture2D>();

		public static readonly Dictionary<string, AudioClip> AudioRegistry = new Dictionary<string, AudioClip>();

		public static TMP_FontAsset CustomFontAsset;

		public static TextAsset CustomSubtitleAsset;

		private List<TranslationFolder> _translationFolders = new List<TranslationFolder>();

		private List<string> _allowedImageTypes = new List<string>(1) { "png" };

		private List<string> _allowedAudioTypes = new List<string>(3) { "wav", "ogg", "mp3" };

		private string PluginDir => Path.Combine(Paths.PluginPath, "WKTranslator");

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null || (Object)(object)Instance != (Object)(object)this)
			{
				Instance = this;
			}
			LogManager.Initialize(((BaseUnityPlugin)this).Logger);
			_langKey = ((BaseUnityPlugin)this).Config.Bind<string>("General", "LanguageKey", "en", "Select the language corresponding to the translation JSON\ne.g.: cz");
			_langKey.SettingChanged += delegate
			{
				ReloadLanguage();
			};
			_translationFolders = TranslationScanner.Scan(Paths.PluginPath);
			ReloadLanguage();
			ApplyHarmonyPatches();
			LogManager.Info("Plugin galfarious.WKTranslator v1.0.0 is loaded!");
			CreateWKTranslationManagerObject();
			LogManager.Info("Added command for dumping text!");
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			CreateWKTranslationManagerObject();
		}

		public void ReloadLanguage()
		{
			ClearAll();
			_translationFolders = TranslationScanner.Scan(Paths.PluginPath);
			TranslationFolder translationFolder = _translationFolders.FirstOrDefault((TranslationFolder t) => t.Config.LanguageKey == _langKey.Value);
			LogManager.Info(translationFolder);
			if (translationFolder == null)
			{
				LogManager.Error("Translation '" + _langKey.Value + "' not found or invalid.");
				return;
			}
			string text = Path.Combine(translationFolder.FolderPath, translationFolder.Config.ConfigFileName);
			FontLoader.LoadCustomFont(translationFolder.FolderPath);
			CustomFontAsset = FontLoader.CustomFont;
			if (CustomFontAsset == null)
			{
				LogManager.Info("No Custom Font Loaded!");
			}
			else
			{
				LogManager.Info("Loaded Custom font!");
			}
			LoadTranslations(translationFolder.FolderPath, translationFolder.Config);
			LoadTextures(Path.Combine(translationFolder.FolderPath, "Textures"));
			LoadAudio(Path.Combine(translationFolder.FolderPath, "Audio"));
			LogManager.Info("Loaded translation '" + translationFolder.Config.LanguageName + "' by " + string.Join(", ", translationFolder.Config.Authors) + ".");
		}

		private static void CreateWKTranslationManagerObject()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			GameObject val = new GameObject("WKTranslationManager");
			val.AddComponent<WKTranslationManager>();
			Object.DontDestroyOnLoad((Object)(object)val);
		}

		private void ClearAll()
		{
			Translations.Clear();
			DynamicTranslation.Clear();
			SampleTranslation.Clear();
			TextureRegistry.Clear();
			AudioRegistry.Clear();
		}

		public static bool TryGetTranslation(string original, out string translated)
		{
			if (Translations.TryGetValue(original, out translated))
			{
				return true;
			}
			if (DynamicTranslation.TryTranslate(original, out translated))
			{
				return true;
			}
			return SampleTranslation.TryTranslate(original, out translated);
		}

		private void LoadTranslations(string filepath, TranslationConfig config)
		{
			LogManager.Info("Loading translations from '" + filepath + "'.");
			string text = Path.Combine(filepath, config.LanguageKey + ".json");
			Translations.Clear();
			DynamicTranslation.Clear();
			SampleTranslation.Clear();
			if (!File.Exists(text))
			{
				LogManager.Error("Translation '" + text + "' not found or invalid.");
				return;
			}
			try
			{
				string text2 = File.ReadAllText(text);
				JObject val = JObject.Parse(text2);
				foreach (JProperty item in val.Properties())
				{
					ProcessTranslationToken(item.Name, item.Value);
				}
				SampleTranslation.FinalizeRegistration();
				LogManager.Info($"Loaded {Translations.Count} exact, {DynamicTranslation.Count} template, " + $"{SampleTranslation.Count} sample translations from {Path.GetFileName(text)}");
			}
			catch (Exception ex)
			{
				LogManager.Error("Failed to load translations from '" + text + "': " + ex.Message);
			}
		}

		private void ProcessTranslationToken(string keyName, JToken token)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (SampleTranslation.TryRegisterToken(keyName, token))
			{
				return;
			}
			if ((int)token.Type == 1)
			{
				foreach (JProperty item in ((JObject)token).Properties())
				{
					ProcessTranslationToken(item.Name, item.Value);
				}
				return;
			}
			if ((int)token.Type == 8)
			{
				string text = ((object)token).ToString();
				if (!string.IsNullOrEmpty(text.Trim()))
				{
					Translations.TryAdd(keyName, text);
					DynamicTranslation.TryRegister(keyName, text);
				}
			}
		}

		private void LoadTextures(string dir)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			TextureRegistry.Clear();
			if (!Directory.Exists(dir))
			{
				return;
			}
			string[] files = Directory.GetFiles(dir);
			foreach (string path in files)
			{
				List<string> allowedImageTypes = _allowedImageTypes;
				string extension = Path.GetExtension(path);
				if (allowedImageTypes.Contains(extension.Substring(1, extension.Length - 1)))
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
					byte[] array = File.ReadAllBytes(path);
					Texture2D val = new Texture2D(2, 2);
					ImageConversion.LoadImage(val, array);
					TextureRegistry.Add(fileNameWithoutExtension, val);
				}
			}
		}

		private async void LoadAudio(string dir)
		{
			try
			{
				AudioRegistry.Clear();
				if (!Directory.Exists(dir))
				{
					return;
				}
				string[] files = Directory.GetFiles(dir);
				foreach (string file in files)
				{
					string extension = Path.GetExtension(file);
					string ext = extension.Substring(1, extension.Length - 1);
					if (_allowedAudioTypes.Contains(ext))
					{
						string key = Path.GetFileNameWithoutExtension(file);
						string key2 = key;
						AudioClip value = await LoadSound(file, ext);
						AudioRegistry.TryAdd(key2, value);
					}
				}
			}
			catch
			{
			}
		}

		private void ApplyHarmonyPatches()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			Harmony val = new Harmony("galfarious.WKTranslator.patches");
			val.PatchAll();
		}

		private static async Task<AudioClip> LoadSound(string filename, string type)
		{
			AudioClip audioClip = null;
			string text = type.ToLower();
			if (1 == 0)
			{
			}
			AudioType val = (AudioType)(text switch
			{
				"wav" => 20, 
				"ogg" => 14, 
				"mp3" => 13, 
				_ => 0, 
			});
			if (1 == 0)
			{
			}
			AudioType audioType = val;
			if ((int)audioType == 0)
			{
				return null;
			}
			UnityWebRequest uwr = new UnityWebRequest(filename, "GET")
			{
				downloadHandler = (DownloadHandler)new DownloadHandlerAudioClip(filename, audioType)
			};
			DownloadHandlerAudioClip dh = (DownloadHandlerAudioClip)uwr.downloadHandler;
			dh.streamAudio = false;
			dh.compressed = true;
			uwr.SendWebRequest();
			try
			{
				while (!uwr.isDone)
				{
					await Task.Delay(5);
				}
				if ((int)uwr.result == 2 || (int)uwr.result == 3)
				{
					LogManager.Error(uwr.error);
				}
				else
				{
					audioClip = dh.audioClip;
				}
			}
			catch (Exception ex)
			{
				LogManager.Error(ex.Message + "\n" + ex.StackTrace);
			}
			return audioClip;
		}
	}
	public static class SampleTranslation
	{
		private class SampleEntry
		{
			public string OriginalKey;

			public Regex CompiledRegex;

			public string TranslationTemplate;

			public List<string> Placeholders;

			public bool IsAtomic;

			public bool IsLiteral;

			public string Anchor;
		}

		private class GroupEntry
		{
			public List<string> Headers = new List<string>();

			public List<SampleEntry> Rules = new List<SampleEntry>();
		}

		private class ConditionalEntry
		{
			public int RequiredGroupCount;

			public List<SampleEntry> MandatoryRules = new List<SampleEntry>();

			public Dictionary<int, List<SampleEntry>> IndexedRules = new Dictionary<int, List<SampleEntry>>();
		}

		private static readonly List<SampleEntry> _samples = new List<SampleEntry>();

		private static readonly List<GroupEntry> _groups = new List<GroupEntry>();

		private static readonly List<ConditionalEntry> _conditionals = new List<ConditionalEntry>();

		public static int Count => _samples.Count + _groups.Count + _conditionals.Count;

		public static void Clear()
		{
			_samples.Clear();
			_groups.Clear();
			_conditionals.Clear();
		}

		public static bool TryRegisterToken(string keyName, JToken token)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (keyName.StartsWith("sampleR", StringComparison.OrdinalIgnoreCase) && (int)token.Type == 1)
			{
				RegisterConditional(keyName, (JObject)token);
				return true;
			}
			if (keyName.StartsWith("sampleG:", StringComparison.OrdinalIgnoreCase) && (int)token.Type == 1)
			{
				RegisterGroup((JObject)token);
				return true;
			}
			if (keyName.StartsWith("sample:", StringComparison.OrdinalIgnoreCase) && (int)token.Type == 1)
			{
				foreach (JProperty item in ((JObject)token).Properties())
				{
					_samples.Add(CreateEntry(item.Name, ((object)item.Value).ToString()));
				}
				return true;
			}
			if ((int)token.Type == 8)
			{
				string text = ((object)token).ToString();
				if (text.StartsWith("sample:", StringComparison.OrdinalIgnoreCase))
				{
					_samples.Add(CreateEntry(keyName, text.Substring(7).Trim()));
					return true;
				}
			}
			return false;
		}

		public static void FinalizeRegistration()
		{
			_samples.Sort((SampleEntry a, SampleEntry b) => (a.IsAtomic != b.IsAtomic) ? a.IsAtomic.CompareTo(b.IsAtomic) : b.TranslationTemplate.Length.CompareTo(a.TranslationTemplate.Length));
		}

		public static bool TryTranslate(string original, out string translated)
		{
			translated = null;
			if (string.IsNullOrEmpty(original))
			{
				return false;
			}
			string text = original;
			bool anyTranslated = false;
			foreach (ConditionalEntry conditional in _conditionals)
			{
				bool flag = true;
				foreach (SampleEntry mandatoryRule in conditional.MandatoryRules)
				{
					if (!(mandatoryRule.IsLiteral ? (text.IndexOf(mandatoryRule.OriginalKey, StringComparison.OrdinalIgnoreCase) != -1) : mandatoryRule.CompiledRegex.IsMatch(text)))
					{
						flag = false;
						break;
					}
				}
				if (!flag)
				{
					continue;
				}
				int num = 0;
				List<SampleEntry> list = new List<SampleEntry>();
				foreach (KeyValuePair<int, List<SampleEntry>> indexedRule in conditional.IndexedRules)
				{
					bool flag2 = false;
					foreach (SampleEntry item in indexedRule.Value)
					{
						if (item.IsLiteral ? (text.IndexOf(item.OriginalKey, StringComparison.OrdinalIgnoreCase) != -1) : item.CompiledRegex.IsMatch(text))
						{
							flag2 = true;
							list.Add(item);
						}
					}
					if (flag2)
					{
						num++;
					}
				}
				if (num < conditional.RequiredGroupCount)
				{
					continue;
				}
				foreach (SampleEntry mandatoryRule2 in conditional.MandatoryRules)
				{
					text = ApplyReplacement(text, mandatoryRule2, ref anyTranslated);
				}
				list.Sort((SampleEntry a, SampleEntry b) => b.OriginalKey.Length.CompareTo(a.OriginalKey.Length));
				foreach (SampleEntry item2 in list)
				{
					text = ApplyReplacement(text, item2, ref anyTranslated);
				}
			}
			foreach (GroupEntry group in _groups)
			{
				if (group.Headers.Count == 0)
				{
					continue;
				}
				bool flag3 = false;
				foreach (string header in group.Headers)
				{
					if (text.IndexOf(header, StringComparison.OrdinalIgnoreCase) == -1)
					{
						continue;
					}
					flag3 = true;
					break;
				}
				if (!flag3)
				{
					continue;
				}
				foreach (SampleEntry rule in group.Rules)
				{
					text = ApplyReplacement(text, rule, ref anyTranslated);
				}
			}
			foreach (SampleEntry sample in _samples)
			{
				if (string.IsNullOrEmpty(sample.Anchor) || text.IndexOf(sample.Anchor, StringComparison.OrdinalIgnoreCase) != -1)
				{
					text = ApplyReplacement(text, sample, ref anyTranslated);
				}
			}
			if (!anyTranslated)
			{
				return false;
			}
			translated = text;
			return true;
		}

		private static void RegisterConditional(string keyName, JObject obj)
		{
			ConditionalEntry conditionalEntry = new ConditionalEntry();
			Match match = Regex.Match(keyName, "\\d+");
			conditionalEntry.RequiredGroupCount = (match.Success ? int.Parse(match.Value) : 2);
			foreach (JProperty item2 in obj.Properties())
			{
				string name = item2.Name;
				string val = ((object)item2.Value).ToString();
				if (name.StartsWith("request:", StringComparison.OrdinalIgnoreCase))
				{
					string key = name.Substring(8);
					conditionalEntry.MandatoryRules.Add(CreateEntry(key, val));
					continue;
				}
				Match match2 = Regex.Match(name, "^request(\\d+):(.*)", RegexOptions.IgnoreCase);
				if (match2.Success)
				{
					int key2 = int.Parse(match2.Groups[1].Value);
					string value = match2.Groups[2].Value;
					SampleEntry item = CreateEntry(value, val);
					if (!conditionalEntry.IndexedRules.TryGetValue(key2, out var value2))
					{
						value2 = new List<SampleEntry>();
						conditionalEntry.IndexedRules[key2] = value2;
					}
					value2.Add(item);
				}
			}
			_conditionals.Add(conditionalEntry);
		}

		private static void RegisterGroup(JObject obj)
		{
			GroupEntry groupEntry = new GroupEntry();
			foreach (JProperty item2 in obj.Properties())
			{
				if (item2.Name.StartsWith("header:", StringComparison.OrdinalIgnoreCase))
				{
					string text = item2.Name.Substring(7);
					string item = (text.StartsWith("tag:", StringComparison.OrdinalIgnoreCase) ? text.Substring(4) : text);
					groupEntry.Headers.Add(item);
					string text2 = ((object)item2.Value).ToString();
					if (!string.IsNullOrEmpty(text2))
					{
						groupEntry.Rules.Add(CreateEntry(text, text2));
					}
				}
				else
				{
					groupEntry.Rules.Add(CreateEntry(item2.Name, ((object)item2.Value).ToString()));
				}
			}
			_groups.Add(groupEntry);
		}

		private static SampleEntry CreateEntry(string key, string val)
		{
			string text = key;
			bool flag = false;
			if (text.StartsWith("tag:", StringComparison.OrdinalIgnoreCase))
			{
				flag = true;
				text = text.Substring(4);
			}
			List<string> list = new List<string>();
			foreach (Match item in Regex.Matches(text, "\\{(\\d+)\\}"))
			{
				list.Add(item.Groups[1].Value);
			}
			bool flag2 = list.Count == 0;
			string input = Regex.Escape(text);
			input = Regex.Replace(input, "\\\\\\{\\d+\\}", "(.+?)");
			if (flag2 && !flag)
			{
				string text2 = (Regex.IsMatch(text, "^\\w") ? "(?<=^|\\W|\\\\n|\\\\r)" : "");
				string text3 = (Regex.IsMatch(text, "\\w$") ? "(?=\\W|$)" : "");
				input = text2 + input + text3;
			}
			return new SampleEntry
			{
				OriginalKey = text,
				CompiledRegex = new Regex(input, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant),
				TranslationTemplate = val,
				Placeholders = list,
				IsAtomic = flag2,
				IsLiteral = flag,
				Anchor = GetLongestStaticChunk(text)
			};
		}

		private static string ApplyReplacement(string input, SampleEntry sample, ref bool anyTranslated)
		{
			if (sample.IsLiteral)
			{
				if (input.IndexOf(sample.OriginalKey, StringComparison.OrdinalIgnoreCase) == -1)
				{
					return input;
				}
				string text = Regex.Replace(input, Regex.Escape(sample.OriginalKey), sample.TranslationTemplate.Replace("$", "$$"), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (text == input)
				{
					return input;
				}
				anyTranslated = true;
				return text;
			}
			if (sample.IsAtomic)
			{
				if (input.IndexOf(sample.OriginalKey, StringComparison.OrdinalIgnoreCase) == -1)
				{
					return input;
				}
				string text2 = sample.CompiledRegex.Replace(input, delegate(Match m)
				{
					int num = m.Index - 1;
					if (num >= 0 && num < input.Length)
					{
						int num2 = input.LastIndexOf('<', num);
						int num3 = input.LastIndexOf('>', num);
						if (num2 > num3)
						{
							return m.Value;
						}
						int num4 = input.LastIndexOf('{', num);
						int num5 = input.LastIndexOf('}', num);
						if (num4 > num5)
						{
							return m.Value;
						}
					}
					return sample.TranslationTemplate;
				});
				if (text2 == input)
				{
					return input;
				}
				anyTranslated = true;
				return text2;
			}
			if (!sample.CompiledRegex.IsMatch(input))
			{
				return input;
			}
			string result = sample.CompiledRegex.Replace(input, delegate(Match match)
			{
				string text3 = sample.TranslationTemplate;
				for (int i = 1; i < match.Groups.Count; i++)
				{
					string text4 = sample.Placeholders[i - 1];
					string newValue = match.Groups[i].Value.Trim();
					text3 = text3.Replace("{" + text4 + "}", newValue);
				}
				return text3;
			});
			anyTranslated = true;
			return result;
		}

		private static string GetLongestStaticChunk(string input)
		{
			if (string.IsNullOrEmpty(input))
			{
				return string.Empty;
			}
			string input2 = Regex.Replace(input, "<[^>]+>", " ");
			input2 = Regex.Replace(input2, "\\{\\#?\\d+\\}", " ");
			string[] array = input2.Split(new char[6] { ' ', '\t', '.', ',', '!', '?' }, StringSplitOptions.RemoveEmptyEntries);
			string text = string.Empty;
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (text2.Length > text.Length)
				{
					text = text2;
				}
			}
			return (text.Length > 3) ? text : string.Empty;
		}
	}
	public static class TextScanner
	{
		private class ScannerBehaviour : MonoBehaviour
		{
			private float _timer;

			private const float ScanInterval = 3f;

			private void Update()
			{
				_timer += Time.unscaledDeltaTime;
				if (_timer >= 3f)
				{
					_timer = 0f;
					ScanUI();
				}
			}

			private void ScanUI()
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				Text[] array = Resources.FindObjectsOfTypeAll<Text>();
				Scene scene;
				foreach (Text val in array)
				{
					scene = ((Component)val).gameObject.scene;
					if (!((Scene)(ref scene)).isLoaded)
					{
						scene = ((Component)val).gameObject.scene;
						if (!(((Scene)(ref scene)).name == "DontDestroyOnLoad"))
						{
							continue;
						}
					}
					AddFoundString(val.text);
				}
				TMP_Text[] array2 = Resources.FindObjectsOfTypeAll<TMP_Text>();
				foreach (TMP_Text val2 in array2)
				{
					scene = ((Component)val2).gameObject.scene;
					if (!((Scene)(ref scene)).isLoaded)
					{
						scene = ((Component)val2).gameObject.scene;
						if (!(((Scene)(ref scene)).name == "DontDestroyOnLoad"))
						{
							continue;
						}
					}
					AddFoundString(val2.text);
				}
			}
		}

		private static Dictionary<string, HashSet<string>> _categorizedStrings = new Dictionary<string, HashSet<string>>();

		private static bool _isActive;

		private static GameObject _scannerGo;

		private static readonly Regex GarbageFilter = new Regex("^<[^>]+>[\\d\\.,\\s]+<\\/[^>]+>$|^Time Since Last Hit:|^<color=[^>]+>null</color>|^[\\d\\W]+$|<sprite=", RegexOptions.IgnoreCase);

		public static void RunScanner()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (!_isActive)
			{
				_isActive = true;
				_categorizedStrings.Clear();
				_scannerGo = new GameObject("WK_TextScanner");
				_scannerGo.AddComponent<ScannerBehaviour>();
				Object.DontDestroyOnLoad((Object)(object)_scannerGo);
			}
		}

		public static void StopScanner()
		{
			if (_isActive)
			{
				_isActive = false;
				if ((Object)(object)_scannerGo != (Object)null)
				{
					Object.Destroy((Object)(object)_scannerGo);
				}
				SaveToFile();
			}
		}

		private static void AddFoundString(string text)
		{
			//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)
			if (IsValidText(text))
			{
				Scene activeScene = SceneManager.GetActiveScene();
				string text2 = ((Scene)(ref activeScene)).name;
				if (string.IsNullOrEmpty(text2))
				{
					text2 = "Unknown";
				}
				if (!_categorizedStrings.ContainsKey(text2))
				{
					_categorizedStrings[text2] = new HashSet<string>();
				}
				if (!_categorizedStrings[text2].Contains(text))
				{
					_categorizedStrings[text2].Add(text);
					LogManager.Debug("Found text: " + text);
				}
			}
		}

		private static bool IsValidText(string s)
		{
			if (string.IsNullOrWhiteSpace(s))
			{
				return false;
			}
			if (s.Contains("UnityEngine") || s.Contains("System."))
			{
				return false;
			}
			if (GarbageFilter.IsMatch(s))
			{
				return false;
			}
			if (s.Length == 1 && s != "I" && s != "A" && s != "a")
			{
				return false;
			}
			return true;
		}

		private static void SaveToFile()
		{
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (HashSet<string> value in _categorizedStrings.Values)
			{
				foreach (string item in value)
				{
					if (!dictionary.ContainsKey(item))
					{
						dictionary[item] = 0;
					}
					dictionary[item]++;
				}
			}
			Dictionary<string, HashSet<string>> dictionary2 = new Dictionary<string, HashSet<string>>();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (KeyValuePair<string, HashSet<string>> categorizedString in _categorizedStrings)
			{
				string key = categorizedString.Key;
				dictionary2[key] = new HashSet<string>();
				foreach (string item2 in categorizedString.Value)
				{
					if (dictionary[item2] > 1)
					{
						hashSet.Add(item2);
					}
					else
					{
						dictionary2[key].Add(item2);
					}
				}
			}
			if (hashSet.Count > 0)
			{
				dictionary2["_Common"] = hashSet;
			}
			JObject val = new JObject();
			foreach (string item3 in dictionary2.Keys.OrderBy((string k) => k))
			{
				HashSet<string> hashSet2 = dictionary2[item3];
				if (hashSet2.Count == 0)
				{
					continue;
				}
				JObject val2 = new JObject();
				foreach (string item4 in hashSet2.OrderBy((string x) => x))
				{
					val2[item4] = JToken.op_Implicit(item4);
				}
				val[item3] = (JToken)(object)val2;
			}
			string text = Path.Combine(Paths.PluginPath, "WKTranslator");
			Directory.CreateDirectory(text);
			string text2 = Path.Combine(text, "scan_output_categorized.json");
			File.WriteAllText(text2, ((JToken)val).ToString((Formatting)1, Array.Empty<JsonConverter>()));
			Debug.Log((object)("[WKTranslator] Scan saved to " + text2));
		}
	}
	public class TranslationConfig
	{
		[JsonProperty("languageKey")]
		public string LanguageKey { get; set; }

		[JsonProperty("languageName")]
		public string LanguageName { get; set; }

		[JsonProperty("authors")]
		public List<string> Authors { get; set; }

		[JsonIgnore]
		public string ConfigFileName { get; set; }

		[JsonIgnore]
		[JsonProperty("fontFile")]
		public string FontFileName { get; set; }
	}
	public class TranslationFolder
	{
		public string FolderPath { get; }

		public TranslationConfig Config { get; }

		public TranslationFolder(string path, TranslationConfig config)
		{
			FolderPath = path;
			Config = config;
		}
	}
	public static class TranslationScanner
	{
		public static List<TranslationFolder> Scan(string rootPluginPath)
		{
			List<TranslationFolder> list = new List<TranslationFolder>();
			string[] directories = Directory.GetDirectories(rootPluginPath);
			foreach (string path in directories)
			{
				IEnumerable<string> enumerable = from x in Directory.GetFiles(path, "*.json")
					where !string.IsNullOrEmpty(x)
					select x;
				foreach (string item in enumerable)
				{
					LogManager.Debug(item);
					try
					{
						TranslationConfig translationConfig = JsonConvert.DeserializeObject<TranslationConfig>(File.ReadAllText(item));
						translationConfig.ConfigFileName = Path.GetFileName(item);
						list.Add(new TranslationFolder(path, translationConfig));
					}
					catch (Exception arg)
					{
						LogManager.Error($"Failed to load {item}\n{arg}");
					}
				}
			}
			return list;
		}
	}
	public class WKTranslationManager : MonoBehaviour
	{
		[HarmonyPatch(typeof(TMP_Text))]
		public static class TMPTextPatches
		{
			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPrefix]
			public static bool PrefixText(TMP_Text __instance, ref string __0)
			{
				if (string.IsNullOrEmpty(__0))
				{
					return true;
				}
				if (Plugin.TryGetTranslation(__0, out var translated))
				{
					__0 = translated;
					FontLoader.TryReplace(__instance);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Text))]
		public static class LegacyTextPatches
		{
			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPrefix]
			public static bool PrefixText(Text __instance, ref string __0)
			{
				if (string.IsNullOrEmpty(__0))
				{
					return true;
				}
				if (Plugin.TryGetTranslation(__0, out var translated))
				{
					__0 = translated;
					FontLoader.TryReplace(__instance);
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Sprite))]
		private static class SpritePatches
		{
			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPostfix]
			private static void PostFix_texture(ref Texture2D __result)
			{
				if (__result != null && (Plugin.TextureRegistry.ContainsKey("_ALL") || Plugin.TextureRegistry.TryGetValue(((Object)__result).name, out var value)))
				{
					value = Plugin.TextureRegistry.First((KeyValuePair<string, Texture2D> p) => p.Key == "_ALL").Value;
					__result = value;
				}
			}
		}

		[HarmonyPatch(typeof(SpriteRenderer))]
		private static class SpriteRendererTextureOverridePatch
		{
			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyPostfix]
			private static void Postfix_SetSprite(SpriteRenderer __instance)
			{
				try
				{
					if (__instance == null)
					{
						return;
					}
					Sprite sprite = __instance.sprite;
					object obj;
					if (sprite == null)
					{
						obj = null;
					}
					else
					{
						Texture2D texture = sprite.texture;
						obj = ((texture != null) ? ((Object)texture).name : null);
					}
					string text = (string)obj;
					if (text == null)
					{
						return;
					}
					Texture2D value;
					if (!Plugin.TextureRegistry.ContainsKey("_ALL"))
					{
						Plugin.TextureRegistry.TryGetValue(text, out value);
					}
					else
					{
						value = Plugin.TextureRegistry.First((KeyValuePair<string, Texture2D> p) => p.Key == "_ALL").Value;
					}
					if ((Object)(object)value != (Object)null)
					{
						OverrideRendererTexture(__instance, value);
					}
				}
				catch (Exception arg)
				{
					LogManager.Debug($"[MaterialOverride] failed on {((__instance != null) ? ((Object)__instance).name : null)}: {arg}");
				}
			}
		}

		[HarmonyPatch]
		private static class AudioSourcePatches
		{
			[HarmonyPatch(typeof(AudioSource), "Play", new Type[] { })]
			[HarmonyPrefix]
			private static void Play_NoArgs_Postfix(AudioSource __instance)
			{
				SwapClip(__instance);
			}

			[HarmonyPatch(typeof(AudioSource), "Play", new Type[] { typeof(double) })]
			[HarmonyPrefix]
			private static void Play_DelayDouble_Postfix(AudioSource __instance)
			{
				SwapClip(__instance);
			}

			[HarmonyPatch(typeof(AudioSource), "Play", new Type[] { typeof(ulong) })]
			[HarmonyPrefix]
			private static void Play_DelayUlong_Postfix(AudioSource __instance)
			{
				SwapClip(__instance);
			}

			[HarmonyPatch(typeof(AudioSource), "PlayOneShot", new Type[] { typeof(AudioClip) })]
			[HarmonyPrefix]
			private static void PlayOneShot_ClipOnly_Postfix(AudioSource __instance, ref AudioClip __0)
			{
				if (Plugin.AudioRegistry.TryGetValue(((Object)__0).name, out var value))
				{
					__0 = value;
				}
			}

			[HarmonyPatch(typeof(AudioSource), "PlayOneShot", new Type[]
			{
				typeof(AudioClip),
				typeof(float)
			})]
			[HarmonyPrefix]
			private static void PlayOneShot_ClipAndVolume_Postfix(AudioSource __instance, ref AudioClip __0)
			{
				if (Plugin.AudioRegistry.TryGetValue(((Object)__0).name, out var value))
				{
					__0 = value;
				}
			}

			private static void SwapClip(AudioSource src)
			{
				if (((src != null) ? src.clip : null) == null)
				{
					return;
				}
				string name = ((Object)src.clip).name;
				AudioClip value;
				if (!Plugin.AudioRegistry.ContainsKey("_ALL"))
				{
					if (!Plugin.AudioRegistry.TryGetValue(name, out value))
					{
						return;
					}
				}
				else
				{
					value = Plugin.AudioRegistry.First((KeyValuePair<string, AudioClip> p) => p.Key == "_ALL").Value;
				}
				if ((Object)(object)value != (Object)null)
				{
					src.clip = value;
				}
			}
		}

		public static WKTranslationManager Instance;

		private static readonly int MainTexture = Shader.PropertyToID("_MainTex");

		private static List<string> untranslatedText = new List<string>();

		public void Awake()
		{
			if (Instance != null && (Object)(object)Instance != (Object)(object)this)
			{
				LogManager.Warn("Destroying duplicate WKTranslationManager");
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Instance = this;
			LogManager.Info("WKTranslationManager Awake");
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		public void DumpAllHiddenAssets()
		{
			Object[] array = Resources.LoadAll("", typeof(GameObject));
			Object[] array2 = array;
			foreach (Object val in array2)
			{
				GameObject val2 = (GameObject)(object)((val is GameObject) ? val : null);
				if (!((Object)(object)val2 == (Object)null))
				{
					Text[] componentsInChildren = val2.GetComponentsInChildren<Text>(true);
					Text[] array3 = componentsInChildren;
					foreach (Text val3 in array3)
					{
						AddToDict(val3.text);
					}
					TextMeshProUGUI[] componentsInChildren2 = val2.GetComponentsInChildren<TextMeshProUGUI>(true);
					TextMeshProUGUI[] array4 = componentsInChildren2;
					foreach (TextMeshProUGUI val4 in array4)
					{
						AddToDict(((TMP_Text)val4).text);
					}
				}
			}
		}

		public void DumpStringsFromCode()
		{
			Assembly assembly = Assembly.Load("Assembly-CSharp");
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					if (fieldInfo.FieldType == typeof(string))
					{
						string text = (string)fieldInfo.GetValue(null);
						if (!string.IsNullOrEmpty(text))
						{
							AddToDict(text);
						}
					}
				}
			}
		}

		public void DumpAllScriptableObjects()
		{
			ScriptableObject[] array = Resources.FindObjectsOfTypeAll<ScriptableObject>();
			ScriptableObject[] array2 = array;
			foreach (ScriptableObject val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo[] array3 = fields;
				foreach (FieldInfo fieldInfo in array3)
				{
					if (fieldInfo.FieldType == typeof(string))
					{
						string text = (string)fieldInfo.GetValue(val);
						if (!string.IsNullOrEmpty(text))
						{
							AddToDict(text);
						}
					}
					else
					{
						if ((!(fieldInfo.FieldType == typeof(string[])) && !(fieldInfo.FieldType == typeof(List<string>))) || !(fieldInfo.GetValue(val) is IEnumerable<string> enumerable))
						{
							continue;
						}
						foreach (string item in enumerable)
						{
							AddToDict(item);
						}
					}
				}
			}
		}

		public void DumpAllPrefabs()
		{
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			GameObject[] array2 = array;
			foreach (GameObject val in array2)
			{
				Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true);
				Component[] array3 = componentsInChildren;
				foreach (Component val2 in array3)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					PropertyInfo propertyInfo = ((object)val2).GetType().GetProperty("text") ?? ((object)val2).GetType().GetProperty("m_text");
					if (propertyInfo != null && propertyInfo.PropertyType == typeof(string))
					{
						string text = (string)propertyInfo.GetValue(val2);
						if (!string.IsNullOrEmpty(text))
						{
							AddToDict(text);
						}
					}
				}
			}
		}

		public void LoadEverythingThenDump()
		{
			IEnumerable<AssetBundle> allLoadedAssetBundles = AssetBundle.GetAllLoadedAssetBundles();
			foreach (AssetBundle item in allLoadedAssetBundles)
			{
				item.LoadAllAssets();
			}
		}

		public void AddToDict(string txt)
		{
			if (!untranslatedText.Contains(txt))
			{
				untranslatedText.Add(txt);
			}
		}

		public void DumpTheText()
		{
			LoadEverythingThenDump();
			DumpAllHiddenAssets();
			DumpStringsFromCode();
			DumpAllScriptableObjects();
			DumpAllPrefabs();
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (directoryName == null)
			{
				return;
			}
			string path = Path.Combine(directoryName, "untranslated.json");
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in untranslatedText)
			{
				dictionary.TryAdd(item, item);
			}
			string contents = JsonConvert.SerializeObject((object)dictionary, (Formatting)1);
			File.WriteAllText(path, contents);
		}

		public async void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			CommandConsole.AddCommand("dumpalltext", (Action<string[]>)delegate
			{
				DumpTheText();
			}, false);
			if (CanContinueScene(((Scene)(ref scene)).name))
			{
				await PrepareAsync();
				ReplaceAllMaterial();
				ReplaceTextures();
				ReplaceAllMaterial();
				ReplaceOnSources();
				CommandConsole.AddCommand("startscanner", (Action<string[]>)delegate
				{
					TextScanner.RunScanner();
				}, false);
				CommandConsole.AddCommand("endscanner", (Action<string[]>)delegate
				{
					TextScanner.StopScanner();
				}, false);
				CommandConsole.AddCommand("reloadtranslation", (Action<string[]>)delegate
				{
					Plugin.Instance.ReloadLanguage();
				}, false);
				LogManager.Warn("Added commands");
			}
		}

		private async Task PrepareAsync()
		{
			Scene activeScene = SceneManager.GetActiveScene();
			LogManager.Info("Scanning scene: " + ((Scene)(ref activeScene)).name + " for static text...");
			TMP_Text[] allTmp = Resources.FindObjectsOfTypeAll<TMP_Text>();
			TMP_Text[] array = allTmp;
			foreach (TMP_Text txt in array)
			{
				if (ValidForTranslation(((Component)txt).gameObject))
				{
					TryTranslate(txt);
				}
			}
			Text[] allLegacy = Resources.FindObjectsOfTypeAll<Text>();
			Text[] array2 = allLegacy;
			foreach (Text txt2 in array2)
			{
				if (ValidForTranslation(((Component)txt2).gameObject))
				{
					TryTranslateLegacy(txt2);
				}
			}
		}

		private bool ValidForTranslation(GameObject go)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Scene scene = go.scene;
			int result;
			if (!((Scene)(ref scene)).isLoaded)
			{
				scene = go.scene;
				result = ((((Scene)(ref scene)).name == "DontDestroyOnLoad") ? 1 : 0);
			}
			else
			{
				result = 1;
			}
			return (byte)result != 0;
		}

		public static void TryTranslate(TMP_Text txtComponent)
		{
			if (!((Object)(object)txtComponent == (Object)null) && !string.IsNullOrEmpty(txtComponent.text) && Plugin.TryGetTranslation(txtComponent.text, out var translated) && !(txtComponent.text == translated))
			{
				txtComponent.text = translated;
				FontLoader.TryReplace(txtComponent);
				txtComponent.enableAutoSizing = true;
				txtComponent.fontSizeMax = txtComponent.fontSize;
				txtComponent.fontSizeMin = 12f;
				txtComponent.enableWordWrapping = false;
				if (((Component)txtComponent).gameObject.activeInHierarchy)
				{
					LayoutRebuilder.MarkLayoutForRebuild(txtComponent.rectTransform);
				}
			}
		}

		public static void TryTranslateLegacy(Text txtComponent)
		{
			if (!((Object)(object)txtComponent == (Object)null) && !string.IsNullOrEmpty(txtComponent.text) && Plugin.TryGetTranslation(txtComponent.text, out var translated) && !(txtComponent.text == translated))
			{
				txtComponent.text = translated;
				FontLoader.TryReplace(txtComponent);
				txtComponent.resizeTextForBestFit = true;
				txtComponent.resizeTextMaxSize = Mathf.FloorToInt((float)txtComponent.fontSize);
				txtComponent.resizeTextMinSize = 10;
				txtComponent.horizontalOverflow = (HorizontalWrapMode)1;
				if (((Component)txtComponent).gameObject.activeInHierarchy)
				{
					LayoutRebuilder.MarkLayoutForRebuild(((Graphic)txtComponent).rectTransform);
				}
			}
		}

		private void ReplaceAllMaterial()
		{
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if (!val.HasProperty(MainTexture) || ((val != null) ? val.mainTexture : null) == null)
				{
					continue;
				}
				LogManager.Debug("Found " + ((Object)val.mainTexture).name);
				Texture2D value;
				if (!Plugin.TextureRegistry.ContainsKey("_ALL"))
				{
					Plugin.TextureRegistry.TryGetValue(((Object)val.mainTexture).name, out value);
				}
				else
				{
					value = Plugin.TextureRegistry.First((KeyValuePair<string, Texture2D> p) => p.Key == "_ALL").Value;
				}
				if (!((Object)(object)value == (Object)null))
				{
					LogManager.Debug("Replacing " + ((Object)val.mainTexture).name);
					val.mainTexture = (Texture)(object)value;
				}
			}
		}

		private void ReplaceTextures()
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			Image[] array = Resources.FindObjectsOfTypeAll<Image>();
			Rect val2 = default(Rect);
			foreach (Image val in array)
			{
				if (val.sprite == null)
				{
					continue;
				}
				Texture2D value;
				if (!Plugin.TextureRegistry.ContainsKey("_ALL"))
				{
					if (!Plugin.TextureRegistry.TryGetValue(((Object)val.sprite).name, out value))
					{
						continue;
					}
				}
				else
				{
					value = Plugin.TextureRegistry.First((KeyValuePair<string, Texture2D> p) => p.Key == "_ALL").Value;
				}
				Sprite sprite = val.sprite;
				((Rect)(ref val2))..ctor(0f, 0f, (float)((Texture)value).width, (float)((Texture)value).height);
				Sprite overrideSprite = (val.sprite = Sprite.Create(value, val2, new Vector2(0.5f, 0.5f), sprite.pixelsPerUnit, 0u, (SpriteMeshType)0, sprite.border));
				val.overrideSprite = overrideSprite;
				if (((Graphic)val).rectTransform != null)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(((Graphic)val).rectTransform);
				}
			}
		}

		private static void OverrideRendererTexture(SpriteRenderer sr, Texture2D newTex)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			MaterialPropertyBlock val = new MaterialPropertyBlock();
			((Renderer)sr).GetPropertyBlock(val);
			val.SetTexture(MainTexture, (Texture)(object)newTex);
			((Renderer)sr).SetPropertyBlock(val);
		}

		private void ReplaceOnSources()
		{
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true);
			foreach (AudioSource val in array)
			{
				if (val.clip == null)
				{
					continue;
				}
				string name = val.clip.GetName();
				AudioClip value;
				if (!Plugin.AudioRegistry.ContainsKey("_ALL"))
				{
					if (!Plugin.AudioRegistry.TryGetValue(name, out value))
					{
						continue;
					}
				}
				else
				{
					value = Plugin.AudioRegistry.First((KeyValuePair<string, AudioClip> p) => p.Key == "_ALL").Value;
				}
				if (value != null)
				{
					bool isPlaying = val.isPlaying;
					bool playOnAwake = val.playOnAwake;
					val.clip = value;
					if (isPlaying || playOnAwake)
					{
						val.Play();
					}
					LogManager.Debug("Replaced AudioSource Clip on " + ((Object)((Component)val).gameObject).name + " (" + name + ")");
				}
			}
		}

		private bool CanContinueScene(string sceneName)
		{
			if (1 == 0)
			{
			}
			bool result = true;
			if (1 == 0)
			{
			}
			return result;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "galfarious.WKTranslator";

		public const string PLUGIN_NAME = "WKTranslator";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}