Decompiled source of DSCnFontMod v1.0.0

YapYapCnFontMod.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jettcodey.FontAPI;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("YapYapCnFontMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("YapYapCnFontMod")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b470584b-ed47-456f-971d-9cc1817fe7bd")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("cn.player.yapyapcnfont", "YapYap中文字体模组", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class YapYapCnFontMod : BaseUnityPlugin
{
	private static HashSet<char> missingCharacters = new HashSet<char>();

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

	private static string missingCharsPath;

	private static Harmony harmony;

	private static float lastSaveTime = 0f;

	private const float SAVE_INTERVAL = 30f;

	public static YapYapCnFontMod Instance { get; private set; }

	internal static ManualLogSource Logger { get; private set; }

	private void Awake()
	{
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		Logger.LogInfo((object)"YapYap中文字体模组初始化...");
		string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		missingCharsPath = Path.Combine(directoryName, "missing_chinese_characters.txt");
		LoadMissingCharacters();
		if (string.IsNullOrEmpty(directoryName))
		{
			Logger.LogError((object)"无法获取插件目录路径");
			return;
		}
		string text = Path.Combine(directoryName, "yapyapcnfontbundle");
		Logger.LogInfo((object)("正在加载字体资源包: " + text));
		if (!File.Exists(text))
		{
			Logger.LogError((object)("文件不存在: " + text));
			return;
		}
		AssetBundle val = AssetBundle.LoadFromFile(text);
		if ((Object)(object)val == (Object)null)
		{
			Logger.LogError((object)"AssetBundle加载失败");
			return;
		}
		Logger.LogInfo((object)$"AssetBundle加载成功,包含 {val.GetAllAssetNames().Length} 个资源");
		string[] allAssetNames = val.GetAllAssetNames();
		foreach (string text2 in allAssetNames)
		{
			Logger.LogInfo((object)("资源名称: " + text2));
		}
		ExploreFontAPI(val);
		InitializeHarmonyPatches();
		Logger.LogInfo((object)"缺失字符监控已启动。当遇到显示为方框的中文字符时,它们将被记录到文件中。");
	}

	private void Update()
	{
		if (Time.time - lastSaveTime > 30f && missingCharacters.Count > 0)
		{
			SaveMissingCharacters();
			lastSaveTime = Time.time;
		}
	}

	private void ExploreFontAPI(AssetBundle bundle)
	{
		try
		{
			TryCallFontAPI(bundle);
			if (!CheckIfFontApplied())
			{
				TryAlternativeApproach(bundle);
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("探索FontAPI时出错: " + ex.Message));
		}
	}

	private void TryCallFontAPI(AssetBundle bundle)
	{
		bool flag = false;
		Type typeFromHandle = typeof(FontAPI);
		MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Static | BindingFlags.Public);
		Logger.LogInfo((object)$"FontAPI共有 {methods.Length} 个公共静态方法:");
		MethodInfo[] array = methods;
		foreach (MethodInfo methodInfo in array)
		{
			Logger.LogInfo((object)$"方法: {methodInfo.Name}, 参数: {methodInfo.GetParameters().Length}");
			if (!methodInfo.Name.Contains("Font") && !methodInfo.Name.Contains("Set") && !methodInfo.Name.Contains("Load"))
			{
				continue;
			}
			try
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 0)
				{
					methodInfo.Invoke(null, null);
					Logger.LogInfo((object)("成功调用 " + methodInfo.Name + "()"));
					flag = true;
				}
				else if (parameters.Length == 1)
				{
					if (parameters[0].ParameterType == typeof(AssetBundle))
					{
						methodInfo.Invoke(null, new object[1] { bundle });
						Logger.LogInfo((object)("成功调用 " + methodInfo.Name + "(AssetBundle)"));
						flag = true;
					}
					else if (parameters[0].ParameterType == typeof(string))
					{
						methodInfo.Invoke(null, new object[1] { "ZhengQingKeNanBeiCiGongPuSongTi-2 SDF" });
						Logger.LogInfo((object)("成功调用 " + methodInfo.Name + "(string)"));
						flag = true;
					}
				}
				else if (parameters.Length == 2)
				{
					methodInfo.Invoke(null, new object[2] { bundle, "ZhengQingKeNanBeiCiGongPuSongTi-2 SDF" });
					Logger.LogInfo((object)("成功调用 " + methodInfo.Name + "(AssetBundle, string)"));
					flag = true;
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("调用 " + methodInfo.Name + " 失败: " + (ex.InnerException?.Message ?? ex.Message)));
			}
		}
		if (flag)
		{
			Logger.LogInfo((object)"至少一个FontAPI方法调用成功");
		}
		else
		{
			Logger.LogWarning((object)"所有FontAPI方法调用尝试均失败");
		}
	}

	private bool CheckIfFontApplied()
	{
		return false;
	}

	private void TryAlternativeApproach(AssetBundle bundle)
	{
		Logger.LogInfo((object)"尝试替代方法...");
		try
		{
			Object val = bundle.LoadAsset("ZhengQingKeNanBeiCiGongPuSongTi-2 SDF");
			if (val != (Object)null)
			{
				Logger.LogInfo((object)("成功加载对象,类型: " + ((object)val).GetType().FullName));
				Logger.LogInfo((object)("对象名称: " + val.name));
				return;
			}
			Logger.LogError((object)"无法从AssetBundle加载指定名称的对象");
			Object[] array = bundle.LoadAllAssets();
			Logger.LogInfo((object)$"AssetBundle中包含 {array.Length} 个对象:");
			Object[] array2 = array;
			foreach (Object val2 in array2)
			{
				Logger.LogInfo((object)("  - " + val2.name + " (" + ((object)val2).GetType().Name + ")"));
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("替代方法失败: " + ex.Message));
		}
	}

	private void InitializeHarmonyPatches()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Expected O, but got Unknown
		try
		{
			harmony = new Harmony("cn.player.yapyapcnfont.monitor");
			Type typeFromHandle = typeof(Text);
			if (typeFromHandle != null)
			{
				MethodInfo methodInfo = typeFromHandle.GetProperty("text")?.GetSetMethod();
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TextMeshProMonitor), "RecordUIText", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Logger.LogInfo((object)"已应用UnityEngine.UI.Text补丁");
				}
			}
			TryPatchTextMeshProTypes();
			Logger.LogInfo((object)"Harmony补丁已应用,开始监控缺失字符...");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("应用Harmony补丁失败: " + ex.Message));
		}
	}

	private void TryPatchTextMeshProTypes()
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Expected O, but got Unknown
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Expected O, but got Unknown
		try
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			Assembly[] array = assemblies;
			foreach (Assembly assembly in array)
			{
				try
				{
					Type type = assembly.GetType("TMPro.TextMeshProUGUI");
					Type type2 = assembly.GetType("TMPro.TextMeshPro");
					if (type != null)
					{
						MethodInfo methodInfo = type.GetProperty("text")?.GetSetMethod();
						if (methodInfo != null)
						{
							harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TextMeshProMonitor), "RecordTMPText", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							Logger.LogInfo((object)"已动态应用TextMeshProUGUI补丁");
						}
					}
					if (type2 != null)
					{
						MethodInfo methodInfo2 = type2.GetProperty("text")?.GetSetMethod();
						if (methodInfo2 != null)
						{
							harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(TextMeshProMonitor), "RecordTMP3DText", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							Logger.LogInfo((object)"已动态应用TextMeshPro补丁");
						}
					}
				}
				catch
				{
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("动态加载TextMeshPro类型失败: " + ex.Message));
		}
	}

	private void OnDestroy()
	{
		if (missingCharacters.Count > 0)
		{
			SaveMissingCharacters();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
			Logger.LogInfo((object)"Harmony补丁已清理");
		}
	}

	private void LoadMissingCharacters()
	{
		if (!File.Exists(missingCharsPath))
		{
			return;
		}
		try
		{
			string text = File.ReadAllText(missingCharsPath, Encoding.UTF8);
			string text2 = text;
			foreach (char c in text2)
			{
				if (IsChineseCharacter(c))
				{
					missingCharacters.Add(c);
				}
			}
			Logger.LogInfo((object)$"从文件加载了 {missingCharacters.Count} 个先前记录的缺失字符");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("加载缺失字符文件失败: " + ex.Message));
		}
	}

	private void SaveMissingCharacters()
	{
		try
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine($"# YapYap缺失中文字符记录 - {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
			stringBuilder.AppendLine($"# 总缺失字符数: {missingCharacters.Count}");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("# 缺失字符列表(直接复制到Unity的字符集文件中):");
			int num = 0;
			List<char> list = new List<char>(missingCharacters);
			list.Sort();
			foreach (char item in list)
			{
				stringBuilder.Append(item);
				num++;
				if (num % 50 == 0)
				{
					stringBuilder.AppendLine();
				}
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("# 缺失字符上下文(出现这些字符的文本示例):");
			foreach (string missingCharacterContext in missingCharacterContexts)
			{
				if (missingCharacterContext.Length > 100)
				{
					stringBuilder.AppendLine("- " + missingCharacterContext.Substring(0, 100) + "...");
				}
				else
				{
					stringBuilder.AppendLine("- " + missingCharacterContext);
				}
			}
			File.WriteAllText(missingCharsPath, stringBuilder.ToString(), Encoding.UTF8);
			Logger.LogInfo((object)$"已保存 {missingCharacters.Count} 个缺失字符到: {missingCharsPath}");
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("保存缺失字符文件失败: " + ex.Message));
		}
	}

	public static void RecordMissingCharacter(char c, string context = "")
	{
		if (IsChineseCharacter(c) && !missingCharacters.Contains(c))
		{
			missingCharacters.Add(c);
			if (!string.IsNullOrEmpty(context) && !missingCharacterContexts.Contains(context))
			{
				missingCharacterContexts.Add(context);
			}
			if (Logger != null && missingCharacters.Count % 10 == 0)
			{
				Logger.LogInfo((object)$"已记录 {missingCharacters.Count} 个缺失字符,最新: '{c}' (U+{(int)c:X4})");
			}
		}
	}

	public static bool IsChineseCharacter(char c)
	{
		return (c >= '一' && c <= '\u9fff') || (c >= '㐀' && c <= '䶿') || (c >= 131072 && c <= 173791) || (c >= 173824 && c <= 177983) || (c >= 177984 && c <= 178207) || (c >= 178208 && c <= 183983) || (c >= 183984 && c <= 191471);
	}
}
public static class TextMeshProMonitor
{
	public static void RecordUIText(Text __instance)
	{
		if ((Object)(object)__instance != (Object)null && __instance.text != null)
		{
			CheckAndRecordCharacters(__instance.text, "UnityEngine.UI.Text");
		}
	}

	public static void RecordTMPText(object __instance)
	{
		try
		{
			PropertyInfo property = __instance.GetType().GetProperty("text");
			if (property != null)
			{
				string text = property.GetValue(__instance) as string;
				if (!string.IsNullOrEmpty(text))
				{
					CheckAndRecordCharacters(text, "TextMeshProUGUI");
				}
			}
		}
		catch
		{
		}
	}

	public static void RecordTMP3DText(object __instance)
	{
		try
		{
			PropertyInfo property = __instance.GetType().GetProperty("text");
			if (property != null)
			{
				string text = property.GetValue(__instance) as string;
				if (!string.IsNullOrEmpty(text))
				{
					CheckAndRecordCharacters(text, "TextMeshPro");
				}
			}
		}
		catch
		{
		}
	}

	private static void CheckAndRecordCharacters(string text, string componentType)
	{
		try
		{
			bool flag = false;
			foreach (char c in text)
			{
				if (YapYapCnFontMod.IsChineseCharacter(c))
				{
					flag = true;
					YapYapCnFontMod.RecordMissingCharacter(c, text);
				}
			}
		}
		catch
		{
		}
	}
}