Decompiled source of Translator v0.2.0

plugins/Translator/Translator.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Translator")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Translator")]
[assembly: AssemblyTitle("Translator")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[BepInPlugin("com.pickteam.translator", "ProjectGorgon Translator", "0.2.0")]
public class ModMain : BasePlugin
{
	internal static ManualLogSource Logger;

	internal static Harmony HarmonyInstance;

	internal static string ModFolder;

	internal static ConfigEntry<string> LanguageConfig;

	internal static ConfigEntry<bool> EnableTranslationTools;

	internal static ConfigEntry<bool> EnableDebugMenu;

	public override void Load()
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Expected O, but got Unknown
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Expected O, but got Unknown
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Expected O, but got Unknown
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Expected O, but got Unknown
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		Logger = ((BasePlugin)this).Log;
		ModFolder = Path.GetDirectoryName(((object)this).GetType().Assembly.Location);
		LanguageConfig = ((BasePlugin)this).Config.Bind<string>("General", "Language", "ru", "Translation language code. Translations are loaded from translations/<Language>/ folder (e.g. ru, de, fr).");
		EnableTranslationTools = ((BasePlugin)this).Config.Bind<bool>("DevTools", "EnableTranslationTools", false, "Enable F10 (reload translations) and F11 (export untranslated) hotkeys.");
		EnableDebugMenu = ((BasePlugin)this).Config.Bind<bool>("DevTools", "EnableDebugMenu", false, "Enable F7 scene debugger overlay.");
		ManualLogSource log = ((BasePlugin)this).Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(50, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("=== ProjectGorgon Translator v0.2.0 === Language: ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(LanguageConfig.Value);
		}
		log.LogInfo(val);
		TranslationDictionary.Load(ModFolder, LanguageConfig.Value);
		ManualLogSource log2 = ((BasePlugin)this).Log;
		val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(TranslationDictionary.Count);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" translations.");
		}
		log2.LogInfo(val);
		HarmonyInstance = new Harmony("com.pickteam.russifier");
		HarmonyInstance.PatchAll();
		((BasePlugin)this).Log.LogInfo((object)"Harmony patches applied.");
		ClassInjector.RegisterTypeInIl2Cpp<SceneDebugger>();
		ClassInjector.RegisterTypeInIl2Cpp<SceneDumper>();
		GameObject val2 = new GameObject("Tranlator_Components");
		Object.DontDestroyOnLoad((Object)val2);
		((Object)val2).hideFlags = (HideFlags)61;
		val2.AddComponent<SceneDebugger>();
		val2.AddComponent<SceneDumper>();
	}
}
[HarmonyPatch(typeof(UIInventoryController), "IsItemInSearch")]
public static class Patch_InventorySearch
{
	public static void Postfix(UIInventoryController __instance, Item item, ref bool __result)
	{
		if (__result)
		{
			return;
		}
		string value = Traverse.Create((object)__instance).Field("lastItemSearchTerm").GetValue<string>();
		if (!string.IsNullOrEmpty(value))
		{
			string name = item.Name;
			if (!string.IsNullOrEmpty(name) && TranslationDictionary.TryTranslate(name, out var russian) && !string.IsNullOrEmpty(russian) && russian.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				__result = true;
			}
		}
	}
}
[HarmonyPatch(typeof(UIInteractionController), "ShowTalk")]
public static class Patch_ShowTalk
{
	public static void Prefix(ref string __1, ref string __2, ref string __3, Il2CppStringArray __5)
	{
		if (TranslationDictionary.TryTranslate(__1, out var russian))
		{
			__1 = russian;
		}
		if (TranslationDictionary.TryTranslate(__2, out var russian2))
		{
			__2 = russian2;
		}
		if (TranslationDictionary.TryTranslate(__3, out var russian3))
		{
			__3 = russian3;
		}
		if (__5 == null)
		{
			return;
		}
		for (int i = 0; i < ((Il2CppArrayBase<string>)(object)__5).Length; i++)
		{
			if (TranslationDictionary.TryTranslate(((Il2CppArrayBase<string>)(object)__5)[i], out var russian4))
			{
				((Il2CppArrayBase<string>)(object)__5)[i] = russian4;
			}
		}
	}
}
[HarmonyPatch(typeof(TMP_Text), "SetText", new Type[] { typeof(string) })]
public static class Patch_TMP_SetText_String
{
	public static void Prefix(ref string sourceText)
	{
		if (!string.IsNullOrEmpty(sourceText) && TranslationDictionary.TryTranslate(sourceText, out var russian))
		{
			sourceText = russian;
		}
	}
}
[HarmonyPatch(typeof(TMP_Text), "set_text")]
public static class Patch_TMP_Text_SetText
{
	[ThreadStatic]
	private static bool _translating;

	private static readonly Dictionary<int, float> _autoSizedInstances = new Dictionary<int, float>();

	private static readonly HashSet<int> _fittedContainers = new HashSet<int>();

	private static ManualLogSource Log => ModMain.Logger;

