Decompiled source of LocalizationPatcher v1.0.3

Aethelgard.LocalizationPatcher.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Aethelgard.LocalizationPatcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Dynamic translation fallback patcher for hardcoded mod strings")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+dd5fceaa2ed10d400056cd50fd7fe64c3015bff5")]
[assembly: AssemblyProduct("Aethelgard.LocalizationPatcher")]
[assembly: AssemblyTitle("Aethelgard.LocalizationPatcher")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 Aethelgard.LocalizationPatcher
{
	[BepInPlugin("net.gmloc.aethelgard.localizationpatcher", "Aethelgard Localization Patcher", "1.0.3")]
	public class LocalizationPatcherPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "net.gmloc.aethelgard.localizationpatcher";

		public const string PluginName = "Aethelgard Localization Patcher";

		public const string PluginVersion = "1.0.3";

		public static readonly Dictionary<string, string> ExactDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		public static readonly List<KeyValuePair<string, string>> PhraseReplacements = new List<KeyValuePair<string, string>>();

		private static readonly Regex JsonPairRegex = new Regex("\"((?:\\\\\"|[^\"])*)\"\\s*:\\s*\"((?:\\\\\"|[^\"])*)\"", RegexOptions.Compiled);

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			_harmony = new Harmony("net.gmloc.aethelgard.localizationpatcher");
			LoadLocalizations();
			Type type = AccessTools.TypeByName("UnityEngine.UI.Text");
			if (type != null)
			{
				MethodInfo methodInfo = AccessTools.PropertySetter(type, "text");
				MethodInfo methodInfo2 = AccessTools.Method(typeof(LocalizationPatcherPlugin), "Prefix_SetText", (Type[])null, (Type[])null);
				if (methodInfo != null && methodInfo2 != null)
				{
					_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			Type type2 = AccessTools.TypeByName("TMPro.TMP_Text");
			if (type2 != null)
			{
				MethodInfo methodInfo3 = AccessTools.PropertySetter(type2, "text");
				MethodInfo methodInfo4 = AccessTools.Method(typeof(LocalizationPatcherPlugin), "Prefix_SetText", (Type[])null, (Type[])null);
				if (methodInfo3 != null && methodInfo4 != null)
				{
					_harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			Type type3 = AccessTools.TypeByName("TextsDialog");
			if (type3 != null)
			{
				MethodInfo methodInfo5 = AccessTools.Method(type3, "AddText", (Type[])null, (Type[])null);
				MethodInfo methodInfo6 = AccessTools.Method(typeof(LocalizationPatcherPlugin), "Prefix_AddText", (Type[])null, (Type[])null);
				if (methodInfo5 != null && methodInfo6 != null)
				{
					_harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Aethelgard] Патчер 1.0.3 активен! Точных ключей: {ExactDictionary.Count}, фразовых шаблонов: {PhraseReplacements.Count}");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void LoadLocalizations()
		{
			try
			{
				string path = Path.Combine(Paths.ConfigPath, "Translation", "Russian");
				if (Directory.Exists(path))
				{
					string[] files = Directory.GetFiles(path, "*.json");
					for (int i = 0; i < files.Length; i++)
					{
						ParseJsonFile(File.ReadAllText(files[i]));
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("[Aethelgard] Ошибка загрузки словарей: " + ex.Message));
			}
		}

		private static void ParseJsonFile(string json)
		{
			foreach (Match item in JsonPairRegex.Matches(json))
			{
				string text = item.Groups[1].Value.Replace("\\\"", "\"").Replace("\\n", "\n").Trim();
				string value = item.Groups[2].Value.Replace("\\\"", "\"").Replace("\\n", "\n").Trim();
				if (!string.Equals(text, "language", StringComparison.OrdinalIgnoreCase) && !string.Equals(text, "words", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(value))
				{
					ExactDictionary[text] = value;
					if (text.Length > 5 && (text.Contains(" ") || text.Contains(":")))
					{
						PhraseReplacements.Add(new KeyValuePair<string, string>(text, value));
					}
				}
			}
			PhraseReplacements.Sort((KeyValuePair<string, string> a, KeyValuePair<string, string> b) => b.Key.Length.CompareTo(a.Key.Length));
		}

		public static void Prefix_AddText(ref string topic, ref string text)
		{
			if (!string.IsNullOrEmpty(topic))
			{
				topic = TranslateString(topic);
			}
			if (!string.IsNullOrEmpty(text))
			{
				text = TranslateString(text);
			}
		}

		public static void Prefix_SetText(ref string value)
		{
			if (!string.IsNullOrEmpty(value))
			{
				value = TranslateString(value);
			}
		}

		public static string TranslateString(string input)
		{
			string text = input.Trim();
			if (ExactDictionary.TryGetValue(text, out var value))
			{
				return value;
			}
			if (text.StartsWith("$") && ExactDictionary.TryGetValue(text.Substring(1), out var value2))
			{
				return value2;
			}
			if (input.Length > 15)
			{
				string text2 = input;
				bool flag = false;
				foreach (KeyValuePair<string, string> phraseReplacement in PhraseReplacements)
				{
					if (text2.Contains(phraseReplacement.Key))
					{
						text2 = text2.Replace(phraseReplacement.Key, phraseReplacement.Value);
						flag = true;
					}
				}
				if (flag)
				{
					return text2;
				}
			}
			return input;
		}
	}
}