Decompiled source of RoR2Vietnamese v1.6.3

plugins/RoR2Vietnamese/RoR2Vietnamese.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RoR2Vietnamese;

internal static class Log
{
	private static ManualLogSource _logSource;

	internal static void Init(ManualLogSource logSource)
	{
		_logSource = logSource;
	}

	internal static void Debug(object data)
	{
		_logSource.LogDebug(data);
	}

	internal static void Error(object data)
	{
		_logSource.LogError(data);
	}

	internal static void Fatal(object data)
	{
		_logSource.LogFatal(data);
	}

	internal static void Info(object data)
	{
		_logSource.LogInfo(data);
	}

	internal static void Message(object data)
	{
		_logSource.LogMessage(data);
	}

	internal static void Warning(object data)
	{
		_logSource.LogWarning(data);
	}
}
[BepInPlugin("Helscarthe.RoR2Vietnamese", "RoR2Vietnamese", "1.0.1")]
public class MainPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "Helscarthe.RoR2Vietnamese";

	public const string PluginAuthor = "Helscarthe";

	public const string PluginName = "RoR2Vietnamese";

	public const string PluginVersion = "1.0.1";

	public static TMP_FontAsset vietFont;

	public static TMP_FontAsset currentFont;

	public static AssetBundle mainBundle;

	public static string assetBundlePath;

	private const string BUNDLE_NAME = "bombadiervn";

	private static MethodInfo _foldersAddMethod;

	private int[] _patchedFontIds = new int[0];

	public static PluginInfo PInfo { get; private set; }

	private void Awake()
	{
		PInfo = ((BaseUnityPlugin)this).Info;
		Log.Init(((BaseUnityPlugin)this).Logger);
		assetBundlePath = Path.Combine(Path.GetDirectoryName(PInfo.Location), "AssetBundles", "bombadiervn");
		if (!File.Exists(assetBundlePath))
		{
			Log.Error("Không tìm thấy AssetBundle tại: " + assetBundlePath);
			return;
		}
		mainBundle = AssetBundle.LoadFromFile(assetBundlePath);
		if ((Object)(object)mainBundle == (Object)null)
		{
			Log.Error("Load AssetBundle thất bại!");
			return;
		}
		Object[] array = mainBundle.LoadAllAssets();
		Object[] array2 = array;
		foreach (Object val in array2)
		{
			TMP_FontAsset val2 = (TMP_FontAsset)(object)((val is TMP_FontAsset) ? val : null);
			if (val2 != null)
			{
				vietFont = val2;
				currentFont = val2;
				Log.Info("Đã load font: " + ((Object)val2).name);
				break;
			}
		}
		if ((Object)(object)vietFont == (Object)null)
		{
			Log.Error("Không tìm thấy font trong bundle!");
			return;
		}
		HookLanguageEvent();
		SceneManager.sceneLoaded += OnSceneLoaded;
		Log.Info("RoR2Vietnamese v1.0.1 đã load thành công.");
	}

	private void OnDestroy()
	{
		SceneManager.sceneLoaded -= OnSceneLoaded;
		((MonoBehaviour)this).StopAllCoroutines();
	}

	private void HookLanguageEvent()
	{
		try
		{
			Type type = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetName().Name == "RoR2")
				{
					type = assembly.GetType("RoR2.Language");
					break;
				}
			}
			if (type == null)
			{
				Log.Error("Không tìm thấy RoR2.Language!");
				return;
			}
			EventInfo @event = type.GetEvent("collectLanguageRootFolders", BindingFlags.Static | BindingFlags.Public);
			if (@event == null)
			{
				Log.Warning("Không tìm thấy collectLanguageRootFolders.");
				return;
			}
			Type eventHandlerType = @event.EventHandlerType;
			Type parameterType = eventHandlerType.GetMethod("Invoke").GetParameters()[0].ParameterType;
			_foldersAddMethod = parameterType.GetMethod("Add");
			Delegate handler = Delegate.CreateDelegate(eventHandlerType, this, typeof(MainPlugin).GetMethod("OnCollectLanguageFolders", BindingFlags.Instance | BindingFlags.NonPublic));
			@event.AddEventHandler(null, handler);
			Log.Info("Đã hook collectLanguageRootFolders.");
		}
		catch (Exception ex)
		{
			Log.Error("HookLanguageEvent: " + ex.Message);
		}
	}

	private void OnCollectLanguageFolders(object folders)
	{
		string text = Path.Combine(Path.GetDirectoryName(PInfo.Location), "Languages");
		if (_foldersAddMethod != null)
		{
			_foldersAddMethod.Invoke(folders, new object[1] { text });
		}
		else
		{
			folders.GetType().GetMethod("Add").Invoke(folders, new object[1] { text });
		}
		Log.Info("Đã thêm thư mục ngôn ngữ: " + text);
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		if (!((Object)(object)vietFont == (Object)null))
		{
			((MonoBehaviour)this).StartCoroutine(PatchFontsRepeated());
		}
	}

	private IEnumerator PatchFontsRepeated()
	{
		yield return null;
		PatchAllFontFallbacks();
		yield return (object)new WaitForSeconds(0.5f);
		PatchAllFontFallbacks();
		yield return (object)new WaitForSeconds(1f);
		PatchAllFontFallbacks();
	}

	private bool IsPatched(int id)
	{
		int[] patchedFontIds = _patchedFontIds;
		foreach (int num in patchedFontIds)
		{
			if (num == id)
			{
				return true;
			}
		}
		return false;
	}

	private void MarkPatched(int id)
	{
		int[] array = new int[_patchedFontIds.Length + 1];
		_patchedFontIds.CopyTo(array, 0);
		array[_patchedFontIds.Length] = id;
		_patchedFontIds = array;
	}

	private void PatchAllFontFallbacks()
	{
		if ((Object)(object)vietFont == (Object)null)
		{
			return;
		}
		PropertyInfo property = typeof(TMP_FontAsset).GetProperty("fallbackFontAssetTable", BindingFlags.Instance | BindingFlags.Public);
		if (property == null)
		{
			Log.Error("Không tìm thấy TMP_FontAsset.fallbackFontAssetTable!");
			return;
		}
		Type propertyType = property.PropertyType;
		MethodInfo method = propertyType.GetMethod("Contains");
		MethodInfo method2 = propertyType.GetMethod("Insert");
		MethodInfo method3 = propertyType.GetMethod("Add");
		ConstructorInfo constructor = propertyType.GetConstructor(Type.EmptyTypes);
		TMP_Text[] array = Object.FindObjectsOfType<TMP_Text>(true);
		int num = 0;
		TMP_Text[] array2 = array;
		foreach (TMP_Text val in array2)
		{
			if ((Object)(object)val == (Object)null || (Object)(object)val.font == (Object)null)
			{
				continue;
			}
			TMP_FontAsset font = val.font;
			if ((Object)(object)font == (Object)(object)vietFont)
			{
				continue;
			}
			int instanceID = ((Object)font).GetInstanceID();
			if (!IsPatched(instanceID))
			{
				object value = property.GetValue(font);
				if (value == null)
				{
					object obj = constructor.Invoke(null);
					method3.Invoke(obj, new object[1] { vietFont });
					property.SetValue(font, obj);
					MarkPatched(instanceID);
					num++;
				}
				else if (!(bool)method.Invoke(value, new object[1] { vietFont }))
				{
					method2.Invoke(value, new object[2] { 0, vietFont });
					MarkPatched(instanceID);
					num++;
				}
			}
		}
		if (num > 0)
		{
			Log.Debug("Đã patch fallback vào " + num + " font.");
		}
	}
}