	public static void Prefix(TMP_Text __instance, ref string value)
	{
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Expected O, but got Unknown
		if (_translating || string.IsNullOrEmpty(value))
		{
			return;
		}
		_translating = true;
		try
		{
			int instanceID = ((Object)__instance).GetInstanceID();
			if (_autoSizedInstances.TryGetValue(instanceID, out var value2))
			{
				try
				{
					__instance.enableAutoSizing = false;
					__instance.fontSize = value2;
					__instance.textWrappingMode = (TextWrappingModes)1;
				}
				catch
				{
				}
				_autoSizedInstances.Remove(instanceID);
			}
			if (!TranslationDictionary.TryTranslate(value, out var russian))
			{
				return;
			}
			string text = value;
			value = russian;
			if (!((float)russian.Length > (float)text.Length * 1.3f) || russian.Contains('\n'))
			{
				return;
			}
			try
			{
				if (IsInsideTooltip(__instance.transform))
				{
					return;
				}
				if (IsInRigidLayout(__instance.transform))
				{
					if (!__instance.enableAutoSizing)
					{
						float num = __instance.fontSize;
						if (num <= 0f)
						{
							num = __instance.fontSizeMax;
						}
						if (num <= 0f)
						{
							num = 24f;
						}
						__instance.enableAutoSizing = true;
						__instance.fontSizeMin = Math.Max(num * 0.45f, 5f);
						__instance.fontSizeMax = num;
						__instance.textWrappingMode = (TextWrappingModes)0;
						_autoSizedInstances[instanceID] = num;
					}
				}
				else
				{
					TryExpandContainer(__instance);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Resize] Error: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val);
			}
		}
		finally
		{
			_translating = false;
		}
	}

	private static void TryExpandContainer(TMP_Text text)
	{
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = null;
		Transform val2 = text.transform;
		int num = 0;
		while (num < 3 && (Object)(object)val2 != (Object)null)
		{
			if ((Object)(object)((Component)val2).GetComponent<Button>() != (Object)null || (Object)(object)((Component)val2).GetComponent<Toggle>() != (Object)null)
			{
				val = (RectTransform)(object)((val2 is RectTransform) ? val2 : null);
				break;
			}
			num++;
			val2 = val2.parent;
		}
		if ((Object)(object)val == (Object)null)
		{
			Transform parent = text.transform.parent;
			val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		}
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		int instanceID = ((Object)val).GetInstanceID();
		if (!_fittedContainers.Contains(instanceID) && !((Object)(object)((Component)val).GetComponent<ContentSizeFitter>() != (Object)null))
		{
			ContentSizeFitter obj = ((Component)val).gameObject.AddComponent<ContentSizeFitter>();
			obj.horizontalFit = (FitMode)2;
			obj.verticalFit = (FitMode)0;
			if ((Object)(object)((Component)val).GetComponent<LayoutElement>() == (Object)null)
			{
				LayoutElement obj2 = ((Component)val).gameObject.AddComponent<LayoutElement>();
				Rect rect = val.rect;
				obj2.minWidth = ((Rect)(ref rect)).width;
			}
			_fittedContainers.Add(instanceID);
		}
	}

	private static bool IsInRigidLayout(Transform start)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Transform val = start;
			int num = 0;
			while (num < 4 && (Object)(object)val != (Object)null)
			{
				if ((Object)(object)((Component)val).GetComponent<HorizontalLayoutGroup>() != (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)val).GetComponent<GridLayoutGroup>() != (Object)null)
				{
					return true;
				}
				ContentSizeFitter component = ((Component)val).GetComponent<ContentSizeFitter>();
				if ((Object)(object)component != (Object)null && (int)component.horizontalFit != 0)
				{
					RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null);
					if (!((Object)(object)val2 != (Object)null) || !_fittedContainers.Contains(((Object)val2).GetInstanceID()))
					{
						return true;
					}
				}
				num++;
				val = val.parent;
			}
		}
		catch
		{
		}
		return false;
	}

	private static bool IsInsideTooltip(Transform start)
	{
		try
		{
			Transform val = start;
			int num = 0;
			while (num < 6 && (Object)(object)val != (Object)null)
			{
				if ((Object)(object)((Component)val).GetComponent<UIItemTooltip>() != (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)val).GetComponent<UIAbilityTooltip>() != (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)val).GetComponent<UIRecipeTooltip>() != (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)val).GetComponent<UITooltip>() != (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)val).GetComponent<UIContextMenu>() != (Object)null)
				{
					return true;
				}
				num++;
				val = val.parent;
			}
		}
		catch
		{
		}
		return false;
	}
}
[HarmonyPatch]
public static class Patch_UITools_SetText
{
	[CompilerGenerated]
	private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IEnumerator, IDisposable
	{
		private int <>1__state;

		private MethodBase <>2__current;

		private int <>l__initialThreadId;

		private MethodInfo[] <>7__wrap1;

		private int <>7__wrap2;

		MethodBase IEnumerator<MethodBase>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <TargetMethods>d__0(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>7__wrap1 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				goto IL_00c9;
			}
			<>1__state = -1;
			Type typeFromHandle = typeof(UITools);
			<>7__wrap1 = typeFromHandle.GetMethods(BindingFlags.Static | BindingFlags.Public);
			<>7__wrap2 = 0;
			goto IL_00d7;
			IL_00c9:
			<>7__wrap2++;
			goto IL_00d7;
			IL_00d7:
			if (<>7__wrap2 < <>7__wrap1.Length)
			{
				MethodInfo methodInfo = <>7__wrap1[<>7__wrap2];
				if (methodInfo.Name == "SetText" && methodInfo.GetParameters().Length == 2)
				{
					ManualLogSource logger = ModMain.Logger;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(28, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("  Patching UITools.SetText(");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(methodInfo.GetParameters()[1].ParameterType.Name);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
					}
					logger.LogInfo(val);
					<>2__current = methodInfo;
					<>1__state = 1;
					return true;
				}
				goto IL_00c9;
			}
			<>7__wrap1 = null;
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}

