Decompiled source of REPOConfigFix v1.0.0

Zichen-REPOConfigFix-1.0.0.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Zichen-REPOConfigFix-1.0.0")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+458668cf21bf1ab3b679634fa32dbf3a5ffad58d")]
[assembly: AssemblyProduct("Zichen-REPOConfigFix-1.0.0")]
[assembly: AssemblyTitle("Zichen-REPOConfigFix-1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Zichen_REPOConfigFix
{
	[BepInPlugin("zichen.repoconfigfix", "REPOConfigFix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <WaitAndShowStartupPopup>d__22 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin <>4__this;

			private float <deadline>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitAndShowStartupPopup>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				Plugin plugin = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<deadline>5__2 = Time.unscaledTime + 15f;
					goto IL_00a1;
				case 1:
				{
					<>1__state = -1;
					MenuManager instance = MenuManager.instance;
					if ((Object)(object)instance != (Object)null && !IsPopupSlotBusy(instance))
					{
						plugin.ShowPopupAndDisableSwitch(instance);
						return false;
					}
					goto IL_008a;
				}
				case 2:
					{
						<>1__state = -1;
						goto IL_00a1;
					}
					IL_008a:
					<>2__current = null;
					<>1__state = 2;
					return true;
					IL_00a1:
					if (Time.unscaledTime < <deadline>5__2)
					{
						MenuManager instance = MenuManager.instance;
						if ((Object)(object)instance != (Object)null && !IsPopupSlotBusy(instance))
						{
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
						goto IL_008a;
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PluginGuid = "zichen.repoconfigfix";

		public const string PluginName = "REPOConfigFix";

		public const string PluginVersion = "1.0.0";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		private static ConfigEntry<bool> _cfgModEnabled;

		private static ConfigEntry<bool> _cfgShowStartupPopup;

		private static TMP_FontAsset _cachedCjkFont;

		private static bool _fontSearchDone;

		private const float FontSizeDelta = 4f;

		private Harmony _harmony;

		private static readonly FieldRef<MenuManager, bool> PagePopUpScheduledRef = AccessTools.FieldRefAccess<MenuManager, bool>("pagePopUpScheduled");

		private static readonly FieldRef<MenuManager, MenuPageIndex> CurrentMenuPageIndexRef = AccessTools.FieldRefAccess<MenuManager, MenuPageIndex>("currentMenuPageIndex");

		private static readonly FieldRef<MenuManager, MenuPage> CurrentMenuPageRef = AccessTools.FieldRefAccess<MenuManager, MenuPage>("currentMenuPage");

		public static bool IsStaticModEnabled()
		{
			if (_cfgModEnabled != null)
			{
				return _cfgModEnabled.Value;
			}
			return false;
		}

		public static bool ShowStartupPopup()
		{
			if (_cfgShowStartupPopup != null)
			{
				return _cfgShowStartupPopup.Value;
			}
			return false;
		}

		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			DetachFromManager();
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ResetConfigIfVersionChanged();
			BindConfig();
			if (!IsStaticModEnabled())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"中文修复 v1.0.0 已禁用。");
				return;
			}
			_harmony = new Harmony("zichen.repoconfigfix");
			TryApplyPatches();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"中文修复 v1.0.0 已加载。");
		}

		private void OnDestroy()
		{
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}

		private void BindConfig()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组名称", "REPOConfig 中文修复", new ConfigDescription("", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ReadOnly = true,
					HideDefaultButton = true,
					Order = 1000
				}
			}));
			((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组版本号", "1.0.0", new ConfigDescription("", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ReadOnly = true,
					HideDefaultButton = true,
					Order = 990
				}
			}));
			_cfgModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "模组启用", true, new ConfigDescription("关闭后整个模组全部功能失效。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 900
				}
			}));
			_cfgShowStartupPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "中文修复提示", true, new ConfigDescription("启动时弹窗提示中文修复已生效,弹出后自动关闭此开关。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 890
				}
			}));
		}

		private void TryApplyPatches()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("MenuLib.MonoBehaviors.REPOSlider");
			Type type2 = AccessTools.TypeByName("MenuLib.MonoBehaviors.REPOToggle");
			if (type == null && type2 == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"中文修复:MenuLib 未找到,跳过补丁。");
				return;
			}
			TryPatchAwake(type, "REPOSlider", "REPOSliderAwakePostfix");
			TryPatchAwake(type2, "REPOToggle", "REPOToggleAwakePostfix");
			MethodInfo methodInfo = AccessTools.Method(typeof(MenuManager), "Start", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				try
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "MenuManagerStartPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("REPOConfigFix: MenuManager.Start 补丁失败 — " + ex.Message));
				}
			}
		}

		private void TryPatchAwake(Type targetType, string typeName, string postfixName)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			if (targetType == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("REPOConfigFix: " + typeName + " 未找到,跳过。"));
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(targetType, "Awake", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("REPOConfigFix: " + typeName + ".Awake 未找到,跳过。"));
				return;
			}
			try
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Plugin), postfixName, (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("REPOConfigFix: " + typeName + ".Awake 补丁已安装。"));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("REPOConfigFix: 安装 " + typeName + " 补丁失败 — " + ex.Message));
			}
		}

		private static void REPOSliderAwakePostfix(REPOSlider __instance)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (!IsStaticModEnabled())
			{
				return;
			}
			try
			{
				TMP_FontAsset orFindCjkFont = GetOrFindCjkFont();
				if (!((Object)(object)orFindCjkFont == (Object)null) && !((Object)(object)__instance.labelTMP == (Object)null))
				{
					ApplyCjkFont((TMP_Text)__instance.labelTMP, orFindCjkFont);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("REPOConfigFix: REPOSliderAwakePostfix 异常 — " + ex.Message));
				}
			}
		}

		private static void REPOToggleAwakePostfix(REPOToggle __instance)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (!IsStaticModEnabled())
			{
				return;
			}
			try
			{
				TMP_FontAsset orFindCjkFont = GetOrFindCjkFont();
				if (!((Object)(object)orFindCjkFont == (Object)null) && !((Object)(object)__instance.labelTMP == (Object)null))
				{
					ApplyCjkFont((TMP_Text)__instance.labelTMP, orFindCjkFont);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("REPOConfigFix: REPOToggleAwakePostfix 异常 — " + ex.Message));
				}
			}
		}

		private static void ApplyCjkFont(TMP_Text tmp, TMP_FontAsset cjkFont)
		{
			if (!((Object)(object)tmp == (Object)null) && !((Object)(object)cjkFont == (Object)null) && !((Object)(object)tmp.font == (Object)(object)cjkFont))
			{
				tmp.font = cjkFont;
				tmp.fontSize += 4f;
			}
		}

		private static void MenuManagerStartPostfix()
		{
			if (IsStaticModEnabled() && ShowStartupPopup() && !((Object)(object)Instance == (Object)null))
			{
				((MonoBehaviour)Instance).StartCoroutine(Instance.WaitAndShowStartupPopup());
			}
		}

		[IteratorStateMachine(typeof(<WaitAndShowStartupPopup>d__22))]
		private IEnumerator WaitAndShowStartupPopup()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitAndShowStartupPopup>d__22(0)
			{
				<>4__this = this
			};
		}

		private void ShowPopupAndDisableSwitch(MenuManager mm)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = "REPOConfigFix";
				Color val = default(Color);
				((Color)(ref val))..ctor(0.4f, 1f, 0.55f);
				string text2 = "中文修复已生效。\n<size=85%>配置面板中的中文标题现在可以正常显示。</size>\n\n<size=85%><i>此提示只会弹出一次。</i></size>";
				mm.PagePopUpScheduled(text, val, text2, "OK", true);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"REPOConfigFix: 启动弹窗已显示。");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("REPOConfigFix: 显示启动弹窗失败 — " + ex.Message));
			}
			try
			{
				_cfgShowStartupPopup.Value = false;
			}
			catch
			{
			}
		}

		private static bool IsPopupSlotBusy(MenuManager mm)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Invalid comparison between Unknown and I4
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			if ((Object)(object)mm == (Object)null)
			{
				return true;
			}
			try
			{
				if ((Object)(object)CurrentMenuPageRef.Invoke(mm) == (Object)null)
				{
					return true;
				}
			}
			catch
			{
				return true;
			}
			try
			{
				if (PagePopUpScheduledRef.Invoke(mm))
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				MenuPageIndex val = CurrentMenuPageIndexRef.Invoke(mm);
				if ((int)val == 9 || (int)val == 7)
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		private static TMP_FontAsset GetOrFindCjkFont()
		{
			if (_fontSearchDone)
			{
				return _cachedCjkFont;
			}
			_fontSearchDone = true;
			try
			{
				uint[] array = new uint[3] { 20013u, 25991u, 35821u };
				TMP_FontAsset[] array2 = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("{0}: 扫描到 {1} 个 TMP_FontAsset。", "REPOConfigFix", array2.Length));
				}
				TMP_FontAsset[] array3 = array2;
				foreach (TMP_FontAsset val in array3)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					string text = ((Object)val).name ?? string.Empty;
					if ((text.IndexOf("CJK", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Chinese", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("中文", StringComparison.Ordinal) >= 0 || text.IndexOf("NotoSansCJK", StringComparison.OrdinalIgnoreCase) >= 0) && FontHasGlyph(val, array[0]))
					{
						_cachedCjkFont = val;
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogInfo((object)("REPOConfigFix: 按名称找到 CJK 字体:" + ((Object)val).name));
						}
						return _cachedCjkFont;
					}
				}
				array3 = array2;
				foreach (TMP_FontAsset val2 in array3)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					bool flag = true;
					uint[] array4 = array;
					foreach (uint unicode in array4)
					{
						if (!FontHasGlyph(val2, unicode))
						{
							flag = false;
							break;
						}
					}
					if (flag)
					{
						_cachedCjkFont = val2;
						ManualLogSource log3 = Log;
						if (log3 != null)
						{
							log3.LogInfo((object)("REPOConfigFix: 按字形检测找到 CJK 字体:" + ((Object)val2).name));
						}
						return _cachedCjkFont;
					}
				}
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogWarning((object)"REPOConfigFix: 未找到含 CJK 字形的 TMP_FontAsset,中文标题将无法显示。");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogWarning((object)("REPOConfigFix: 字体扫描异常 — " + ex.Message));
				}
			}
			return null;
		}

		private static bool FontHasGlyph(TMP_FontAsset font, uint unicode)
		{
			if ((Object)(object)font == (Object)null)
			{
				return false;
			}
			try
			{
				return font.HasCharacter((char)unicode, false, false);
			}
			catch
			{
				return false;
			}
		}

		private void ResetConfigIfVersionChanged()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (File.Exists(configFilePath))
				{
					string text = ReadConfigPluginVersion(configFilePath);
					if (!(text == "1.0.0"))
					{
						((BaseUnityPlugin)this).Config.Clear();
						File.Delete(configFilePath);
						((BaseUnityPlugin)this).Config.Reload();
						((BaseUnityPlugin)this).Logger.LogWarning((object)(string.IsNullOrWhiteSpace(text) ? "Old config without Mod Version, reset to defaults." : ("Config version " + text + " -> 1.0.0, reset to defaults.")));
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Reset config failed: " + ex.Message));
			}
		}

		private static string ReadConfigPluginVersion(string configPath)
		{
			if (!File.Exists(configPath))
			{
				return null;
			}
			string input = File.ReadAllText(configPath);
			Match match = Regex.Match(input, "(?m)^Mod Version\\s*=\\s*(.+?)\\s*$");
			if (!match.Success)
			{
				match = Regex.Match(input, "(?m)^模组版本号\\s*=\\s*(.+?)\\s*$");
			}
			if (!match.Success)
			{
				return null;
			}
			return match.Groups[1].Value.Trim();
		}

		private void DetachFromManager()
		{
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? ReadOnly;

		public bool? Browsable;

		public bool? HideDefaultButton;

		public string Category;

		public string DispName;

		public string Description;
	}
}