Decompiled source of TraducaoPTBR v1.0.1

TraducaoPTBR.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

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

[BepInPlugin("razaotium.traducaoptbr", "TraducaoPTBR", "1.0.1")]
public sealed class Plugin : BaseUnityPlugin
{
	internal static Plugin Instance;

	internal static ConfigEntry<bool> Enabled;

	private ConfigEntry<KeyboardShortcut> toggleShortcut;

	private static Dictionary<string, string> corrections;

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

	private static HashSet<string> absentOriginals = new HashSet<string>();

	private static MethodInfo addWord;

	private static FieldInfo translationsField;

	private static FieldInfo cacheField;

	private static FieldInfo localizationInstanceField;

	private float statusUntil;

	private string statusText;

	private void Awake()
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Geral", "Enabled", true, "Aplica as correções da tradução PT-BR (só age com o jogo em Português do Brasil).");
		toggleShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Geral", "Tecla para alternar", new KeyboardShortcut((KeyCode)116, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Liga ou desliga a tradução imediatamente durante o jogo. Padrão: Shift + T. Pode ser alterada no arquivo de configuração.");
		corrections = LoadCorrections();
		addWord = AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null);
		translationsField = AccessTools.Field(typeof(Localization), "m_translations");
		cacheField = AccessTools.Field(typeof(Localization), "m_cache");
		localizationInstanceField = AccessTools.Field(typeof(Localization), "m_instance");
		if (addWord == null || translationsField == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Campos de tradução do jogo não encontrados; tradução não será aplicada.");
			return;
		}
		new Harmony("razaotium.traducaoptbr").PatchAll(Assembly.GetExecutingAssembly());
		((BaseUnityPlugin)this).Logger.LogInfo((object)(corrections.Count + " correções carregadas. Alternância: " + toggleShortcut.Value));
		Localization val = (Localization)((localizationInstanceField == null) ? null : /*isinst with value type is only supported in some contexts*/);
		if (val != null && val.GetSelectedLanguage() == "Portuguese_Brazilian")
		{
			OnLanguageLoaded(val, "Portuguese_Brazilian");
		}
	}

	private void Update()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (toggleShortcut == null)
		{
			return;
		}
		KeyboardShortcut value = toggleShortcut.Value;
		if (!((KeyboardShortcut)(ref value)).IsDown())
		{
			return;
		}
		Localization instance = Localization.instance;
		if (instance == null || instance.GetSelectedLanguage() != "Portuguese_Brazilian")
		{
			ShowStatus("Escolha Português do Brasil para alternar a tradução.");
			return;
		}
		if (translationsField == null || addWord == null)
		{
			ShowStatus("Não foi possível alternar a tradução.");
			return;
		}
		bool value2 = Enabled.Value;
		Enabled.Value = !value2;
		try
		{
			if (Enabled.Value)
			{
				Apply(instance);
			}
			else
			{
				Restore(instance);
			}
			ClearCache(instance);
			RefreshVisibleText(instance);
			ShowStatus("Tradução PT-BR: " + (Enabled.Value ? "LIGADA" : "DESLIGADA"));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Tradução PT-BR " + (Enabled.Value ? "ligada" : "desligada") + " sem reiniciar."));
		}
		catch (Exception ex)
		{
			Enabled.Value = value2;
			((BaseUnityPlugin)this).Logger.LogError((object)("Falha ao alternar tradução: " + ex));
			try
			{
				if (value2)
				{
					Apply(instance);
				}
				else
				{
					Restore(instance);
				}
				ClearCache(instance);
				RefreshVisibleText(instance);
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Falha ao restaurar idioma: " + ex2));
			}
			ShowStatus("Falha ao alternar a tradução; veja o log.");
		}
	}

	private static void RefreshVisibleText(Localization localization)
	{
		Localization.OnLanguageChange?.Invoke();
		Canvas[] array = Object.FindObjectsOfType<Canvas>();
		foreach (Canvas val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				localization.ReLocalizeAll(((Component)val).transform);
			}
		}
	}

	private void ShowStatus(string message)
	{
		statusText = message;
		statusUntil = Time.unscaledTime + 3f;
	}

	private void OnGUI()
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (statusText != null && !(Time.unscaledTime >= statusUntil))
		{
			GUI.Box(new Rect(20f, 20f, 460f, 42f), statusText);
		}
	}

	private Dictionary<string, string> LoadCorrections()
	{
		Dictionary<string, string> dictionary = new Dictionary<string, string>();
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("correcoes.tsv");
		if (stream == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Recurso correcoes.tsv ausente na DLL.");
			return dictionary;
		}
		using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
		string text;
		while ((text = streamReader.ReadLine()) != null)
		{
			if (text.Length != 0 && text[0] != '#')
			{
				int num = text.IndexOf('\t');
				if (num > 0)
				{
					dictionary[text.Substring(0, num)] = text.Substring(num + 1).Replace('⏎', '\n');
				}
			}
		}
		return dictionary;
	}

	private static Dictionary<string, string> GetTranslations(Localization localization)
	{
		if (!(translationsField.GetValue(localization) is Dictionary<string, string> result))
		{
			throw new InvalidOperationException("Dicionário de traduções indisponível.");
		}
		return result;
	}

	internal static void OnLanguageLoaded(Localization localization, string language)
	{
		if (language != "Portuguese_Brazilian" || translationsField == null || corrections == null)
		{
			return;
		}
		Dictionary<string, string> translations = GetTranslations(localization);
		originals.Clear();
		absentOriginals.Clear();
		foreach (KeyValuePair<string, string> correction in corrections)
		{
			if (translations.TryGetValue(correction.Key, out var value))
			{
				originals[correction.Key] = value;
			}
			else
			{
				absentOriginals.Add(correction.Key);
			}
		}
		if (Enabled != null && Enabled.Value)
		{
			Apply(localization);
		}
	}

	private static void Apply(Localization localization)
	{
		foreach (KeyValuePair<string, string> correction in corrections)
		{
			addWord.Invoke(localization, new object[2] { correction.Key, correction.Value });
		}
		ClearCache(localization);
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)(corrections.Count + " textos PT-BR corrigidos."));
		}
	}

	private static void Restore(Localization localization)
	{
		Dictionary<string, string> translations = GetTranslations(localization);
		foreach (KeyValuePair<string, string> correction in corrections)
		{
			if (translations.TryGetValue(correction.Key, out var value) && !(value != correction.Value))
			{
				if (originals.TryGetValue(correction.Key, out var value2))
				{
					translations[correction.Key] = value2;
				}
				else if (absentOriginals.Contains(correction.Key))
				{
					translations.Remove(correction.Key);
				}
			}
		}
	}

	private static void ClearCache(Localization localization)
	{
		if (!(cacheField != null))
		{
			return;
		}
		object value = cacheField.GetValue(localization);
		if (value != null)
		{
			MethodInfo methodInfo = AccessTools.Method(value.GetType(), "EvictAll", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(value, null);
			}
		}
	}
}
[HarmonyPatch(typeof(Localization), "SetupLanguage")]
internal static class SetupLanguagePatch
{
	private static void Postfix(Localization __instance, string __0)
	{
		Plugin.OnLanguageLoaded(__instance, __0);
	}
}