		[DebuggerHidden]
		IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
		{
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				return this;
			}
			return new <TargetMethods>d__0(0);
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<MethodBase>)this).GetEnumerator();
		}
	}

	[IteratorStateMachine(typeof(<TargetMethods>d__0))]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <TargetMethods>d__0(-2);
	}

	public static void Prefix(ref string __1)
	{
		if (TranslationDictionary.TryTranslate(__1, out var russian))
		{
			__1 = russian;
		}
	}
}
[HarmonyPatch(typeof(Text), "set_text")]
public static class Patch_UI_Text_SetText
{
	[ThreadStatic]
	private static bool _translating;

	public static void Prefix(ref string value)
	{
		if (_translating || string.IsNullOrEmpty(value))
		{
			return;
		}
		_translating = true;
		try
		{
			if (TranslationDictionary.TryTranslate(value, out var russian))
			{
				value = russian;
			}
		}
		finally
		{
			_translating = false;
		}
	}
}
public class SceneDebugger : MonoBehaviour
{
	private bool _visible;

	private Rect _windowRect = new Rect(20f, 20f, 900f, 600f);

	private Vector2 _treeScroll;

	private Vector2 _inspScroll;

	private GameObject _selected;

	private readonly HashSet<int> _expanded = new HashSet<int>();

	private string _search = "";

	private float _splitX = 400f;

	private float _scanTimer;

	private const float ScanInterval = 3f;

	private int _lastScanCount;

	private GUIStyle _boxStyle;

	private GUIStyle _btnStyle;

	private GUIStyle _lblStyle;

	private GUIStyle _fieldStyle;

	private bool _stylesReady;

	public SceneDebugger(IntPtr ptr)
		: base(ptr)
	{
	}//IL_0015: 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)


