Decompiled source of Ratpack Korean v1.1.1

BepInEx/patchers/RatpackKorean/RatpackKorean.Bootstrap.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RatpackKorean;

public static class Bootstrap
{
	public static IEnumerable<string> TargetDLLs => new string[0];

	public static void Patch(AssemblyDefinition assembly)
	{
	}

	public static void Initialize()
	{
		ManualLogSource val = Logger.CreateLogSource("Ratpack Korean Setup");
		try
		{
			string[] files = Directory.GetFiles(Paths.PluginPath, "RatpackKorean.dll", SearchOption.AllDirectories);
			if (files.Length != 1)
			{
				throw new InvalidOperationException("Expected one RatpackKorean.dll; remove duplicate manual installations.");
			}
			string text = Configure(Paths.BepInExRootPath, Path.GetDirectoryName(files[0]));
			val.LogInfo((object)text);
		}
		catch (Exception ex)
		{
			val.LogError((object)("Automatic Korean setup failed: " + ex));
		}
	}

	private static string Fingerprint(string path)
	{
		using SHA256 sHA = SHA256.Create();
		using FileStream inputStream = File.OpenRead(path);
		return BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "");
	}

	private static string FindDependencyFile(string root, string name, string fingerprint)
	{
		foreach (string item in Directory.GetFiles(root, name, SearchOption.AllDirectories).OrderBy<string, string>((string x) => x, StringComparer.Ordinal))
		{
			if (Fingerprint(item) == fingerprint)
			{
				return item;
			}
		}
		throw new FileNotFoundException("Install dependency Eomuk-ROUNDS_Korean_Mod-24.2.23 again: missing or modified " + name);
	}

	private static string Escape(string text)
	{
		return text.Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t");
	}

	private static void ReadDictionary(string path, IDictionary<string, string> map)
	{
		string[] array = File.ReadAllLines(path, Encoding.UTF8);
		foreach (string text in array)
		{
			if (!string.IsNullOrWhiteSpace(text) && !text.StartsWith("//"))
			{
				int num = text.IndexOf('=');
				if (num > 0)
				{
					map[text.Substring(0, num)] = text.Substring(num + 1);
				}
			}
		}
	}

	private static bool WriteIfChanged(string path, string text)
	{
		if (File.Exists(path) && File.ReadAllText(path, Encoding.UTF8) == text)
		{
			return false;
		}
		Directory.CreateDirectory(Path.GetDirectoryName(path));
		File.WriteAllText(path, text, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
		return true;
	}

	public static string Configure(string root, string package)
	{
		root = Path.GetFullPath(root);
		package = Path.GetFullPath(package);
		string text = FindDependencyFile(root, "font.dll", "57135C684864B15EC8C785C4BAA89796656FAEDFA036AC0072A32E1D34A523C3");
		string path = FindDependencyFile(root, "Translations.dll", "7591B6641AE7E8BC77CF9EAB0A6332C16D5CFCD7585656C2198EF7BF20A85625");
		string text2 = Path.Combine(root, "config/RatpackKorean/generated");
		SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(StringComparer.Ordinal);
		ReadDictionary(path, sortedDictionary);
		ReadDictionary(Path.Combine(package, "RatpackKorean.txt"), sortedDictionary);
		KeyValuePair<string, string>[] array = sortedDictionary.ToArray();
		for (int i = 0; i < array.Length; i++)
		{
			KeyValuePair<string, string> keyValuePair = array[i];
			if (!keyValuePair.Key.StartsWith("r:") && !keyValuePair.Key.StartsWith("sr:") && !sortedDictionary.ContainsKey(keyValuePair.Key.ToUpperInvariant()))
			{
				sortedDictionary[keyValuePair.Key.ToUpperInvariant()] = keyValuePair.Value;
			}
		}
		WriteIfChanged(Path.Combine(text2, "Translations.txt"), "// Generated locally from installed dependencies and Ratpack Korean.\n" + string.Join("\n", sortedDictionary.Select((KeyValuePair<string, string> x) => x.Key + "=" + x.Value).ToArray()) + "\n");
		WriteIfChanged(Path.Combine(text2, "pixel-dictionary.tsv"), string.Join("\n", (from x in sortedDictionary
			where !x.Key.StartsWith("r:") && !x.Key.StartsWith("sr:")
			select x.Key + "\t" + x.Value).ToArray()) + "\n");
		string[] array2 = new string[4] { "_AutoGeneratedTranslations.txt", "_Substitutions.txt", "_Preprocessors.txt", "_Postprocessors.txt" };
		foreach (string path2 in array2)
		{
			if (!File.Exists(Path.Combine(text2, path2)))
			{
				WriteIfChanged(Path.Combine(text2, path2), "");
			}
		}
		string text3 = Path.Combine(root, "config/AutoTranslatorConfig.ini");
		string text4 = (File.Exists(text3) ? File.ReadAllText(text3, Encoding.UTF8) : "");
		string text5 = text4;
		string[,] array3 = new string[23, 3]
		{
			{ "Service", "Endpoint", "" },
			{ "Service", "FallbackEndpoint", "" },
			{ "General", "Language", "ko" },
			{ "General", "FromLanguage", "en" },
			{ "Files", "Directory", text2 },
			{
				"Files",
				"OutputFile",
				Path.Combine(text2, "_AutoGeneratedTranslations.txt")
			},
			{
				"Files",
				"SubstitutionFile",
				Path.Combine(text2, "_Substitutions.txt")
			},
			{
				"Files",
				"PreprocessorsFile",
				Path.Combine(text2, "_Preprocessors.txt")
			},
			{
				"Files",
				"PostprocessorsFile",
				Path.Combine(text2, "_Postprocessors.txt")
			},
			{ "TextFrameworks", "EnableIMGUI", "True" },
			{ "TextFrameworks", "EnableUGUI", "True" },
			{ "TextFrameworks", "EnableTextMesh", "True" },
			{ "TextFrameworks", "EnableTextMeshPro", "True" },
			{ "Behaviour", "MaxCharactersPerTranslation", "2000" },
			{ "Behaviour", "OverrideFont", "Malgun Gothic" },
			{ "Behaviour", "OverrideFontTextMeshPro", "" },
			{ "Behaviour", "FallbackFontTextMeshPro", text },
			{ "Behaviour", "EnableUIResizing", "True" },
			{ "Behaviour", "TextGetterCompatibilityMode", "False" },
			{ "Behaviour", "InitializeHarmonyDetourBridge", "False" },
			{ "Behaviour", "EnableSilentMode", "True" },
			{ "Behaviour", "ReloadTranslationsOnFileChange", "False" },
			{ "Http", "DisableCertificateValidation", "False" }
		};
		for (int num2 = 0; num2 < array3.GetLength(0); num2++)
		{
			text5 = SetIni(text5, array3[num2, 0], array3[num2, 1], array3[num2, 2]);
		}
		string text6 = text3 + ".before-RatpackKorean";
		if (text5 != text4 && File.Exists(text3) && !File.Exists(text6))
		{
			File.Copy(text3, text6);
		}
		WriteIfChanged(text3, text5);
		string text7 = "Automatic setup ready; dictionary=" + sortedDictionary.Count + "; font=" + text + "; dictionaryPath=" + text2;
		WriteIfChanged(Path.Combine(text2, "setup-report.txt"), text7 + "\n");
		return text7;
	}

	public static string SetIni(string text, string section, string key, string value)
	{
		List<string> list = new List<string>(text.Replace("\r\n", "\n").Split(new char[1] { '\n' }));
		int num = -1;
		int num2 = list.Count;
		for (int i = 0; i < list.Count; i++)
		{
			string text2 = list[i].Trim();
			if (text2.Equals("[" + section + "]", StringComparison.OrdinalIgnoreCase))
			{
				num = i;
			}
			else if (num >= 0 && text2.StartsWith("[") && text2.EndsWith("]"))
			{
				num2 = i;
				break;
			}
		}
		if (num < 0)
		{
			list.Add("[" + section + "]");
			list.Add(key + "=" + value);
		}
		else
		{
			bool flag = false;
			for (int j = num + 1; j < num2; j++)
			{
				int num3 = list[j].IndexOf('=');
				if (num3 >= 0 && list[j].Substring(0, num3).Trim().Equals(key, StringComparison.OrdinalIgnoreCase))
				{
					list[j] = key + "=" + value;
					flag = true;
				}
			}
			if (!flag)
			{
				list.Insert(num2, key + "=" + value);
			}
		}
		return string.Join("\n", list.ToArray()).TrimEnd(new char[1] { '\n' }) + "\n";
	}
}

