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.");
}
}
}