Decompiled source of CjkFontFix v1.0.0

CjkFontFix.dll

Decompiled 19 hours ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CjkFontFix;

[BepInPlugin("local.ultrakill.cjkfontfix", "CJK Font Fix", "1.2.0")]
public class CjkFontFixPlugin : BaseUnityPlugin
{
	private static readonly char[] Probe = new char[3] { 'あ', '日', '한' };

	private readonly List<TMP_FontAsset> donors = new List<TMP_FontAsset>();

	private readonly HashSet<int> donorIds = new HashSet<int>();

	private readonly HashSet<string> patchedPairs = new HashSet<string>();

	private static readonly string[] FontFiles = new string[11]
	{
		"YuGothR.ttc", "YuGothM.ttc", "meiryo.ttc", "msgothic.ttc", "malgun.ttf", "gulim.ttc", "batang.ttc", "msyh.ttc", "msjh.ttc", "simsun.ttc",
		"simhei.ttf"
	};

	private const int MaxFileFonts = 5;

	private readonly List<TMP_FontAsset> fileFonts = new List<TMP_FontAsset>();

	private float nextPatch;

	private int logged;

	private void Awake()
	{
		((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
		Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		try
		{
			LoadFileFonts();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Loading font files failed: " + ex));
		}
		SceneManager.sceneLoaded += delegate
		{
			nextPatch = 0f;
		};
	}

	private void LoadFileFonts()
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Expected O, but got Unknown
		string text = Environment.GetEnvironmentVariable("WINDIR");
		if (string.IsNullOrEmpty(text))
		{
			text = "C:\\Windows";
		}
		string text2 = Path.Combine(text, "Fonts");
		string[] fontFiles = FontFiles;
		foreach (string text3 in fontFiles)
		{
			if (fileFonts.Count >= 5)
			{
				break;
			}
			string text4 = Path.Combine(text2, text3);
			if (!File.Exists(text4))
			{
				continue;
			}
			try
			{
				Font val = new Font(text4);
				TMP_FontAsset val2 = TMP_FontAsset.CreateFontAsset(val);
				if ((Object)(object)val2 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not make a font from " + text3));
					continue;
				}
				if (!CanDraw(val2))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)(text3 + " loaded but has no CJK glyphs; skipped."));
					continue;
				}
				((Object)val2).name = "CJK " + text3;
				fileFonts.Add(val2);
				donors.Add(val2);
				donorIds.Add(((Object)val2).GetInstanceID());
				((BaseUnityPlugin)this).Logger.LogInfo((object)("CJK font loaded from file: " + text3));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Skipping " + text3 + ": " + ex.Message));
			}
		}
		if (fileFonts.Count == 0)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("No usable CJK font files found in " + text2));
		}
	}

	private static bool CanDraw(TMP_FontAsset fa)
	{
		try
		{
			char[] probe = Probe;
			foreach (char c in probe)
			{
				if (fa.HasCharacter(c, true, true))
				{
					return true;
				}
			}
		}
		catch (Exception)
		{
		}
		return false;
	}

	private void Update()
	{
		if (Time.unscaledTime < nextPatch)
		{
			return;
		}
		nextPatch = Time.unscaledTime + 2f;
		try
		{
			Patch();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Patch failed: " + ex));
			nextPatch = Time.unscaledTime + 30f;
		}
	}

	private void Patch()
	{
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: Unknown result type (might be due to invalid IL or missing references)
		TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
		TMP_FontAsset[] array2 = array;
		foreach (TMP_FontAsset val in array2)
		{
			if (!((Object)(object)val == (Object)null) && !donorIds.Contains(((Object)val).GetInstanceID()) && CanDraw(val))
			{
				donorIds.Add(((Object)val).GetInstanceID());
				donors.Add(val);
				if (logged++ < 10)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("CJK-capable font found: " + ((Object)val).name));
				}
			}
		}
		if (donors.Count == 0)
		{
			return;
		}
		List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets;
		if (fallbackFontAssets != null)
		{
			foreach (TMP_FontAsset donor in donors)
			{
				if ((Object)(object)donor != (Object)null && !fallbackFontAssets.Contains(donor))
				{
					fallbackFontAssets.Add(donor);
				}
			}
		}
		bool flag = false;
		TMP_FontAsset[] array3 = array;
		foreach (TMP_FontAsset val2 in array3)
		{
			if ((Object)(object)val2 == (Object)null || donorIds.Contains(((Object)val2).GetInstanceID()))
			{
				continue;
			}
			if (val2.fallbackFontAssetTable == null)
			{
				val2.fallbackFontAssetTable = new List<TMP_FontAsset>();
			}
			foreach (TMP_FontAsset donor2 in donors)
			{
				if (!((Object)(object)donor2 == (Object)null))
				{
					string item = ((Object)val2).GetInstanceID() + ">" + ((Object)donor2).GetInstanceID();
					if (patchedPairs.Add(item) && !val2.fallbackFontAssetTable.Contains(donor2))
					{
						val2.fallbackFontAssetTable.Add(donor2);
						flag = true;
					}
				}
			}
		}
		if (!flag)
		{
			return;
		}
		TMP_Text[] array4 = Resources.FindObjectsOfTypeAll<TMP_Text>();
		foreach (TMP_Text val3 in array4)
		{
			if ((Object)(object)val3 != (Object)null)
			{
				Scene scene = ((Component)val3).gameObject.scene;
				if (((Scene)(ref scene)).IsValid() && ((Component)val3).gameObject.activeInHierarchy)
				{
					((Graphic)val3).SetAllDirty();
				}
			}
		}
	}
}