BepInEx/plugins/RatpackKorean/RatpackKorean.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using XUnity.AutoTranslator.Plugin.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RatpackKorean;

[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.ratpack.korean", "Ratpack Korean", "1.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	private static readonly Dictionary<char, Sprite> Glyphs = new Dictionary<char, Sprite>();

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

	private static readonly Dictionary<string, string> Cache = new Dictionary<string, string>(StringComparer.Ordinal);

	private static Plugin instance;

	private static string folder;

	private static readonly string[] ClientOnlyGuids = new string[3] { "local.ratpack.korean", "gravydevsupreme.xunity.autotranslator", "gravydevsupreme.xunity.resourceredirector" };

	private Harmony harmony;

	private static TMP_FontAsset maskFont;

	private static int repairedMaskLabels;

	private static readonly Dictionary<int, Material> MaskMaterials = new Dictionary<int, Material>();

	private static readonly HashSet<TextMeshProUGUI> PendingMaskedLabels = new HashSet<TextMeshProUGUI>();

	private static Material overlayMaterial;

	private static Material OverlayMaterial
	{
		get
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)overlayMaterial == (Object)null)
			{
				Shader val = Shader.Find("GUI/Text Shader");
				if ((Object)(object)val == (Object)null)
				{
					throw new InvalidOperationException("Missing Unity GUI/Text Shader for Korean HUD overlay.");
				}
				overlayMaterial = new Material(val);
				((Object)overlayMaterial).name = "RatpackKorean_HUD_Overlay";
				overlayMaterial.renderQueue = 4000;
				overlayMaterial.color = Color.white;
				Object.DontDestroyOnLoad((Object)(object)overlayMaterial);
			}
			return overlayMaterial;
		}
	}

	private void LateUpdate()
	{
		if (PendingMaskedLabels.Count == 0)
		{
			return;
		}
		TextMeshProUGUI[] array = PendingMaskedLabels.ToArray();
		PendingMaskedLabels.Clear();
		TextMeshProUGUI[] array2 = array;
		foreach (TextMeshProUGUI val in array2)
		{
			if (!((Object)(object)val != (Object)null) || !((Behaviour)val).isActiveAndEnabled)
			{
				continue;
			}
			((TMP_Text)val).ForceMeshUpdate();
			TMP_SubMeshUI[] array3 = (TMP_SubMeshUI[])AccessTools.Field(typeof(TextMeshProUGUI), "m_subTextObjects").GetValue(val);
			for (int j = ((TMP_Text)val).textInfo.materialCount; j < array3.Length; j++)
			{
				if ((Object)(object)array3[j] != (Object)null)
				{
					array3[j].canvasRenderer.SetMesh((Mesh)null);
				}
			}
			((Graphic)val).SetMaterialDirty();
		}
	}

	private static void MaskedTextPrefix(TextMeshProUGUI __instance)
	{
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Expected O, but got Unknown
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Expected O, but got Unknown
		Mask component = ((Component)__instance).GetComponent<Mask>();
		if ((Object)(object)component == (Object)null || !((Behaviour)component).enabled || string.IsNullOrEmpty(((TMP_Text)__instance).text) || !((TMP_Text)__instance).text.Any((char c) => c >= '가' && c <= '힣'))
		{
			return;
		}
		if ((Object)(object)maskFont == (Object)null)
		{
			maskFont = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name.StartsWith("SourceHanSans", StringComparison.Ordinal) && f.HasCharacter('한')));
		}
		if (!((Object)(object)maskFont == (Object)null) && !((Object)(object)((TMP_Text)__instance).font == (Object)(object)maskFont))
		{
			Material fontSharedMaterial = ((TMP_Text)__instance).fontSharedMaterial;
			Material value = null;
			if ((Object)(object)fontSharedMaterial != (Object)null && !MaskMaterials.TryGetValue(((Object)fontSharedMaterial).GetInstanceID(), out value))
			{
				Type type = typeof(TMP_Text).Assembly.GetType("TMPro.TMP_MaterialManager", throwOnError: true);
				MethodInfo methodInfo = AccessTools.Method(type, "GetFallbackMaterial", new Type[2]
				{
					typeof(Material),
					typeof(Material)
				}, (Type[])null);
				value = new Material((Material)methodInfo.Invoke(null, new object[2]
				{
					fontSharedMaterial,
					((TMP_Asset)maskFont).material
				}));
				((Object)value).name = "RatpackKorean_Masked_" + ((Object)fontSharedMaterial).name;
				Object.DontDestroyOnLoad((Object)(object)value);
				MaskMaterials[((Object)fontSharedMaterial).GetInstanceID()] = value;
			}
			((TMP_Text)__instance).font = maskFont;
			if ((Object)(object)value != (Object)null)
			{
				((TMP_Text)__instance).fontSharedMaterial = value;
			}
			if (((Object)__instance).name == "GameOverText")
			{
				float fontSize = ((TMP_Text)__instance).fontSize;
				((TMP_Text)__instance).enableWordWrapping = false;
				((TMP_Text)__instance).fontSizeMin = fontSize * 0.35f;
				((TMP_Text)__instance).fontSizeMax = fontSize;
				((TMP_Text)__instance).enableAutoSizing = true;
			}
			((Graphic)__instance).SetVerticesDirty();
			((Graphic)__instance).SetMaterialDirty();
			PendingMaskedLabels.Add(__instance);
			repairedMaskLabels++;
			((BaseUnityPlugin)instance).Logger.LogInfo((object)("Masked Korean label uses primary glyph mesh: " + ((Object)__instance).name));
		}
	}

	private static void OverlayTextPostfix(object __instance)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		string[] array = new string[2] { "_fg", "_bg" };
		foreach (string text in array)
		{
			IList list = (IList)AccessTools.Field(__instance.GetType(), text).GetValue(__instance);
			foreach (SpriteRenderer item in list)
			{
				SpriteRenderer val = item;
				((Renderer)val).sharedMaterial = OverlayMaterial;
			}
		}
	}

	private static void OverlayBarPostfix(SpriteRenderer __result)
	{
		if ((Object)(object)__result != (Object)null)
		{
			((Renderer)__result).sharedMaterial = OverlayMaterial;
		}
	}

	private void Awake()
	{
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Expected O, but got Unknown
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Expected O, but got Unknown
		//IL_01e9: Expected O, but got Unknown
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Expected O, but got Unknown
		instance = this;
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		string text = Path.Combine(Paths.ConfigPath, "RatpackKorean/generated/pixel-dictionary.tsv");
		if (!File.Exists(text))
		{
			throw new FileNotFoundException("Ratpack Korean automatic setup did not run. See the setup error in BepInEx/LogOutput.log.", text);
		}
		string[] array = File.ReadAllLines(text, Encoding.UTF8);
		foreach (string text2 in array)
		{
			int num = text2.IndexOf('\t');
			if (num > 0)
			{
				Map[Unescape(text2.Substring(0, num))] = Unescape(text2.Substring(num + 1));
			}
		}
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
		if (!ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(folder, "hangul-atlas.png"))))
		{
			throw new InvalidDataException("Korean pixel atlas did not load.");
		}
		((Texture)val).filterMode = (FilterMode)1;
		((Texture)val).wrapMode = (TextureWrapMode)1;
		Object.DontDestroyOnLoad((Object)(object)val);
		string[] array2 = File.ReadAllLines(Path.Combine(folder, "hangul-atlas.tsv"));
		foreach (string text3 in array2)
		{
			string[] array3 = text3.Split(new char[1] { '\t' });
			char key = (char)int.Parse(array3[0]);
			Sprite val2 = Sprite.Create(val, new Rect((float)int.Parse(array3[1]), (float)int.Parse(array3[2]), 40f, 56f), new Vector2(0f, 1f), 8f);
			Object.DontDestroyOnLoad((Object)(object)val2);
			Glyphs[key] = val2;
		}
		harmony = new Harmony("local.ratpack.korean.pixel");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(TextMeshProUGUI), "OnPreRenderCanvas", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "MaskedTextPrefix", (Type[])null), new HarmonyMethod(typeof(Plugin), "MaskedTextPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		Type type = Type.GetType("UnboundLib.Unbound, UnboundLib", throwOnError: true);
		MethodInfo methodInfo = AccessTools.Method(type, "RegisterClientSideMod", new Type[1] { typeof(string) }, (Type[])null);
		string[] clientOnlyGuids = ClientOnlyGuids;
		foreach (string text4 in clientOnlyGuids)
		{
			methodInfo.Invoke(null, new object[1] { text4 });
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered Korean presentation plugins as client-side mods.");
		Type type2 = Type.GetType("CardInfoDisplayer, Assembly-CSharp", throwOnError: true);
		harmony.Patch((MethodBase)AccessTools.Method(type2, "DrawCard", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "CardLayoutPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static void CardLayoutPostfix(object __instance)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		GameObject val = (GameObject)AccessTools.Field(__instance.GetType(), "grid").GetValue(__instance);
		foreach (Transform item in val.transform)
		{
			Transform val2 = item;
			TextMeshProUGUI[] componentsInChildren = ((Component)val2).GetComponentsInChildren<TextMeshProUGUI>(true);
			if (componentsInChildren.Length == 2 && componentsInChildren.Any((TextMeshProUGUI t) => ((TMP_Text)t).text.Any((char c) => c >= '가' && c <= '힣')))
			{
				TextMeshProUGUI[] array = componentsInChildren;
				foreach (TextMeshProUGUI val3 in array)
				{
					float fontSize = ((TMP_Text)val3).fontSize;
					((TMP_Text)val3).enableWordWrapping = false;
					((TMP_Text)val3).fontSizeMin = fontSize * 0.65f;
					((TMP_Text)val3).fontSizeMax = fontSize;
					((TMP_Text)val3).enableAutoSizing = true;
				}
			}
		}
	}

	private IEnumerator Start()
	{
		yield return null;
		string[] names = new string[2] { "CodyGunCards.Modes.PixelText, CodyGunCards", "LetItRide.PixelText, LetItRide" };
		int patches = 0;
		string[] array = names;
		foreach (string text in array)
		{
			Type type = Type.GetType(text, throwOnError: false);
			if (type == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Missing pixel label type: " + text));
				continue;
			}
			Type type2 = type.Assembly.GetType(type.Namespace + ".PixelFont", throwOnError: true);
			harmony.Patch((MethodBase)AccessTools.Method(type, "Set", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "TextPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(type, "Rebuild", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "OverlayTextPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(type2, "Glyph", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "GlyphPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(type2, "Has", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "HasPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			patches++;
		}
		Type hud = Type.GetType("CodyGunCards.Modes.ModeHud, CodyGunCards", throwOnError: true);
		harmony.Patch((MethodBase)AccessTools.Method(hud, "Part", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "OverlayBarPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Korean ready: " + Map.Count + " dictionary entries, " + Glyphs.Count + " atlas glyphs, " + patches + " pixel systems."));
		string[] args = Environment.GetCommandLineArgs();
		int qa = Array.IndexOf(args, "--ratpack-korean-verify");
		if (qa >= 0 && qa + 1 < args.Length)
		{
			yield return (object)new WaitForSecondsRealtime(20f);
			Verify(args[qa + 1]);
		}
	}

	private static string Unescape(string x)
	{
		return x.Replace("\\n", "\n").Replace("\\r", "\r").Replace("\\t", "\t");
	}

	private static void TextPrefix(ref string __0)
	{
		string text = Translate(__0);
		if (!(text != __0) || !text.Any((char c) => c > '\u007f' && !Glyphs.ContainsKey(c)))
		{
			__0 = text;
		}
	}

	private static bool GlyphPrefix(char __0, ref Sprite __result)
	{
		if (!Glyphs.TryGetValue(__0, out var value))
		{
			return true;
		}
		__result = value;
		return false;
	}

	private static bool HasPrefix(char __0, ref bool __result)
	{
		if (!Glyphs.ContainsKey(__0))
		{
			return true;
		}
		__result = true;
		return false;
	}

	private static string Lookup(string text)
	{
		if (text == null)
		{
			return null;
		}
		if (Map.TryGetValue(text.Trim(), out var value))
		{
			return value;
		}
		if (AutoTranslator.Default != null && AutoTranslator.Default.TryTranslate(text, ref value))
		{
			return value;
		}
		return text;
	}

	public static string Translate(string text)
	{
		if (string.IsNullOrEmpty(text))
		{
			return text;
		}
		if (Cache.TryGetValue(text, out var value))
		{
			return value;
		}
		string text2 = Lookup(text);
		if (text2 == text)
		{
			Match match;
			if ((match = Regex.Match(text, "^WAVE (\\d+)( CLEARED)?$")).Success)
			{
				text2 = "웨이브 " + match.Groups[1].Value + (match.Groups[2].Success ? " 완료" : "");
			}
			else if ((match = Regex.Match(text, "^BEST (\\d+)$")).Success)
			{
				text2 = "최고 기록 " + match.Groups[1].Value;
			}
			else if ((match = Regex.Match(text, "^(\\d+) ENEM(?:Y|IES)( LEFT)?$")).Success)
			{
				text2 = "남은 적 " + match.Groups[1].Value + "명";
			}
			else if ((match = Regex.Match(text, "^ELITE WAVE\\s+(\\d+) ENEMIES$")).Success)
			{
				text2 = "정예 웨이브  적 " + match.Groups[1].Value + "명";
			}
			else if ((match = Regex.Match(text, "^NEW BEST: (\\d+) WAVES?$")).Success)
			{
				text2 = "최고 기록: " + match.Groups[1].Value + "웨이브";
			}
			else if ((match = Regex.Match(text, "^SURVIVED (\\d+) WAVES?\\s+KILLS (\\d+)$")).Success)
			{
				text2 = match.Groups[1].Value + "웨이브 생존  처치 " + match.Groups[2].Value;
			}
			else if ((match = Regex.Match(text, "^CLEARED WITH (\\d+) RETR(?:Y|IES)$")).Success)
			{
				text2 = match.Groups[1].Value + "회 재도전 후 완료";
			}
			else if ((match = Regex.Match(text, "^BOSS (\\d+) OF (\\d+)$")).Success)
			{
				text2 = "보스 " + match.Groups[1].Value + " / " + match.Groups[2].Value;
			}
			else if ((match = Regex.Match(text, "^BY (THE .+)$")).Success)
			{
				text2 = Lookup(match.Groups[1].Value) + "에게 패배";
			}
			else if ((match = Regex.Match(text, "^BET (.+)$")).Success)
			{
				text2 = "건 카드: " + Lookup(match.Groups[1].Value);
			}
			else if ((match = Regex.Match(text, "^WIN\\s+\\+(.+)$")).Success)
			{
				text2 = "당첨 +" + Lookup(match.Groups[1].Value);
			}
			else if ((match = Regex.Match(text, "^LOST\\s+-(.+)$")).Success)
			{
				text2 = "상실 -" + Lookup(match.Groups[1].Value);
			}
			else if ((match = Regex.Match(text, "^([0-9 +:=-]+): (.+)$")).Success)
			{
				text2 = match.Groups[1].Value + ": " + Lookup(match.Groups[2].Value);
			}
			else if (Regex.IsMatch(text, "^(DMG |LASER KATANA:|GUN CARD BECOMES |AMMO BECOMES |SLASH |BULLETS BECOME |SPEED BECOMES |BOUNCES BECOME |NEXT DRAW )"))
			{
				text2 = text.Replace("LASER KATANA: SWEEP ", "레이저 카타나: 휩쓸기 ").Replace("GUN CARD BECOMES SLASH ", "총기 카드 → 베기 ").Replace("AMMO BECOMES SLASH ", "탄약 → 베기 ")
					.Replace("BULLETS BECOME ARC ", "탄환 수 → 베기 각도 ")
					.Replace("SPEED BECOMES REACH ", "탄속 → 사거리 ")
					.Replace("BOUNCES BECOME PARRY ", "반사 횟수 → 튕겨내기 ")
					.Replace("NEXT DRAW ", "다음 발도 ")
					.Replace("SLASH ", "베기 ")
					.Replace("DMG TO ", "피해, 사거리 ")
					.Replace("DMG", "피해")
					.Replace("ARC", "각도")
					.Replace("REACH", "사거리")
					.Replace("PARRY", "튕겨내기")
					.Replace("DRAW", "발도")
					.Replace("LASER", "레이저");
				text2 = Regex.Replace(text2, "(?<=\\d)S\\b", "초");
			}
		}
		if (Cache.Count > 4096)
		{
			Cache.Clear();
		}
		Cache[text] = text2;
		return text2;
	}

	private void Verify(string output)
	{
		//IL_031b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Expected O, but got Unknown
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		List<string> list = new List<string>();
		list.Add("Dictionary=" + Map.Count + "; Glyphs=" + Glyphs.Count);
		int num = 0;
		string[] array = new string[3] { "Breakaway Armour", "Waves", "Sandbox" };
		string text2 = default(string);
		foreach (string text in array)
		{
			bool flag = AutoTranslator.Default.TryTranslate(text, ref text2) && text2.Any((char c) => c > '\u007f');
			list.Add((flag ? "PASS " : "FAIL ") + "automatic dictionary " + text + " => " + text2);
			if (!flag)
			{
				num++;
			}
		}
		bool flag2 = Resources.FindObjectsOfTypeAll<TMP_FontAsset>().Any((TMP_FontAsset f) => f.HasCharacter('한'));
		list.Add((flag2 ? "PASS " : "FAIL ") + "Korean TMP font loaded from dependency");
		if (!flag2)
		{
			num++;
		}
		Type type = Type.GetType("UnboundLib.Networking.SyncModClients, UnboundLib", throwOnError: true);
		IList list2 = (IList)AccessTools.Field(type, "clientSideGUIDs").GetValue(null);
		string[] clientOnlyGuids = ClientOnlyGuids;
		foreach (string text3 in clientOnlyGuids)
		{
			bool flag3 = list2.Contains(text3);
			list.Add((flag3 ? "PASS " : "FAIL ") + "client-side registration " + text3);
			if (!flag3)
			{
				num++;
			}
		}
		string[] array2 = new string[7] { "WAVE 12 CLEARED", "SURVIVED 12 WAVES  KILLS 45", "BET Katana", "WIN  +Polymorph", "BY THE FOREMAN", "2: HUMAN ACCORDION", "DMG 130   ARC 90   REACH 4.0   PARRY 0.15S  DRAW 1.0S" };
		foreach (string text4 in array2)
		{
			string text5 = Translate(text4);
			bool flag4 = text5 != text4 && text5.Any((char c) => c > '\u007f') && !text5.Any((char c) => c > '\u007f' && !Glyphs.ContainsKey(c));
			list.Add((flag4 ? "PASS " : "FAIL ") + text4 + " => " + text5);
			if (!flag4)
			{
				num++;
			}
		}
		string[] array3 = new string[2] { "CodyGunCards.Modes.PixelText, CodyGunCards", "LetItRide.PixelText, LetItRide" };
		foreach (string text6 in array3)
		{
			GameObject val = new GameObject("RatpackKoreanQA");
			try
			{
				Type type2 = Type.GetType(text6, throwOnError: true);
				object obj = Activator.CreateInstance(type2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[2] { val.transform, 100 }, null);
				AccessTools.Method(type2, "Set", (Type[])null, (Type[])null).Invoke(obj, new object[5]
				{
					"WAVE 12 CLEARED",
					Color.white,
					(object)new Vector2(0f, 0f),
					0.1f,
					1f
				});
				string text7 = (string)AccessTools.Field(type2, "_text").GetValue(obj);
				SpriteRenderer[] componentsInChildren = val.GetComponentsInChildren<SpriteRenderer>();
				bool flag5 = text7 == "웨이브 12 완료" && componentsInChildren.Count((SpriteRenderer x) => (Object)(object)x.sprite != (Object)null) >= 7;
				list.Add((flag5 ? "PASS " : "FAIL ") + text6 + " renders " + text7);
				if (!flag5)
				{
					num++;
				}
			}
			catch (Exception ex)
			{
				list.Add("FAIL " + text6 + " " + ex);
				num++;
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}
		try
		{
			num += VerifyOcclusion(list, Path.GetDirectoryName(output));
		}
		catch (Exception ex2)
		{
			list.Add("FAIL HUD occlusion check: " + ex2);
			num++;
		}
		list.Add("Failures=" + num);
		File.WriteAllLines(output, list.ToArray(), Encoding.UTF8);
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Korean verification complete: " + num + " failures. " + output));
	}

	private int VerifyOcclusion(List<string> lines, string outputFolder)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Expected O, but got Unknown
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Expected O, but got Unknown
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("KoreanOcclusionTest");
		RenderTexture val2 = new RenderTexture(640, 256, 24);
		Texture2D val3 = new Texture2D(640, 256, (TextureFormat)3, false);
		Material val4 = null;
		RenderTexture active = RenderTexture.active;
		try
		{
			GameObject val5 = new GameObject("TestCamera");
			val5.transform.SetParent(val.transform, false);
			Camera val6 = val5.AddComponent<Camera>();
			((Behaviour)val6).enabled = false;
			val6.orthographic = true;
			val6.orthographicSize = 2f;
			val6.aspect = 2.5f;
			((Component)val6).transform.position = new Vector3(10000f, 10000f, -10f);
			val6.clearFlags = (CameraClearFlags)2;
			val6.backgroundColor = Color.black;
			val6.cullingMask = int.MinValue;
			val6.targetTexture = val2;
			GameObject val7 = GameObject.CreatePrimitive((PrimitiveType)5);
			((Object)val7).name = "OpaqueMapInFrontOfText";
			val7.transform.SetParent(val.transform, false);
			val7.layer = 31;
			val7.transform.position = new Vector3(10000f, 10000f, -2f);
			val7.transform.localScale = new Vector3(20f, 20f, 1f);
			Shader val8 = Shader.Find("Unlit/Color");
			if ((Object)(object)val8 == (Object)null)
			{
				val8 = Shader.Find("Sprites/Default");
			}
			val4 = new Material(val8);
			val4.color = new Color(0.2f, 0.05f, 0.02f, 1f);
			val7.GetComponent<Renderer>().sharedMaterial = val4;
			Type type = Type.GetType("CodyGunCards.Modes.PixelText, CodyGunCards", throwOnError: true);
			object obj = Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[2] { val.transform, 304 }, null);
			AccessTools.Method(type, "Set", (Type[])null, (Type[])null).Invoke(obj, new object[5]
			{
				"GAME OVER",
				Color.green,
				(object)new Vector2(10000f, 10000.7f),
				0.18f,
				1f
			});
			SpriteRenderer[] componentsInChildren = val.GetComponentsInChildren<SpriteRenderer>(true);
			SpriteRenderer[] array = componentsInChildren;
			foreach (SpriteRenderer val9 in array)
			{
				((Component)val9).gameObject.layer = 31;
			}
			Material[] array2 = componentsInChildren.Select((SpriteRenderer x) => ((Renderer)x).sharedMaterial).ToArray();
			Material val10 = new Material(Shader.Find("Sprites/Default"));
			SpriteRenderer[] array3 = componentsInChildren;
			foreach (SpriteRenderer val11 in array3)
			{
				((Renderer)val11).sharedMaterial = val10;
			}
			val6.Render();
			RenderTexture.active = val2;
			val3.ReadPixels(new Rect(0f, 0f, 640f, 256f), 0, 0);
			val3.Apply();
			int num2 = val3.GetPixels32().Count((Color32 p) => p.g > p.r + 50 && p.g > p.b + 50);
			File.WriteAllBytes(Path.Combine(outputFolder, "occlusion-before.png"), ImageConversion.EncodeToPNG(val3));
			for (int num3 = 0; num3 < componentsInChildren.Length; num3++)
			{
				((Renderer)componentsInChildren[num3]).sharedMaterial = array2[num3];
			}
			val6.Render();
			RenderTexture.active = val2;
			val3.ReadPixels(new Rect(0f, 0f, 640f, 256f), 0, 0);
			val3.Apply();
			int num4 = val3.GetPixels32().Count((Color32 p) => p.g > p.r + 50 && p.g > p.b + 50);
			File.WriteAllBytes(Path.Combine(outputFolder, "occlusion-after.png"), ImageConversion.EncodeToPNG(val3));
			Object.Destroy((Object)(object)val10);
			bool flag = num2 < 20 && num4 > 100;
			lines.Add((flag ? "PASS " : "FAIL ") + "HUD depth occlusion: visible text pixels before=" + num2 + ", after=" + num4 + "; obstacle shader=" + ((Object)val8).name);
			return (!flag) ? 1 : 0;
		}
		finally
		{
			RenderTexture.active = active;
			Object.Destroy((Object)(object)val);
			Object.Destroy((Object)(object)val3);
			val2.Release();
			Object.Destroy((Object)(object)val2);
			if ((Object)(object)val4 != (Object)null)
			{
				Object.Destroy((Object)(object)val4);
			}
		}
	}
}