	private void InitStyles()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_0042: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		if (!_stylesReady)
		{
			_boxStyle = new GUIStyle(GUI.skin.box);
			_btnStyle = new GUIStyle(GUI.skin.button)
			{
				alignment = (TextAnchor)3,
				fontSize = 12
			};
			_lblStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 12
			};
			_fieldStyle = new GUIStyle(GUI.skin.textField)
			{
				fontSize = 12
			};
			_stylesReady = true;
		}
	}

	private void Update()
	{
		if (ModMain.EnableDebugMenu.Value && Input.GetKeyDown((KeyCode)288))
		{
			_visible = !_visible;
		}
		if (ModMain.EnableTranslationTools.Value && Input.GetKeyDown((KeyCode)291))
		{
			TranslationDictionary.Reload();
			ScanAndTranslateScene();
			ModMain.Logger.LogInfo((object)"Translations reloaded + scene scanned (F10).");
		}
		if (ModMain.EnableTranslationTools.Value && Input.GetKeyDown((KeyCode)292))
		{
			ScanAndTranslateScene();
			TranslationDictionary.ExportUntranslated();
			ModMain.Logger.LogInfo((object)"Scene scanned + untranslated exported (F11).");
		}
		_scanTimer += Time.deltaTime;
		if (_scanTimer >= 3f)
		{
			_scanTimer = 0f;
			ScanAndTranslateScene();
		}
	}

	private void ScanAndTranslateScene()
	{
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Expected O, but got Unknown
		int num = 0;
		bool flag = default(bool);
		try
		{
			Il2CppArrayBase<TMP_Text> val = Resources.FindObjectsOfTypeAll<TMP_Text>();
			if (val != null)
			{
				foreach (TMP_Text item in val)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					try
					{
						string text = item.text;
						if (!string.IsNullOrEmpty(text) && TranslationDictionary.TryTranslate(text, out var russian))
						{
							item.text = russian;
							num++;
						}
					}
					catch
					{
					}
				}
			}
			Il2CppArrayBase<Text> val2 = Resources.FindObjectsOfTypeAll<Text>();
			if (val2 != null)
			{
				foreach (Text item2 in val2)
				{
					if ((Object)(object)item2 == (Object)null)
					{
						continue;
					}
					try
					{
						string text2 = item2.text;
						if (!string.IsNullOrEmpty(text2) && TranslationDictionary.TryTranslate(text2, out var russian2))
						{
							item2.text = russian2;
							num++;
						}
					}
					catch
					{
					}
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource logger = ModMain.Logger;
			BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(19, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[SceneScan] Error: ");
				((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
			}
			logger.LogWarning(val3);
		}
		if (num != _lastScanCount)
		{
			ManualLogSource logger2 = ModMain.Logger;
			BepInExDebugLogInterpolatedStringHandler val4 = new BepInExDebugLogInterpolatedStringHandler(42, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[SceneScan] Translated ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" prefab-baked texts");
			}
			logger2.LogDebug(val4);
			_lastScanCount = num;
		}
	}

	private void OnGUI()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if (_visible)
		{
			InitStyles();
			_windowRect = GUI.Window(7777, _windowRect, WindowFunction.op_Implicit((Action<int>)DrawWindow), "Scene Debugger (F7)");
		}
	}

	private void DrawWindow(int id)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0311: Unknown result type (might be due to invalid IL or missing references)
		float num = 20f;
		float width = ((Rect)(ref _windowRect)).width;
		float height = ((Rect)(ref _windowRect)).height;
		GUI.Label(new Rect(5f, num, 55f, 20f), "Search:", _lblStyle);
		_search = GUI.TextField(new Rect(60f, num, width - 75f, 20f), _search, _fieldStyle);
		num += 25f;
		string text = $"Translations: {TranslationDictionary.Count} loaded, {TranslationDictionary.UntranslatedCount} untranslated | F10=Reload F11=Export";
		GUI.Label(new Rect(5f, num, width - 10f, 18f), text, _lblStyle);
		num += 22f;
		float num2 = num;
		float num3 = height - num2 - 5f;
		GUI.Box(new Rect(0f, num2, _splitX, num3), "", _boxStyle);
		float y = 0f;
		Scene activeScene = SceneManager.GetActiveScene();
		Il2CppReferenceArray<GameObject> rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
		float num4 = 0f;
		foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)rootGameObjects)
		{
			if ((Object)(object)item != (Object)null)
			{
				num4 += EstimateNodeHeight(item, 0);
			}
		}
		num4 = Mathf.Max(num4, 100f);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(0f, 0f, _splitX - 20f, num4);
		_treeScroll = GUI.BeginScrollView(new Rect(0f, num2, _splitX, num3), _treeScroll, val);
		foreach (GameObject item2 in (Il2CppArrayBase<GameObject>)(object)rootGameObjects)
		{
			y = DrawNode(item2, 0, y, _splitX - 20f);
		}
		GUI.EndScrollView();
		GUI.Box(new Rect(_splitX, num2, width - _splitX, num3), "", _boxStyle);
		if ((Object)(object)_selected != (Object)null)
		{
			float y2 = 0f;
			float num5 = width - _splitX - 20f;
			float num6 = EstimateInspectorHeight(_selected, num5);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(0f, 0f, num5, num6);
			_inspScroll = GUI.BeginScrollView(new Rect(_splitX, num2, width - _splitX, num3), _inspScroll, val2);
			y2 = DrawInspector(_selected, num5, y2);
			GUI.EndScrollView();
		}
		else
		{
			GUI.Label(new Rect(_splitX + 10f, num2 + 10f, 200f, 20f), "Select an object", _lblStyle);
		}
		GUI.DragWindow(new Rect(0f, 0f, width, 20f));
	}

	private float DrawNode(GameObject go, int depth, float y, float maxW)
	{
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: 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_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)go == (Object)null)
		{
			return y;
		}
		string name = ((Object)go).name;
		if (!string.IsNullOrEmpty(_search) && !name.ToLower().Contains(_search.ToLower()))
		{
			bool flag = false;
			for (int i = 0; i < go.transform.childCount; i++)
			{
				Transform child = go.transform.GetChild(i);
				if ((Object)(object)child != (Object)null && MatchesSearch(((Component)child).gameObject))
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return y;
			}
		}
		int instanceID = ((Object)go).GetInstanceID();
		bool flag2 = go.transform.childCount > 0;
		bool flag3 = _expanded.Contains(instanceID);
		float num = depth * 18;
		if (flag2)
		{
			string text = (flag3 ? "v" : ">");
			if (GUI.Button(new Rect(num, y, 18f, 18f), text, _btnStyle))
			{
				if (flag3)
				{
					_expanded.Remove(instanceID);
				}
				else
				{
					_expanded.Add(instanceID);
				}
			}
		}
		string text2 = (go.activeInHierarchy ? name : ("[" + name + "]"));
		bool num2 = (Object)(object)_selected == (Object)(object)go;
		Color color = GUI.color;
		if (num2)
		{
			GUI.color = Color.cyan;
		}
		if (GUI.Button(new Rect(num + 20f, y, maxW - num - 25f, 18f), text2, _btnStyle))
		{
			_selected = go;
		}
		GUI.color = color;
		y += 20f;
		if (flag3 && flag2)
		{
			for (int j = 0; j < go.transform.childCount; j++)
			{
				Transform child2 = go.transform.GetChild(j);
				if ((Object)(object)child2 != (Object)null)
				{
					y = DrawNode(((Component)child2).gameObject, depth + 1, y, maxW);
				}
			}
		}
		return y;
	}

	private bool MatchesSearch(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return false;
		}
		if (((Object)go).name.ToLower().Contains(_search.ToLower()))
		{
			return true;
		}
		for (int i = 0; i < go.transform.childCount; i++)
		{
			Transform child = go.transform.GetChild(i);
			if ((Object)(object)child != (Object)null && MatchesSearch(((Component)child).gameObject))
			{
				return true;
			}
		}
		return false;
	}

	private float DrawInspector(GameObject go, float w, float y)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		GUI.Label(new Rect(5f, y, w, 22f), "<b>" + ((Object)go).name + "</b>", _lblStyle);
		y += 22f;
		GUI.Label(new Rect(5f, y, w, 18f), $"Active: {go.activeSelf}  Layer: {go.layer}  Tag: {go.tag}", _lblStyle);
		y += 20f;
		GUI.Label(new Rect(5f, y, w, 18f), $"Position: {go.transform.position}", _lblStyle);
		y += 20f;
		foreach (Component component in go.GetComponents<Component>())
		{
			if ((Object)(object)component == (Object)null)
			{
				continue;
			}
			string name = ((MemberInfo)((Object)component).GetIl2CppType()).Name;
			y += 5f;
			GUI.Label(new Rect(5f, y, w, 20f), "── " + name + " ──", _lblStyle);
			y += 20f;
			Text val = ((Il2CppObjectBase)component).TryCast<Text>();
			if (val != null)
			{
				GUI.Label(new Rect(15f, y, w - 20f, 18f), "text: " + Truncate(val.text, 120), _lblStyle);
				y += 20f;
				continue;
			}
			TextMeshProUGUI val2 = ((Il2CppObjectBase)component).TryCast<TextMeshProUGUI>();
			if (val2 != null)
			{
				GUI.Label(new Rect(15f, y, w - 20f, 18f), "text: " + Truncate(((TMP_Text)val2).text, 120), _lblStyle);
				y += 20f;
			}
		}
		return y;
	}

	private float EstimateNodeHeight(GameObject go, int depth)
	{
		float num = 20f;
		if (_expanded.Contains(((Object)go).GetInstanceID()))
		{
			for (int i = 0; i < go.transform.childCount; i++)
			{
				Transform child = go.transform.GetChild(i);
				if ((Object)(object)child != (Object)null)
				{
					num += EstimateNodeHeight(((Component)child).gameObject, depth + 1);
				}
			}
		}
		return num;
	}

	private float EstimateInspectorHeight(GameObject go, float w)
	{
		float num = 62f;
		foreach (Component component in go.GetComponents<Component>())
		{
			if (!((Object)(object)component == (Object)null))
			{
				num += 25f;
				if ((Object)(object)((Il2CppObjectBase)component).TryCast<Text>() != (Object)null || (Object)(object)((Il2CppObjectBase)component).TryCast<TextMeshProUGUI>() != (Object)null)
				{
					num += 20f;
				}
			}
		}
		return Mathf.Max(num, 100f);
	}

	private string Truncate(string s, int max)
	{
		if (string.IsNullOrEmpty(s))
		{
			return "<empty>";
		}
		s = s.Replace("\n", "\\n").Replace("\r", "");
		if (s.Length <= max)
		{
			return s;
		}
		return s.Substring(0, max) + "...";
	}
}
public class SceneDumper : MonoBehaviour
{
	public SceneDumper(IntPtr ptr)
		: base(ptr)
	{
	}

	private void Update()
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		if (!Input.GetKeyDown((KeyCode)290))
		{
			return;
		}
		Scene activeScene = SceneManager.GetActiveScene();
		ManualLogSource logger = ModMain.Logger;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("=== Scene Dump: ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Scene)(ref activeScene)).name);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ===");
		}
		logger.LogInfo(val);
		foreach (GameObject item in (Il2CppArrayBase<GameObject>)(object)((Scene)(ref activeScene)).GetRootGameObjects())
		{
			DumpObject(item, 0);
		}
		ModMain.Logger.LogInfo((object)"=== End Scene Dump ===");
	}

	private void DumpObject(GameObject go, int depth)
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Expected O, but got Unknown
		if ((Object)(object)go == (Object)null)
		{
			return;
		}
		string text = new string(' ', depth * 2);
		string text2 = (go.activeInHierarchy ? "" : " [inactive]");
		Il2CppArrayBase<Component> components = go.GetComponents<Component>();
		StringBuilder stringBuilder = new StringBuilder();
		foreach (Component item in components)
		{
			if (!((Object)(object)item == (Object)null))
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(", ");
				}
				stringBuilder.Append(((MemberInfo)((Object)item).GetIl2CppType()).Name);
			}
		}
		ManualLogSource logger = ModMain.Logger;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(3, 4, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)go).name);
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<StringBuilder>(stringBuilder);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
		}
		logger.LogInfo(val);
		for (int i = 0; i < go.transform.childCount; i++)
		{
			Transform child = go.transform.GetChild(i);
			if ((Object)(object)child != (Object)null)
			{
				DumpObject(((Component)child).gameObject, depth + 1);
			}
		}
	}
}
public static class TranslationDictionary
{
	private static readonly Dictionary<string, string> _dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

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

	private static readonly List<(Regex pattern, string replacement, Dictionary<string, string> keys)> _regexRules = new List<(Regex, string, Dictionary<string, string>)>();

	private static readonly Regex _trailingCounter = new Regex("(\\s+\\(?\\d+/\\d+\\)?)$", RegexOptions.Compiled);

	private static readonly List<(string english, string russian)> _prefixes = new List<(string, string)>();

	private static readonly List<(string english, string russian)> _suffixes = new List<(string, string)>();

	private static readonly HashSet<string> _untranslated = new HashSet<string>(StringComparer.Ordinal);

	private static string _modFolder;

	private static string _language = "ru";

	private static readonly Regex _junkPattern = new Regex("^(\\d+([/,.]\\d+)*|[A-Za-z]|(Ctrl|Shift|Alt|Numpad|C|S)\\+.+|F\\d{1,2}|(Left|Right|Up|Down) (Arrow|Shift)|(Left Shift|Right Shift|Numlock|Numpad [+\\-])|Space|Tab|Escape|Backspace|(Mouse Button \\d+)|`|.*<sprite=.*|<b>x \\d+</b>.*|\\n<em>Cause of death.*|.*<color=#FFCC00>Poetry Jam.*|\\d+\\s*<sprite=.*|(None)|/|Welcome, .+!|\\d+[.,]\\d+ FPS)$", RegexOptions.Compiled | RegexOptions.Singleline);

	public static int Count => _dict.Count;

	public static int UntranslatedCount => _untranslated.Count;

	public static string Language => _language;

	public static void Load(string modFolder, string language = null)
	{
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Expected O, but got Unknown
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Expected O, but got Unknown
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Expected O, but got Unknown
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Expected O, but got Unknown
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Expected O, but got Unknown
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Expected O, but got Unknown
		_modFolder = modFolder;
		if (!string.IsNullOrEmpty(language))
		{
			_language = language;
		}
		_dict.Clear();
		_exactDict.Clear();
		_regexRules.Clear();
		_prefixes.Clear();
		_suffixes.Clear();
		_untranslated.Clear();
		string text = Path.Combine(modFolder, "translations", _language);
		bool flag = default(bool);
		if (!Directory.Exists(text))
		{
			Directory.CreateDirectory(text);
			ManualLogSource logger = ModMain.Logger;
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(29, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Created translations folder: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
			}
			logger.LogWarning(val);
			return;
		}
		string[] files = Directory.GetFiles(text, "*.yaml");
		foreach (string text2 in files)
		{
			if (text2.EndsWith(".regex.yaml", StringComparison.OrdinalIgnoreCase) || text2.EndsWith(".keys.yaml", StringComparison.OrdinalIgnoreCase))
			{
				continue;
			}
			try
			{
				LoadYamlFile(text2);
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = ModMain.Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(16, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error loading ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Path.GetFileName(text2));
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				logger2.LogError(val2);
			}
		}
		files = Directory.GetFiles(text, "*.yml");
		foreach (string path in files)
		{
			try
			{
				LoadYamlFile(path);
			}
			catch (Exception ex2)
			{
				ManualLogSource logger3 = ModMain.Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(16, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error loading ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Path.GetFileName(path));
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
				}
				logger3.LogError(val2);
			}
		}
		files = Directory.GetFiles(text, "*.regex.yaml");
		foreach (string text3 in files)
		{
			try
			{
				string path2 = text3.Replace(".regex.yaml", ".keys.yaml");
				Dictionary<string, string> regexKeys = null;
				if (File.Exists(path2))
				{
					regexKeys = LoadKeysFile(path2);
				}
				LoadYamlFile(text3, regexMode: true, regexKeys);
			}
			catch (Exception ex3)
			{
				ManualLogSource logger4 = ModMain.Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(16, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error loading ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Path.GetFileName(text3));
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex3.Message);
				}
				logger4.LogError(val2);
			}
		}
		string path3 = Path.Combine(text, "prefixes.yaml");
		if (File.Exists(path3))
		{
			try
			{
				LoadAffixFile(path3, _prefixes);
			}
			catch (Exception ex4)
			{
				ManualLogSource logger5 = ModMain.Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(29, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error loading prefixes.yaml: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex4.Message);
				}
				logger5.LogError(val2);
			}
		}
		string path4 = Path.Combine(text, "postfixes.yaml");
		if (!File.Exists(path4))
		{
			return;
		}
		try
		{
			LoadAffixFile(path4, _suffixes);
		}
		catch (Exception ex5)
		{
			ManualLogSource logger6 = ModMain.Logger;
			BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error loading postfixes.yaml: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex5.Message);
			}
			logger6.LogError(val2);
		}
	}

	public static void Reload()
	{
		if (_modFolder != null)
		{
			Load(_modFolder, _language);
		}
	}

	public static bool TryTranslate(string english, out string russian)
	{
		if (string.IsNullOrEmpty(english))
		{
			russian = english;
			return false;
		}
		if (_exactDict.TryGetValue(english, out russian))
		{
			return true;
		}
		if (_dict.TryGetValue(english.Trim(), out russian))
		{
			return true;
		}
		Match match = _trailingCounter.Match(english);
		if (match.Success)
		{
			string text = english.Substring(0, match.Index);
			if (_exactDict.TryGetValue(text, out russian) || _dict.TryGetValue(text.Trim(), out russian))
			{
				russian += match.Value;
				return true;
			}
		}
		if (_prefixes.Count > 0 || _suffixes.Count > 0)
		{
			string text2 = english;
			string text3 = null;
			string text4 = null;
			string text5 = null;
			string text6 = null;
			for (int i = 0; i < _prefixes.Count; i++)
			{
				if (text2.StartsWith(_prefixes[i].english, StringComparison.OrdinalIgnoreCase))
				{
					text3 = _prefixes[i].english;
					text4 = _prefixes[i].russian;
					text2 = text2.Substring(_prefixes[i].english.Length);
					break;
				}
			}
			for (int j = 0; j < _suffixes.Count; j++)
			{
				if (text2.EndsWith(_suffixes[j].english, StringComparison.OrdinalIgnoreCase))
				{
					text5 = _suffixes[j].english;
					text6 = _suffixes[j].russian;
					text2 = text2.Substring(0, text2.Length - _suffixes[j].english.Length);
					break;
				}
			}
			if ((text4 != null || text6 != null) && text2.Length > 0)
			{
				string value = null;
				if ((_exactDict.TryGetValue(text2, out value) || _dict.TryGetValue(text2.Trim(), out value)) && !string.IsNullOrEmpty(value))
				{
					russian = AssembleAffixed(text4, value, text6);
					return true;
				}
				if (text4 != null && text6 != null && text3 != null)
				{
					string text7 = text3 + text2;
					if ((_exactDict.TryGetValue(text7, out value) || _dict.TryGetValue(text7.Trim(), out value)) && !string.IsNullOrEmpty(value))
					{
						russian = value + text6;
						return true;
					}
				}
				if (text4 != null && text6 != null && text5 != null)
				{
					string text8 = text2 + text5;
					if ((_exactDict.TryGetValue(text8, out value) || _dict.TryGetValue(text8.Trim(), out value)) && !string.IsNullOrEmpty(value))
					{
						russian = AssembleAffixed(text4, value, null);
						return true;
					}
				}
			}
		}
		for (int k = 0; k < _regexRules.Count; k++)
		{
			(Regex pattern, string replacement, Dictionary<string, string> keys) tuple = _regexRules[k];
			Regex item = tuple.pattern;
			string item2 = tuple.replacement;
			Dictionary<string, string> item3 = tuple.keys;
			Match match2 = item.Match(english);
			if (!match2.Success)
			{
				continue;
			}
			if (item3 != null && item3.Count > 0)
			{
				russian = item2;
				for (int num = match2.Groups.Count - 1; num >= 1; num--)
				{
					string value2 = match2.Groups[num].Value;
					if (!item3.TryGetValue(value2, out var value3))
					{
						value3 = value2;
					}
					russian = russian.Replace($"${num}", value3);
				}
			}
			else
			{
				russian = match2.Result(item2);
			}
			return true;
		}
		if (!IsJunk(english))
		{
			_untranslated.Add(english);
		}
		russian = null;
		return false;
	}

	private static string AssembleAffixed(string prefixRu, string baseRu, string suffixRu)
	{
		if (!string.IsNullOrEmpty(prefixRu) && prefixRu.EndsWith(" "))
		{
			return prefixRu + char.ToLower(baseRu[0]) + baseRu.Substring(1, baseRu.Length - 1) + suffixRu;
		}
		if (!string.IsNullOrEmpty(prefixRu) && prefixRu.StartsWith(" "))
		{
			return baseRu + suffixRu + prefixRu;
		}
		return prefixRu + baseRu + suffixRu;
	}

	public static string Translate(string english)
	{
		if (TryTranslate(english, out var russian))
		{
			return russian;
		}
		return english;
	}

	public static string Translate(string english, string context)
	{
		string key = context + ":" + english;
		if (_exactDict.TryGetValue(key, out var value))
		{
			return value;
		}
		return Translate(english);
	}

	public static void ExportUntranslated()
	{
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Expected O, but got Unknown
		if (_modFolder == null)
		{
			return;
		}
		string path = Path.Combine(_modFolder, "translations", _language, "_untranslated.yaml");
		List<string> list = new List<string>(_untranslated);
		list.Sort(StringComparer.OrdinalIgnoreCase);
		using StreamWriter streamWriter = new StreamWriter(path, append: false, Encoding.UTF8);
		streamWriter.WriteLine($"# Непереведённые строки ({list.Count}) — {DateTime.Now:yyyy-MM-dd HH:mm}");
		streamWriter.WriteLine("# Добавьте перевод после двоеточия и перенесите в нужный .yaml файл");
		streamWriter.WriteLine();
		foreach (string item in list)
		{
			string text = (YamlNeedsQuoting(item) ? ("\"" + YamlEscape(item) + "\"") : item);
			streamWriter.WriteLine(text + ": ");
		}
		ManualLogSource logger = ModMain.Logger;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Exported ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" untranslated strings to _untranslated.yaml");
		}
		logger.LogInfo(val);
	}

	private static bool IsJunk(string s)
	{
		if (s.Length <= 2)
		{
			return true;
		}
		if (!Regex.IsMatch(s, "[a-z]", RegexOptions.IgnoreCase))
		{
			return true;
		}
		if (ContainsCyrillic(s))
		{
			return true;
		}
		return _junkPattern.IsMatch(s.Trim());
	}

	private static bool ContainsCyrillic(string s)
	{
		for (int i = 0; i < s.Length; i++)
		{
			if (s[i] >= 'Ѐ' && s[i] <= 'ӿ')
			{
				return true;
			}
		}
		return false;
	}

	private static void LoadYamlFile(string path, bool regexMode = false, Dictionary<string, string> regexKeys = null)
	{
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Expected O, but got Unknown
		//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Expected O, but got Unknown
		string text = File.ReadAllText(path, Encoding.UTF8);
		int num = 0;
		int i = 0;
		bool flag = default(bool);
		while (i < text.Length)
		{
			for (; i < text.Length && char.IsWhiteSpace(text[i]); i++)
			{
			}
			if (i >= text.Length)
			{
				break;
			}
			if (text[i] == '#')
			{
				for (; i < text.Length && text[i] != '\n'; i++)
				{
				}
				continue;
			}
			string text2;
			if (text[i] == '"')
			{
				int num2 = FindClosingQuote(text, i + 1);
				if (num2 < 0)
				{
					for (; i < text.Length && text[i] != '\n'; i++)
					{
					}
					continue;
				}
				text2 = YamlUnescape(text.Substring(i + 1, num2 - i - 1));
				i = num2 + 1;
			}
			else
			{
				int num3 = i;
				for (; i < text.Length && text[i] != ':' && text[i] != '\n' && text[i] != '\r'; i++)
				{
				}
				if (i >= text.Length || text[i] != ':')
				{
					for (; i < text.Length && text[i] != '\n'; i++)
					{
					}
					continue;
				}
				text2 = text.Substring(num3, i - num3).TrimEnd();
			}
			for (; i < text.Length && (text[i] == ' ' || text[i] == '\t'); i++)
			{
			}
			if (i >= text.Length || text[i] != ':')
			{
				for (; i < text.Length && text[i] != '\n'; i++)
				{
				}
				continue;
			}
			for (i++; i < text.Length && (text[i] == ' ' || text[i] == '\t'); i++)
			{
			}
			string text3;
			if (i < text.Length && text[i] == '"')
			{
				int num4 = FindClosingQuote(text, i + 1);
				if (num4 < 0)
				{
					for (; i < text.Length && text[i] != '\n'; i++)
					{
					}
					continue;
				}
				text3 = YamlUnescape(text.Substring(i + 1, num4 - i - 1));
				i = num4 + 1;
			}
			else if (i < text.Length && text[i] != '\n' && text[i] != '\r')
			{
				int num5 = i;
				for (; i < text.Length && text[i] != '\n' && text[i] != '\r'; i++)
				{
				}
				string text4 = text.Substring(num5, i - num5);
				int num6 = text4.IndexOf(" #");
				if (num6 >= 0)
				{
					text4 = text4.Substring(0, num6);
				}
				text3 = text4.TrimEnd();
			}
			else
			{
				text3 = null;
			}
			for (; i < text.Length && text[i] != '\n'; i++)
			{
			}
			if (i < text.Length)
			{
				i++;
			}
			if (string.IsNullOrEmpty(text2) || string.IsNullOrEmpty(text3))
			{
				continue;
			}
			if (regexMode)
			{
				string text5 = text2;
				if (text5.Length > 2 && text5[0] == '/' && text5[text5.Length - 1] == '/')
				{
					text5 = text5.Substring(1, text5.Length - 2);
				}
				try
				{
					Regex item = new Regex(text5, RegexOptions.Compiled | RegexOptions.Singleline);
					_regexRules.Add((item, text3, regexKeys));
					num++;
				}
				catch (Exception ex)
				{
					ManualLogSource logger = ModMain.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(16, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("  Bad regex '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogError(val);
				}
			}
			else
			{
				_exactDict[text2] = text3;
				_dict[text2.Trim()] = text3;
				num++;
			}
		}
		ManualLogSource logger2 = ModMain.Logger;
		BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(12, 2, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("  ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Path.GetFileName(path));
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
			((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
			((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" entries");
		}
		logger2.LogInfo(val2);
	}

	private static Dictionary<string, string> LoadKeysFile(string path)
	{
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Expected O, but got Unknown
		Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
		string[] array = File.ReadAllLines(path, Encoding.UTF8);
		int num = 0;
		string[] array2 = array;
		for (int i = 0; i < array2.Length; i++)
		{
			string text = array2[i].TrimStart();
			if (text.Length == 0 || text[0] == '#')
			{
				continue;
			}
			string text2;
			string value;
			if (text[0] == '"')
			{
				int num2 = FindClosingQuote(text, 1);
				if (num2 < 0)
				{
					continue;
				}
				text2 = YamlUnescape(text.Substring(1, num2 - 1));
				int num3 = text.IndexOf(':', num2 + 1);
				if (num3 < 0)
				{
					continue;
				}
				value = ParseYamlValue(text.Substring(num3 + 1));
			}
			else
			{
				int num4 = text.IndexOf(':');
				if (num4 < 0)
				{
					continue;
				}
				text2 = text.Substring(0, num4).TrimEnd();
				value = ParseYamlValue(text.Substring(num4 + 1));
			}
			if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(value))
			{
				dictionary[text2] = value;
				num++;
			}
		}
		ManualLogSource logger = ModMain.Logger;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(9, 2, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("  ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(path));
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" keys");
		}
		logger.LogInfo(val);
		return dictionary;
	}

	private static void LoadAffixFile(string path, List<(string english, string russian)> target)
	{
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Expected O, but got Unknown
		string[] array = File.ReadAllLines(path, Encoding.UTF8);
		int num = 0;
		string[] array2 = array;
		for (int i = 0; i < array2.Length; i++)
		{
			string text = array2[i].TrimStart();
			if (text.Length == 0 || text[0] == '#')
			{
				continue;
			}
			string text2;
			string text3;
			if (text[0] == '"')
			{
				int num2 = FindClosingQuote(text, 1);
				if (num2 < 0)
				{
					continue;
				}
				text2 = YamlUnescape(text.Substring(1, num2 - 1));
				int num3 = text.IndexOf(':', num2 + 1);
				if (num3 < 0)
				{
					continue;
				}
				text3 = ParseYamlValue(text.Substring(num3 + 1));
			}
			else
			{
				int num4 = text.IndexOf(':');
				if (num4 < 0)
				{
					continue;
				}
				text2 = text.Substring(0, num4).TrimEnd();
				text3 = ParseYamlValue(text.Substring(num4 + 1));
			}
			if (!string.IsNullOrEmpty(text2) && !string.IsNullOrEmpty(text3))
			{
				target.Add((text2, text3));
				num++;
			}
		}
		target.Sort(((string english, string russian) a, (string english, string russian) b) => b.english.Length.CompareTo(a.english.Length));
		ManualLogSource logger = ModMain.Logger;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 2, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("  ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(path));
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" affixes");
		}
		logger.LogInfo(val);
	}

	private static string ParseYamlValue(string raw)
	{
		string text = raw.TrimStart();
		if (text.Length > 0 && text[0] == '"')
		{
			int num = FindClosingQuote(text, 1);
			if (num >= 0)
			{
				return YamlUnescape(text.Substring(1, num - 1));
			}
		}
		int num2 = text.IndexOf(" #");
		if (num2 >= 0)
		{
			text = text.Substring(0, num2);
		}
		return text.TrimEnd();
	}

	private static int FindClosingQuote(string s, int startAfter)
	{
		for (int i = startAfter; i < s.Length; i++)
		{
			if (s[i] == '\\')
			{
				i++;
			}
			else if (s[i] == '"')
			{
				return i;
			}
		}
		return -1;
	}

	private static string YamlUnescape(string s)
	{
		return s.Replace("\\\"", "\"").Replace("\\\\", "\\").Replace("\\n", "\n")
			.Replace("\\t", "\t");
	}

	private static bool YamlNeedsQuoting(string s)
	{
		if (!s.Contains(':') && !s.Contains('#') && !s.Contains('"') && !s.Contains('\\') && !s.Contains('\n') && !s.Contains('\t') && !s.StartsWith(" "))
		{
			return s.EndsWith(" ");
		}
		return true;
	}

	private static string YamlEscape(string s)
	{
		return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n")
			.Replace("\t", "\\t");
	}
}