Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LC Chinese Project v0.1.3
BepInEx/plugins/V81TestChn/V81TestChn.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.TextCore.LowLevel; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("V81TestChn")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("V81TestChn")] [assembly: AssemblyTitle("V81TestChn")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 V81TestChn { internal static class AlertTextureReplacementService { [CompilerGenerated] private sealed class <WaitForFixedSceneLabels>d__35 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string stage; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForFixedSceneLabels>d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <elapsed>5__2 = 0f; break; case 1: <>1__state = -1; <elapsed>5__2 += 0.25f; break; } if (<elapsed>5__2 < 8f) { if (SyncFixedSceneLabelsInRelayScene(stage + ".relay-scene") > 0) { _fixedSceneLabelWatcher = null; return false; } <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 1; return true; } Plugin.Log.LogWarning((object)("NativeRelay[" + stage + ".relay-scene] target=FixedSceneLabel action=timeout")); _fixedSceneLabelWatcher = null; 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(); } } [CompilerGenerated] private sealed class <WaitForSystemOnlineTitle>d__34 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string stage; public HUDManager hudManager; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForSystemOnlineTitle>d__34(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <elapsed>5__2 = 0f; break; case 1: <>1__state = -1; <elapsed>5__2 += 0.1f; break; } if ((Object)(object)hudManager != (Object)null && <elapsed>5__2 < 12f) { TMP_Text text = FindSystemOnlineTitleByFullPath(); if (IsExactSystemOnlineTitle(text)) { ApplySystemOnlineNativeTranslation(text, stage + ".watcher"); _systemOnlineWatcher = null; return false; } <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } Plugin.Log.LogWarning((object)("NativeRelay[" + stage + ".watcher] target=SystemOnline action=timeout")); _systemOnlineWatcher = null; 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(); } } private const string SystemOnlineTitleObjectName = "TipLeft1"; private const string SystemOnlineTitleFullPath = "Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/SystemsOnline/TipLeft1"; private const string SystemOnlineTitlePathSuffix = "IngamePlayerHUD/BottomMiddle/SystemsOnline/TipLeft1"; private const string SystemOnlineRelativePath = "BottomMiddle/SystemsOnline/TipLeft1"; private const string EnteringAtmosphereTitleObjectName = "LoadText"; private const string RelaySceneName = "SampleSceneRelay"; private const string SystemOnlineLocalizedText = "系统在线"; private const string EnteringAtmosphereLocalizedText = "正在进入大气层..."; private const string HazardLevelLocalizedText = "危险等级:"; private const string LifeSupportOfflineLocalizedText = "[生命维持:离线]"; private static Coroutine? _systemOnlineWatcher; private static Coroutine? _fixedSceneLabelWatcher; private static readonly Dictionary<string, string> FixedSceneLabels = new Dictionary<string, string>(StringComparer.Ordinal) { ["TO MEET PROFIT QUOTA"] = "以达到利润配额", ["PERFORMANCE REPORT"] = "绩效报告", ["EMPLOYEE RANK"] = "员工等级", ["Fines"] = "罚款", ["(Dead)"] = "(死亡)", ["Deceased"] = "死亡", ["[LIFE SUPPORT: OFFLINE]"] = "[生命维持:离线]", ["You will keep your employee rank. Your ship and credits will be reset."] = "你的员工等级将被保留,但飞船和点数将被重置。" }; public static void Initialize(string pluginDir) { Plugin.Log.LogInfo((object)"Native relay title translation enabled; SYSTEMS ONLINE uses original TMP object only."); } public static void ForceApplySystemOnlineOverlay(HUDManager? hudManager, string stage) { TMP_Text val = FindSystemOnlineTitle(hudManager, allowGlobalFallback: false); if ((Object)(object)val != (Object)null) { ApplySystemOnlineNativeTranslation(val, stage); return; } Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=SystemOnline action=not-found")); AuditSystemOnlineBranch(stage, hudManager); } public static void BeginSystemOnlineExactPathWatcher(HUDManager? hudManager, string stage) { if (!((Object)(object)hudManager == (Object)null) && _systemOnlineWatcher == null) { _systemOnlineWatcher = ((MonoBehaviour)hudManager).StartCoroutine(WaitForSystemOnlineTitle(hudManager, stage)); } } public static void TryApplySystemOnlineDirect(HUDManager? hudManager, string stage) { TMP_Text val = FindSystemOnlineTitle(hudManager, allowGlobalFallback: true); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=SystemOnline action=not-found")); } else { ApplySystemOnlineNativeTranslation(val, stage); } } public static void QueueSystemOnlineSync(HUDManager? hudManager, string stage) { } public static void TryApplyEnteringAtmosphereOverlayFromLoadingScreen(HUDManager? hudManager, string stage) { TMP_Text val = FindEnteringAtmosphereTitle(hudManager); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=EnteringAtmosphere action=not-found")); } else { ApplyEnteringAtmosphereNativeTranslation(val, stage); } } public static void HideEnteringAtmosphereOverlayForHud(HUDManager? hudManager, string stage) { TMP_Text val = FindEnteringAtmosphereTitle(hudManager); if ((Object)(object)val != (Object)null) { ApplyEnteringAtmosphereNativeTranslation(val, stage); } } public static void SyncEnteringAtmosphereOverlayState(TMP_Text? text, string stage) { if (!((Object)(object)text == (Object)null) && IsEnteringAtmosphereTitleObject(text)) { ApplyEnteringAtmosphereNativeTranslation(text, stage); } } public static void SyncHazardLevelRelay(HUDManager? hudManager, string stage) { TMP_Text val = FindHazardLevelTitle(hudManager); if ((Object)(object)val != (Object)null) { ApplyHazardLevelNativeTranslation(val, stage); } } public static void SyncLandingInfo(HUDManager? hudManager, string stage) { if (!((Object)(object)hudManager == (Object)null)) { ApplyDynamicFieldTranslation((TMP_Text?)(object)hudManager.planetInfoHeaderText, stage, "PlanetInfoHeader"); ApplyDynamicFieldTranslation((TMP_Text?)(object)hudManager.planetInfoSummaryText, stage, "PlanetInfoSummary"); ApplyDynamicFieldTranslation((TMP_Text?)(object)hudManager.planetRiskLevelText, stage, "PlanetRiskLevel"); SyncHazardLevelRelay(hudManager, stage); } } public static void SyncFixedSceneLabels(HUDManager? hudManager, string stage) { if (!((Object)(object)hudManager == (Object)null)) { TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { TryReplaceFixedSceneLabel(componentsInChildren[i], stage); } } } public static void BeginFixedSceneLabelWatcher(HUDManager? hudManager, string stage) { if (!((Object)(object)hudManager == (Object)null) && _fixedSceneLabelWatcher == null) { _fixedSceneLabelWatcher = ((MonoBehaviour)hudManager).StartCoroutine(WaitForFixedSceneLabels(stage)); } } public static void TryReplaceSystemOnlineText(TMP_Text? text, string stage) { if (!((Object)(object)text == (Object)null)) { if (IsSystemOnlineObject(text)) { ApplySystemOnlineNativeTranslation(text, stage); } else if (IsEnteringAtmosphereTitleObject(text)) { ApplyEnteringAtmosphereNativeTranslation(text, stage); } else if (IsHazardLevelTitle(text.text)) { ApplyHazardLevelNativeTranslation(text, stage); } else { TryReplaceFixedSceneLabel(text, stage); } } } public static bool TryReplaceFixedSceneLabel(TMP_Text? text, string stage) { if ((Object)(object)text == (Object)null || string.IsNullOrWhiteSpace(text.text)) { return false; } if (!TryResolveFixedSceneLabel(text.text, out string localized)) { return false; } ApplyLocalizedText(text, localized, stage, "FixedSceneLabel"); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=FixedSceneLabel action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text)); return true; } public static void TryReplaceSystemOnlineText(Text? text, string stage) { } public static void TryReplaceSystemOnlineText(TextMesh? text, string stage) { } public static void TryReplace(Image? image, string stage) { } public static void TryReplace(RawImage? image, string stage) { } public static void TryReplace(SpriteRenderer? renderer, string stage) { } public static void TryReplace(Material? material, string stage) { } private static void ApplySystemOnlineNativeTranslation(TMP_Text text, string stage) { if (!((Behaviour)text).enabled) { ((Behaviour)text).enabled = true; } ApplyLocalizedText(text, ResolveLocalizedText(text.text, "系统在线"), stage, "SystemOnline"); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=SystemOnline action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text)); } [IteratorStateMachine(typeof(<WaitForSystemOnlineTitle>d__34))] private static IEnumerator WaitForSystemOnlineTitle(HUDManager hudManager, string stage) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForSystemOnlineTitle>d__34(0) { hudManager = hudManager, stage = stage }; } [IteratorStateMachine(typeof(<WaitForFixedSceneLabels>d__35))] private static IEnumerator WaitForFixedSceneLabels(string stage) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitForFixedSceneLabels>d__35(0) { stage = stage }; } private static void ApplyEnteringAtmosphereNativeTranslation(TMP_Text text, string stage) { ApplyLocalizedText(text, ResolveLocalizedText(text.text, "正在进入大气层..."), stage, "EnteringAtmosphere"); } private static void ApplyHazardLevelNativeTranslation(TMP_Text text, string stage) { ApplyLocalizedText(text, "危险等级:", stage, "HazardLevel"); } private static void ApplyLocalizedText(TMP_Text text, string localized, string stage, string target) { if (!string.IsNullOrWhiteSpace(localized)) { if (!string.Equals(text.text, localized, StringComparison.Ordinal)) { text.text = localized; } FontFallbackService.ApplyFallback(text, localized); ApplyLifeSupportOfflineTypography(text, localized); } } private static void ApplyLifeSupportOfflineTypography(TMP_Text text, string localized) { if (string.Equals(localized, "[生命维持:离线]", StringComparison.Ordinal)) { text.richText = true; text.enableWordWrapping = false; text.overflowMode = (TextOverflowModes)0; text.fontStyle = (FontStyles)0; text.characterSpacing = Math.Max(text.characterSpacing, 6f); text.wordSpacing = Math.Max(text.wordSpacing, 8f); } } private static TMP_Text? FindSystemOnlineTitle(HUDManager? hudManager, bool allowGlobalFallback) { if ((Object)(object)hudManager != (Object)null) { if ((Object)(object)((Component)hudManager).transform != (Object)null) { Transform obj = ((Component)hudManager).transform.Find("BottomMiddle/SystemsOnline/TipLeft1"); TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null); if (IsExactSystemOnlineTitle(val)) { return val; } } TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val2 in componentsInChildren) { if (IsExactSystemOnlineTitle(val2)) { return val2; } } } if (allowGlobalFallback) { TMP_Text val3 = FindSystemOnlineTitleByFullPath(); if (IsExactSystemOnlineTitle(val3)) { return val3; } TMP_Text[] componentsInChildren = Resources.FindObjectsOfTypeAll<TMP_Text>(); foreach (TMP_Text val4 in componentsInChildren) { if (IsExactSystemOnlineTitle(val4)) { return val4; } } } return null; } private static TMP_Text? FindSystemOnlineTitleByFullPath() { GameObject val = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/SystemsOnline/TipLeft1"); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<TMP_Text>(); } private static TMP_Text? FindEnteringAtmosphereTitle(HUDManager? hudManager) { if ((Object)(object)hudManager?.LoadingScreen == (Object)null) { return null; } TMP_Text[] componentsInChildren = ((Component)hudManager.LoadingScreen).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren) { if (IsEnteringAtmosphereTitleObject(val)) { return val; } } return null; } private static TMP_Text? FindHazardLevelTitle(HUDManager? hudManager) { if ((Object)(object)hudManager == (Object)null) { return null; } TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren) { if (IsHazardLevelTitle(val.text)) { return val; } } return null; } private static bool IsSystemOnlineObject(TMP_Text? text) { return IsExactSystemOnlineTitle(text); } private static bool IsSystemOnlinePath(Transform? transform) { if ((Object)(object)transform == (Object)null) { return false; } return BuildPath(transform).EndsWith("IngamePlayerHUD/BottomMiddle/SystemsOnline/TipLeft1", StringComparison.OrdinalIgnoreCase); } private static bool IsEnteringAtmosphereTitleObject(TMP_Text? text) { if ((Object)(object)text == (Object)null) { return false; } if (string.Equals(((Object)text).name, "LoadText", StringComparison.OrdinalIgnoreCase)) { return HasNamedAncestor(text.transform, "LoadingText"); } return false; } private static bool IsHazardLevelTitle(string? text) { if (string.IsNullOrWhiteSpace(text)) { return false; } string a = text.Trim(); if (!string.Equals(a, "HAZARD LEVEL:", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "危险等级:", StringComparison.Ordinal)) { return string.Equals(a, "危险等级:", StringComparison.Ordinal); } return true; } private static string ResolveLocalizedText(string? current, string fallback) { if (!string.IsNullOrWhiteSpace(current) && TranslationService.TryTranslate(current, out string translated)) { return translated; } return fallback; } private static bool TryResolveFixedSceneLabel(string? current, out string localized) { localized = string.Empty; if (string.IsNullOrWhiteSpace(current)) { return false; } if (FixedSceneLabels.TryGetValue(current.Trim(), out localized) && !string.IsNullOrWhiteSpace(localized)) { return true; } return false; } private static int SyncFixedSceneLabelsInRelayScene(string stage) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) Scene sceneByName = SceneManager.GetSceneByName("SampleSceneRelay"); if (!((Scene)(ref sceneByName)).IsValid() || !((Scene)(ref sceneByName)).isLoaded) { return 0; } int num = 0; GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { TMP_Text[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<TMP_Text>(true); for (int j = 0; j < componentsInChildren.Length; j++) { if (TryReplaceFixedSceneLabel(componentsInChildren[j], stage)) { num++; } } } return num; } private static bool HasNamedAncestor(Transform? transform, string expectedName) { Transform val = transform; while ((Object)(object)val != (Object)null) { if (string.Equals(((Object)val).name, expectedName, StringComparison.OrdinalIgnoreCase)) { return true; } val = val.parent; } return false; } private static void AuditSystemOnlineBranch(string stage, HUDManager? hudManager) { int num = 0; if ((Object)(object)hudManager != (Object)null) { TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren) { if (HasNamedAncestor(val.transform, "SystemsOnline")) { num++; Plugin.Log.LogInfo((object)$"NativeRelay[{stage}] target=SystemOnline action=audit exact={IsExactSystemOnlineTitle(val)} name={((Object)val).name} path={BuildPath(val.transform)} text={val.text}"); } } } _ = 0; } private static void ApplyDynamicFieldTranslation(TMP_Text? text, string stage, string target) { if (!((Object)(object)text == (Object)null) && !string.IsNullOrWhiteSpace(text.text) && TranslationService.TryTranslate(text.text, out string translated) && !string.IsNullOrWhiteSpace(translated)) { if (!string.Equals(text.text, translated, StringComparison.Ordinal)) { text.text = translated; } FontFallbackService.ApplyFallback(text, translated); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=" + target + " action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text)); } } private static string BuildPath(Transform? transform) { if ((Object)(object)transform == (Object)null) { return "<null>"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static bool IsExactSystemOnlineTitle(TMP_Text? text) { if ((Object)(object)text == (Object)null) { return false; } if (BuildPath(text.transform).EndsWith("IngamePlayerHUD/BottomMiddle/SystemsOnline/TipLeft1", StringComparison.OrdinalIgnoreCase)) { return true; } return false; } } internal static class EmbeddedFontPatcherService { private sealed class FontBundlePair { public string BundleName { get; set; } = string.Empty; public TMP_FontAsset? Normal { get; set; } public TMP_FontAsset? Transmit { get; set; } } [CompilerGenerated] private sealed class <ResolveCandidateDirectories>d__24 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private string pluginDir; public string <>3__pluginDir; private string <relative>5__2; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ResolveCandidateDirectories>d__24(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <relative>5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <relative>5__2 = NormalizePathSegment(_fontAssetsPath.Value); if (!string.IsNullOrWhiteSpace(<relative>5__2)) { <>2__current = Path.Combine(pluginDir, "V81TestChn", <relative>5__2); <>1__state = 1; return true; } goto IL_00cd; case 1: <>1__state = -1; <>2__current = Path.Combine(pluginDir, <relative>5__2); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = Path.Combine(Paths.ConfigPath, <relative>5__2); <>1__state = 3; return true; case 3: <>1__state = -1; goto IL_00cd; case 4: <>1__state = -1; <>2__current = Path.Combine(pluginDir, "V81TestChn", "fonts", "fontpatcher", "default"); <>1__state = 5; return true; case 5: <>1__state = -1; <>2__current = Path.Combine(Paths.ConfigPath, "FontPatcher", "default"); <>1__state = 6; return true; case 6: { <>1__state = -1; return false; } IL_00cd: <>2__current = Path.Combine(pluginDir, "V81TestChn", "fontpatcher", "default"); <>1__state = 4; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { <ResolveCandidateDirectories>d__24 <ResolveCandidateDirectories>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <ResolveCandidateDirectories>d__ = this; } else { <ResolveCandidateDirectories>d__ = new <ResolveCandidateDirectories>d__24(0); } <ResolveCandidateDirectories>d__.pluginDir = <>3__pluginDir; return <ResolveCandidateDirectories>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } private static readonly List<FontBundlePair> LoadedBundles = new List<FontBundlePair>(); private static readonly HashSet<int> PatchedFontIds = new HashSet<int>(); private static readonly HashSet<string> ScannedDirectories = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static ConfigEntry<bool>? _enabled; private static ConfigEntry<string>? _fontAssetsPath; private static ConfigEntry<string>? _normalRegexPattern; private static ConfigEntry<string>? _transmitRegexPattern; private static ConfigEntry<bool>? _useVanillaNormal; private static ConfigEntry<bool>? _useVanillaTransmit; private static ConfigEntry<bool>? _debugLog; private static ConfigEntry<bool>? _applyMaterialTweaks; private static ConfigEntry<string>? _bundleNameRegexPattern; private static Regex? _normalRegex; private static Regex? _transmitRegex; private static Regex? _bundleNameRegex; private static bool _initialized; private static int _patchLogBudget = 160; private static int _scanLogBudget = 60; private static bool _loggedNormalBundleBypass; public static void Initialize(string pluginDir, ConfigFile config) { if (!_initialized) { _enabled = config.Bind<bool>("EmbeddedFontPatcher", "Enable", true, "Enable embedded FontPatcher compatibility behavior."); _fontAssetsPath = config.Bind<string>("EmbeddedFontPatcher", "FontAssetsPath", "fontpatcher\\default", "Relative directory for font bundles."); _normalRegexPattern = config.Bind<string>("EmbeddedFontPatcher", "NormalFontNameRegex", "^(b|DialogueText).*$", "Regex used to detect normal UI fonts."); _transmitRegexPattern = config.Bind<string>("EmbeddedFontPatcher", "TransmitFontNameRegex", "^.*$", "Regex used to detect signal/transmit fonts."); _useVanillaNormal = config.Bind<bool>("EmbeddedFontPatcher", "UseVanillaNormalFont", true, "Keep vanilla normal font characters in addition to bundle fallback fonts."); _useVanillaTransmit = config.Bind<bool>("EmbeddedFontPatcher", "UseVanillaTransmitFont", true, "Keep vanilla transmit font characters in addition to bundle fallback fonts."); _debugLog = config.Bind<bool>("EmbeddedFontPatcher", "DebugLog", false, "Enable verbose embedded FontPatcher logs."); _applyMaterialTweaks = config.Bind<bool>("EmbeddedFontPatcher", "ApplyMaterialTweaks", false, "Apply FontPatcher-like material underlay tweaks."); _bundleNameRegexPattern = config.Bind<string>("EmbeddedFontPatcher", "BundleNameRegex", "^(00 default|cn|zh.*)$", "Only bundles whose file name matches this regex will be loaded. Prevents unintended style drift from unrelated language bundles."); UpgradeLegacyRegexDefaultsIfNeeded(); _normalRegex = CreateRegex(_normalRegexPattern.Value, "^(b|DialogueText).*$"); _transmitRegex = CreateRegex(_transmitRegexPattern.Value, "^.*$"); _bundleNameRegex = CreateRegex(_bundleNameRegexPattern.Value, "^(00 default|cn|zh.*)$"); _initialized = true; if (_enabled.Value) { LoadBundles(pluginDir); PatchLoadedFontAssets(); } Plugin.Log.LogInfo((object)$"EmbeddedFontPatcher initialized: enabled={_enabled.Value}, bundles={LoadedBundles.Count}, assetsPath={_fontAssetsPath.Value}"); } } public static void PatchFontAsset(TMP_FontAsset? fontAsset, string stage = "unknown") { if (!_initialized || !_enabled.Value || (Object)(object)fontAsset == (Object)null || _normalRegex == null || _transmitRegex == null) { return; } int instanceID = ((Object)fontAsset).GetInstanceID(); string text = ((Object)fontAsset).name ?? string.Empty; bool flag = _normalRegex.IsMatch(text); bool flag2 = _transmitRegex.IsMatch(text); if ((!flag && !flag2) || !PatchedFontIds.Add(instanceID)) { return; } if (fontAsset.fallbackFontAssetTable == null) { fontAsset.fallbackFontAssetTable = new List<TMP_FontAsset>(); } if (flag) { DisableVanillaFont(fontAsset); if (!_loggedNormalBundleBypass) { _loggedNormalBundleBypass = true; Plugin.Log.LogWarning((object)"EmbeddedFontPatcher bypassed normal bundle fallbacks; relying on V81 dynamic Chinese fallback to avoid unreadable atlas stalls."); } } if (flag2 && !_useVanillaTransmit.Value) { DisableVanillaFont(fontAsset); } int num = 0; foreach (FontBundlePair loadedBundle in LoadedBundles) { if (!flag) { TMP_FontAsset val = (flag ? loadedBundle.Normal : loadedBundle.Transmit); if (!((Object)(object)val == (Object)null) && !fontAsset.fallbackFontAssetTable.Contains(val)) { fontAsset.fallbackFontAssetTable.Add(val); num++; } } } if (_applyMaterialTweaks.Value) { ApplyMaterialTweaks(((TMP_Asset)fontAsset).material); } if (num > 0 && _patchLogBudget > 0) { _patchLogBudget--; Plugin.Log.LogWarning((object)string.Format("EmbeddedFontPatcher patched '{0}' at {1}: addedFallbacks={2}, mode={3}", text, stage, num, flag ? "Normal" : "Transmit")); } else if (_debugLog.Value) { Plugin.Log.LogInfo((object)string.Format("EmbeddedFontPatcher visited '{0}' at {1}: addedFallbacks={2}, mode={3}", text, stage, num, flag ? "Normal" : "Transmit")); } } public static void PatchTextComponent(TMP_Text? text, string stage = "unknown") { if (!((Object)(object)((text != null) ? text.font : null) == (Object)null)) { PatchFontAsset(text.font, stage); } } private static void LoadBundles(string pluginDir) { LoadedBundles.Clear(); ScannedDirectories.Clear(); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (string item in ResolveCandidateDirectories(pluginDir)) { if (!Directory.Exists(item) || !ScannedDirectories.Add(item)) { continue; } int num = 0; FileInfo[] files = new DirectoryInfo(item).GetFiles("*", SearchOption.TopDirectoryOnly); foreach (FileInfo fileInfo in files) { if (!hashSet.Add(fileInfo.Name)) { continue; } if (_bundleNameRegex != null && !_bundleNameRegex.IsMatch(fileInfo.Name)) { if (_debugLog.Value) { Plugin.Log.LogInfo((object)("EmbeddedFontPatcher skipped bundle '" + fileInfo.Name + "' by BundleNameRegex.")); } continue; } try { AssetBundle val = AssetBundle.LoadFromFile(fileInfo.FullName); if ((Object)(object)val == (Object)null) { continue; } TMP_FontAsset val2 = val.LoadAsset<TMP_FontAsset>("Normal"); TMP_FontAsset val3 = val.LoadAsset<TMP_FontAsset>("Transmit"); if (!((Object)(object)val2 == (Object)null) || !((Object)(object)val3 == (Object)null)) { if ((Object)(object)val2 != (Object)null) { ((Object)val2).name = fileInfo.Name + "(Normal)"; } if ((Object)(object)val3 != (Object)null) { ((Object)val3).name = fileInfo.Name + "(Transmit)"; } LoadedBundles.Add(new FontBundlePair { BundleName = fileInfo.Name, Normal = val2, Transmit = val3 }); num++; if (_debugLog.Value) { Plugin.Log.LogInfo((object)$"EmbeddedFontPatcher loaded bundle '{fileInfo.Name}' from '{item}': normal={(Object)(object)val2 != (Object)null}, transmit={(Object)(object)val3 != (Object)null}"); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("EmbeddedFontPatcher failed loading '" + fileInfo.FullName + "': " + ex.GetType().Name + ": " + ex.Message)); } } if (num > 0 && _scanLogBudget > 0) { _scanLogBudget--; Plugin.Log.LogInfo((object)$"EmbeddedFontPatcher loaded {num} bundles from '{item}'."); } } } [IteratorStateMachine(typeof(<ResolveCandidateDirectories>d__24))] private static IEnumerable<string> ResolveCandidateDirectories(string pluginDir) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ResolveCandidateDirectories>d__24(-2) { <>3__pluginDir = pluginDir }; } private static void PatchLoadedFontAssets() { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); for (int i = 0; i < array.Length; i++) { PatchFontAsset(array[i], "Resources.Scan"); } } private static void DisableVanillaFont(TMP_FontAsset font) { if (font.characterLookupTable != null) { font.characterLookupTable.Clear(); } font.atlasPopulationMode = (AtlasPopulationMode)0; } private static void ApplyMaterialTweaks(Material? material) { if (!((Object)(object)material == (Object)null)) { if (material.HasProperty(ShaderUtilities.ID_UnderlayDilate)) { material.SetFloat(ShaderUtilities.ID_UnderlayDilate, 1f); } if (material.HasProperty(ShaderUtilities.ID_UnderlayOffsetX)) { material.SetFloat(ShaderUtilities.ID_UnderlayOffsetX, 0.1f); } } } private static void UpgradeLegacyRegexDefaultsIfNeeded() { if (_normalRegexPattern != null && _transmitRegexPattern != null) { string text = "^(b|DialogueText|3270.*)$"; string text2 = "^edunline.*$"; string text3 = "^(b|DialogueText).*$"; string text4 = "^.*$"; if (string.Equals(_normalRegexPattern.Value, text, StringComparison.Ordinal)) { _normalRegexPattern.Value = text3; Plugin.Log.LogWarning((object)("EmbeddedFontPatcher auto-upgraded NormalFontNameRegex from legacy '" + text + "' to '" + text3 + "' to match FontPatcher behavior.")); } if (string.Equals(_transmitRegexPattern.Value, text2, StringComparison.Ordinal)) { _transmitRegexPattern.Value = text4; Plugin.Log.LogWarning((object)("EmbeddedFontPatcher auto-upgraded TransmitFontNameRegex from legacy '" + text2 + "' to '" + text4 + "' to match FontPatcher behavior.")); } } } private static Regex CreateRegex(string source, string fallback) { try { return new Regex(source, RegexOptions.Compiled); } catch (Exception ex) { Plugin.Log.LogWarning((object)("EmbeddedFontPatcher invalid regex '" + source + "', fallback to '" + fallback + "'. Error: " + ex.Message)); return new Regex(fallback, RegexOptions.Compiled); } } private static string NormalizePathSegment(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } return value.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar).Trim(); } } internal static class EndGameLocalizationService { private const string DeadLocalizedText = "(死亡)"; private const string DeceasedLocalizedText = "死亡"; private const string MissingLocalizedText = "失踪"; private const string TextureSubfolder = "textures"; private const string EndgameAllPlayersDeadTextureFile = "EndgameAllPlayersDeadOverlay.png"; private const string EndgameStatsBoxesTextureFile = "EndgameStatsBoxesLocalized.png"; private const string EndgameStatsDeceasedTextureFile = "EndgameStatsDeceased.png"; private const string EndgameStatsMissingTextureFile = "EndgameStatsMissing.png"; private static string? _textureDirectory; private static readonly Dictionary<string, Sprite?> SpriteCache = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase); public static void Initialize(string pluginDir) { _textureDirectory = Path.Combine(pluginDir, "textures"); } public static void ApplyHudEndGameLocalization(HUDManager? hudManager, string stage) { if (hudManager?.statsUIElements != null) { CleanupLegacyEndGameOverlays(hudManager.statsUIElements); LocalizeRuntimeDeadTexts(stage); LocalizePlayerStateBadges(hudManager.statsUIElements, stage); LocalizeAllPlayersDeadOverlayImage(hudManager.statsUIElements, stage); LocalizeStatsBoxesImage(hudManager.statsUIElements, stage); } } public static void ApplySpectateUiLocalization(HUDManager? hudManager, string stage) { if (!((Object)(object)hudManager == (Object)null)) { LocalizeSpectateDeadTexts(stage); } } public static void ApplyChallengeSlotLocalization(ChallengeLeaderboardSlot? slot, string stage) { if (!((Object)(object)slot?.scrapCollectedText == (Object)null) && string.Equals(((TMP_Text)slot.scrapCollectedText).text?.Trim(), "Deceased", StringComparison.OrdinalIgnoreCase)) { ((TMP_Text)slot.scrapCollectedText).text = "死亡"; FontFallbackService.ApplyFallback((TMP_Text?)(object)slot.scrapCollectedText, "死亡"); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=ChallengeLeaderboard action=applied value=" + ((TMP_Text)slot.scrapCollectedText).text)); } } private static void LocalizeRuntimeDeadTexts(string stage) { TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>(); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrWhiteSpace(val.text)) { string a = val.text.Trim(); if (string.Equals(a, "(Dead)", StringComparison.Ordinal)) { ApplyLocalizedText(val, "(死亡)", stage, "EndGameDeadLabel"); } else if (string.Equals(a, "Deceased", StringComparison.OrdinalIgnoreCase)) { ApplyLocalizedText(val, "死亡", stage, "EndGameDeceasedLabel"); } } } } public static void TryRewriteSpectateDeadValue(TMP_Text? text, ref string value, string stage) { if (!((Object)(object)text == (Object)null) && !string.IsNullOrWhiteSpace(value) && IsSpectateDeadLabel(text.transform)) { string a = value.Trim(); if (string.Equals(a, "(Dead)", StringComparison.Ordinal)) { value = "(死亡)"; Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=SpectateDeadLabel action=rewrite path=" + BuildPath(text.transform) + " value=" + value)); } else if (string.Equals(a, "Deceased", StringComparison.OrdinalIgnoreCase)) { value = "死亡"; Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=SpectateDeceasedLabel action=rewrite path=" + BuildPath(text.transform) + " value=" + value)); } } } public static void TryLocalizeSpectateDeadLabel(TMP_Text? text, string stage) { if (!((Object)(object)text == (Object)null) && !string.IsNullOrWhiteSpace(text.text) && IsSpectateDeadLabel(text.transform)) { string a = text.text.Trim(); if (string.Equals(a, "(Dead)", StringComparison.Ordinal)) { ApplyLocalizedText(text, "(死亡)", stage, "SpectateDeadLabel"); } else if (string.Equals(a, "Deceased", StringComparison.OrdinalIgnoreCase)) { ApplyLocalizedText(text, "死亡", stage, "SpectateDeceasedLabel"); } } } private static void LocalizeSpectateDeadTexts(string stage) { TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>(); for (int i = 0; i < array.Length; i++) { TryLocalizeSpectateDeadLabel(array[i], stage); } } private static void LocalizePlayerStateBadges(EndOfGameStatUIElements elements, string stage) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) TMP_Text template = PickTemplate(elements); if (elements.playerStates == null) { return; } Image[] playerStates = elements.playerStates; foreach (Image val in playerStates) { if ((Object)(object)val == (Object)null) { continue; } if (!((Behaviour)val).enabled || (Object)(object)val.sprite == (Object)null) { SetOverlayActive(((Component)val).transform, "__V81_EndgameStateOverlay", active: false); } else if (val.sprite == elements.deceasedIcon) { if (!TryApplyLocalizedStateSprite(val, "EndgameStatsDeceased.png", stage, "deceased")) { ((Behaviour)val).enabled = false; ((Component)EnsureOverlayLabel(((Component)val).transform, "__V81_EndgameStateOverlay", template, new Vector2(220f, 90f), Vector2.zero, "死亡", 24f, new Color(1f, 0.22f, 0.22f, 1f), (TextAlignmentOptions)514)).gameObject.SetActive(true); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=EndGameState action=fallback-label state=deceased path=" + BuildPath(((Component)val).transform))); } } else if (val.sprite == elements.missingIcon) { if (!TryApplyLocalizedStateSprite(val, "EndgameStatsMissing.png", stage, "missing")) { ((Behaviour)val).enabled = false; ((Component)EnsureOverlayLabel(((Component)val).transform, "__V81_EndgameStateOverlay", template, new Vector2(220f, 90f), Vector2.zero, "失踪", 24f, new Color(1f, 0.22f, 0.22f, 1f), (TextAlignmentOptions)514)).gameObject.SetActive(true); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=EndGameState action=fallback-label state=missing path=" + BuildPath(((Component)val).transform))); } } else { SetOverlayActive(((Component)val).transform, "__V81_EndgameStateOverlay", active: false); } } } private static void LocalizeAllPlayersDeadOverlayImage(EndOfGameStatUIElements elements, string stage) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) Image allPlayersDeadOverlay = elements.allPlayersDeadOverlay; if ((Object)(object)allPlayersDeadOverlay == (Object)null) { return; } if (!((Behaviour)allPlayersDeadOverlay).enabled) { DestroyChildIfExists(((Component)allPlayersDeadOverlay).transform, "__V81_EndgameNoSurvivorsOverlay"); DestroyChildIfExists(((Component)allPlayersDeadOverlay).transform, "__V81_EndgameAllPlayersDeadTexture"); return; } DestroyChildIfExists(((Component)allPlayersDeadOverlay).transform, "__V81_EndgameNoSurvivorsOverlay"); DestroyChildIfExists(((Component)allPlayersDeadOverlay).transform, "__V81_EndgameAllScrapLostOverlay"); DestroyChildIfExists(((Component)allPlayersDeadOverlay).transform, "__V81_EndgameAllPlayersDeadTexture"); Sprite sprite = allPlayersDeadOverlay.sprite; Type type = allPlayersDeadOverlay.type; bool preserveAspect = allPlayersDeadOverlay.preserveAspect; Sprite val = LoadSprite("EndgameAllPlayersDeadOverlay.png", sprite); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=EndGameOverlay action=texture-missing file=EndgameAllPlayersDeadOverlay.png")); return; } allPlayersDeadOverlay.sprite = val; allPlayersDeadOverlay.preserveAspect = preserveAspect; allPlayersDeadOverlay.type = type; ((Graphic)allPlayersDeadOverlay).color = Color.white; Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=EndGameOverlay action=applied path=" + BuildPath(((Component)allPlayersDeadOverlay).transform) + " " + $"type={allPlayersDeadOverlay.type} preserveAspect={allPlayersDeadOverlay.preserveAspect} imageRect={DescribeRect(((Graphic)allPlayersDeadOverlay).rectTransform.rect)} " + "templateSprite=" + DescribeSprite(sprite) + " localizedSprite=" + DescribeSprite(val))); } private static void LocalizeStatsBoxesImage(EndOfGameStatUIElements elements, string stage) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) Image val = FindStatsBoxesImage(elements); if (!((Object)(object)val == (Object)null)) { DestroyChildIfExists(((Component)val).transform, "__V81_EndgameGradeLabel"); DestroyChildIfExists(((Component)val).transform, "__V81_EndgameGradeTexture"); DestroyChildIfExists(((Component)val).transform, "__V81_EndgameCollectedTexture"); Sprite sprite = val.sprite; Type type = val.type; bool preserveAspect = val.preserveAspect; Sprite val2 = LoadSprite("EndgameStatsBoxesLocalized.png", sprite); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=EndGameStatsBoxes action=texture-missing file=EndgameStatsBoxesLocalized.png")); return; } val.sprite = val2; val.preserveAspect = preserveAspect; val.type = type; ((Graphic)val).color = Color.white; Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=EndGameStatsBoxes action=applied path=" + BuildPath(((Component)val).transform) + " " + $"type={val.type} preserveAspect={val.preserveAspect} imageRect={DescribeRect(((Graphic)val).rectTransform.rect)} " + "templateSprite=" + DescribeSprite(sprite) + " localizedSprite=" + DescribeSprite(val2))); } } private static TMP_Text? PickTemplate(EndOfGameStatUIElements elements) { return (TMP_Text?)(object)(elements.playerNamesText?.FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI text) => (Object)(object)text != (Object)null)) ?? elements.gradeLetter); } private static Image? FindStatsBoxesImage(EndOfGameStatUIElements elements) { Image bestCandidate = null; int bestScore = int.MinValue; TextMeshProUGUI quotaNumerator = elements.quotaNumerator; ConsiderCandidate(ref bestCandidate, ref bestScore, FindBestImageOnAncestorChain((quotaNumerator != null) ? ((TMP_Text)quotaNumerator).transform : null, elements), elements); TextMeshProUGUI gradeLetter = elements.gradeLetter; ConsiderCandidate(ref bestCandidate, ref bestScore, FindBestImageOnAncestorChain((gradeLetter != null) ? ((TMP_Text)gradeLetter).transform : null, elements), elements); TextMeshProUGUI gradeLetter2 = elements.gradeLetter; object obj; if (gradeLetter2 == null) { obj = null; } else { Canvas canvas = ((Graphic)gradeLetter2).canvas; obj = ((canvas != null) ? ((Component)canvas).transform : null); } if (obj == null) { TextMeshProUGUI quotaNumerator2 = elements.quotaNumerator; if (quotaNumerator2 == null) { obj = null; } else { Canvas canvas2 = ((Graphic)quotaNumerator2).canvas; obj = ((canvas2 != null) ? ((Component)canvas2).transform : null); } } Transform val = (Transform)obj; if ((Object)(object)val != (Object)null) { Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true); foreach (Image val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2 != elements.allPlayersDeadOverlay) { Sprite sprite = val2.sprite; string text = ((sprite != null) ? ((Object)sprite).name : null); if (!string.IsNullOrWhiteSpace(text) && text.IndexOf("endgameStatsBoxes", StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } ConsiderCandidate(ref bestCandidate, ref bestScore, val2, elements); } } if ((Object)(object)bestCandidate != (Object)null) { ManualLogSource log = Plugin.Log; string arg = BuildPath(((Component)bestCandidate).transform); object arg2 = bestScore; Sprite sprite2 = bestCandidate.sprite; log.LogInfo((object)string.Format("NativeRelay[EndGameStatsBoxes] action=fallback-candidate path={0} score={1} sprite={2}", arg, arg2, ((sprite2 != null) ? ((Object)sprite2).name : null) ?? "<null>")); return bestCandidate; } } TextMeshProUGUI quotaNumerator3 = elements.quotaNumerator; object obj2; if (quotaNumerator3 == null) { obj2 = null; } else { Transform parent = ((TMP_Text)quotaNumerator3).transform.parent; obj2 = ((parent != null) ? ((Component)parent).GetComponent<Image>() : null); } if (obj2 == null) { TextMeshProUGUI gradeLetter3 = elements.gradeLetter; if (gradeLetter3 == null) { return null; } Transform parent2 = ((TMP_Text)gradeLetter3).transform.parent; if (parent2 == null) { return null; } obj2 = ((Component)parent2).GetComponent<Image>(); } return (Image?)obj2; } private static Image? FindBestImageOnAncestorChain(Transform? start, EndOfGameStatUIElements elements) { Transform val = start; Image result = null; int num = int.MinValue; while ((Object)(object)val != (Object)null) { Image component = ((Component)val).GetComponent<Image>(); if ((Object)(object)component != (Object)null && component != elements.allPlayersDeadOverlay && (Object)(object)component.sprite != (Object)null) { int num2 = ScoreStatsBoxesCandidate(component, elements); Plugin.Log.LogInfo((object)$"NativeRelay[EndGameStatsBoxes] action=ancestor-candidate path={BuildPath(((Component)component).transform)} sprite={((Object)component.sprite).name} score={num2}"); if (num2 > num) { num = num2; result = component; } } val = val.parent; } return result; } private static void ConsiderCandidate(ref Image? bestCandidate, ref int bestScore, Image? image, EndOfGameStatUIElements elements) { if (!((Object)(object)image == (Object)null)) { int num = ScoreStatsBoxesCandidate(image, elements); if (num > bestScore) { bestScore = num; bestCandidate = image; } } } private static int ScoreStatsBoxesCandidate(Image image, EndOfGameStatUIElements elements) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) int num = 0; Sprite sprite = image.sprite; string obj = ((sprite != null) ? ((Object)sprite).name : null) ?? string.Empty; string text = BuildPath(((Component)image).transform); Rect rect = ((Graphic)image).rectTransform.rect; if (obj.IndexOf("statsboxes", StringComparison.OrdinalIgnoreCase) >= 0) { num += 1000; } if (obj.IndexOf("endgamestats", StringComparison.OrdinalIgnoreCase) >= 0) { num += 120; } if (obj.IndexOf("statsbg", StringComparison.OrdinalIgnoreCase) >= 0) { num -= 120; } if (text.IndexOf("/EndgameStats/", StringComparison.OrdinalIgnoreCase) >= 0) { num += 40; } if (text.IndexOf("/Text/", StringComparison.OrdinalIgnoreCase) >= 0) { num += 60; } if (((Rect)(ref rect)).width >= 400f && ((Rect)(ref rect)).height >= 180f) { num += 25; } if (((Rect)(ref rect)).width >= 700f && ((Rect)(ref rect)).height >= 500f) { num += 25; } Transform transform = ((Component)image).transform; TextMeshProUGUI quotaNumerator = elements.quotaNumerator; if ((Object)(object)transform == (Object)(object)((quotaNumerator != null) ? ((TMP_Text)quotaNumerator).transform.parent : null)) { num += 180; } Transform transform2 = ((Component)image).transform; TextMeshProUGUI gradeLetter = elements.gradeLetter; if ((Object)(object)transform2 == (Object)(object)((gradeLetter != null) ? ((TMP_Text)gradeLetter).transform.parent : null)) { num += 180; } Rect rect2; if ((Object)(object)elements.quotaNumerator != (Object)null) { rect2 = ((Graphic)image).rectTransform.rect; float width = ((Rect)(ref rect2)).width; rect2 = ((TMP_Text)elements.quotaNumerator).rectTransform.rect; if (width > ((Rect)(ref rect2)).width * 2f) { num += 70; } } if ((Object)(object)elements.gradeLetter != (Object)null) { rect2 = ((Graphic)image).rectTransform.rect; float height = ((Rect)(ref rect2)).height; rect2 = ((TMP_Text)elements.gradeLetter).rectTransform.rect; if (height > ((Rect)(ref rect2)).height * 2f) { num += 40; } } return num; } private static void CleanupLegacyEndGameOverlays(EndOfGameStatUIElements elements) { TextMeshProUGUI gradeLetter = elements.gradeLetter; object obj; if (gradeLetter == null) { obj = null; } else { Canvas canvas = ((Graphic)gradeLetter).canvas; obj = ((canvas != null) ? ((Component)canvas).transform : null); } if (obj == null) { TextMeshProUGUI quotaNumerator = elements.quotaNumerator; if (quotaNumerator == null) { obj = null; } else { Canvas canvas2 = ((Graphic)quotaNumerator).canvas; obj = ((canvas2 != null) ? ((Component)canvas2).transform : null); } } Transform val = (Transform)obj; if ((Object)(object)val == (Object)null) { return; } string[] source = new string[6] { "__V81_EndgameNoSurvivorsOverlay", "__V81_EndgameAllScrapLostOverlay", "__V81_EndgameAllPlayersDeadTexture", "__V81_EndgameGradeLabel", "__V81_EndgameGradeTexture", "__V81_EndgameCollectedTexture" }; Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && source.Contains<string>(((Object)val2).name, StringComparer.Ordinal)) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } private static TextMeshProUGUI EnsureOverlayLabel(Transform parent, string objectName, TMP_Text? template, Vector2 sizeDelta, Vector2 anchoredPosition, string localizedText, float fontSize, Color color, TextAlignmentOptions alignment) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Transform val = parent.Find(objectName); TextMeshProUGUI val3; if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject(objectName, new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(parent, false); val3 = val2.AddComponent<TextMeshProUGUI>(); ((Graphic)val3).raycastTarget = false; } else { val3 = ((Component)val).GetComponent<TextMeshProUGUI>() ?? ((Component)val).gameObject.AddComponent<TextMeshProUGUI>(); } RectTransform rectTransform = ((TMP_Text)val3).rectTransform; rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.sizeDelta = sizeDelta; rectTransform.anchoredPosition = anchoredPosition; if ((Object)(object)template != (Object)null) { ((TMP_Text)val3).font = template.font; ((TMP_Text)val3).fontSharedMaterial = template.fontSharedMaterial; ((TMP_Text)val3).characterSpacing = template.characterSpacing; ((TMP_Text)val3).wordSpacing = template.wordSpacing; ((TMP_Text)val3).lineSpacing = template.lineSpacing; } ((TMP_Text)val3).fontSize = fontSize; ((TMP_Text)val3).alignment = alignment; ((TMP_Text)val3).enableWordWrapping = false; ((Graphic)val3).color = color; ((TMP_Text)val3).text = localizedText; FontFallbackService.ApplyFallback((TMP_Text?)(object)val3, localizedText); return val3; } private static void SetOverlayActive(Transform parent, string objectName, bool active) { Transform val = parent.Find(objectName); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(active); } } private static void DestroyChildIfExists(Transform parent, string objectName) { Transform val = parent.Find(objectName); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } private static void ApplyLocalizedText(TMP_Text text, string localized, string stage, string target) { if (!string.Equals(text.text, localized, StringComparison.Ordinal)) { text.text = localized; } FontFallbackService.ApplyFallback(text, localized); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=" + target + " action=applied path=" + BuildPath(text.transform) + " text=" + text.text)); } private static bool TryApplyLocalizedStateSprite(Image stateImage, string textureFileName, string stage, string state) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) Sprite sprite = stateImage.sprite; Type type = stateImage.type; bool preserveAspect = stateImage.preserveAspect; Sprite val = LoadSprite(textureFileName, sprite); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=EndGameState action=texture-missing state=" + state + " file=" + textureFileName)); return false; } ((Behaviour)stateImage).enabled = true; stateImage.sprite = val; stateImage.type = type; stateImage.preserveAspect = preserveAspect; ((Graphic)stateImage).color = Color.white; SetOverlayActive(((Component)stateImage).transform, "__V81_EndgameStateOverlay", active: false); Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=EndGameState action=applied-sprite state=" + state + " path=" + BuildPath(((Component)stateImage).transform) + " " + $"type={stateImage.type} preserveAspect={stateImage.preserveAspect} imageRect={DescribeRect(((Graphic)stateImage).rectTransform.rect)} " + "templateSprite=" + DescribeSprite(sprite) + " localizedSprite=" + DescribeSprite(val))); return true; } private static Sprite? LoadSprite(string fileName, Sprite? templateSprite = null) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) string key = BuildSpriteCacheKey(fileName, templateSprite); if (SpriteCache.TryGetValue(key, out Sprite value)) { return value; } if (string.IsNullOrWhiteSpace(_textureDirectory)) { return null; } string path = Path.Combine(_textureDirectory, fileName); if (!File.Exists(path)) { SpriteCache[key] = null; return null; } try { byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array, false)) { Object.Destroy((Object)(object)val); SpriteCache[key] = null; return null; } ((Object)val).name = fileName; ((Texture)val).wrapMode = (TextureWrapMode)1; Vector2Int val2 = ResolveSpriteRectSize(templateSprite, ((Texture)val).width, ((Texture)val).height); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(0f, 0f, (float)((Vector2Int)(ref val2)).x, (float)((Vector2Int)(ref val2)).y); Vector2 val4 = ResolveSpritePivot(templateSprite, val3); Vector4 val5 = ResolveSpriteBorder(templateSprite, val3); float num = ((templateSprite != null) ? templateSprite.pixelsPerUnit : 100f); Sprite val6 = Sprite.Create(val, val3, val4, num, 0u, (SpriteMeshType)0, val5); ((Object)val6).name = Path.GetFileNameWithoutExtension(fileName); SpriteCache[key] = val6; return val6; } catch (Exception ex) { Plugin.Log.LogWarning((object)("NativeRelay[EndGameTexture] action=load-failed file=" + fileName + " error=" + ex.GetType().Name + ": " + ex.Message)); SpriteCache[key] = null; return null; } } private static string BuildSpriteCacheKey(string fileName, Sprite? templateSprite) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)templateSprite == (Object)null) { return fileName; } Rect rect = templateSprite.rect; Vector2 pivot = templateSprite.pivot; Vector4 border = templateSprite.border; return $"{fileName}|rect={Mathf.RoundToInt(((Rect)(ref rect)).width)}x{Mathf.RoundToInt(((Rect)(ref rect)).height)}|pivot={Mathf.RoundToInt(pivot.x)},{Mathf.RoundToInt(pivot.y)}|ppu={Mathf.RoundToInt(templateSprite.pixelsPerUnit * 1000f)}|border={Mathf.RoundToInt(border.x)},{Mathf.RoundToInt(border.y)},{Mathf.RoundToInt(border.z)},{Mathf.RoundToInt(border.w)}"; } private static Vector2Int ResolveSpriteRectSize(Sprite? templateSprite, int textureWidth, int textureHeight) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)templateSprite == (Object)null) { return new Vector2Int(textureWidth, textureHeight); } Rect rect = templateSprite.rect; int num = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref rect)).width), 1, textureWidth); int num2 = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref rect)).height), 1, textureHeight); return new Vector2Int(num, num2); } private static Vector2 ResolveSpritePivot(Sprite? templateSprite, Rect spriteRect) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)templateSprite == (Object)null || ((Rect)(ref spriteRect)).width <= 0f || ((Rect)(ref spriteRect)).height <= 0f) { return new Vector2(0.5f, 0.5f); } float x = templateSprite.pivot.x; Rect rect = templateSprite.rect; float num = Mathf.Clamp01(x / Mathf.Max(((Rect)(ref rect)).width, 1f)); float y = templateSprite.pivot.y; rect = templateSprite.rect; return new Vector2(num, Mathf.Clamp01(y / Mathf.Max(((Rect)(ref rect)).height, 1f))); } private static Vector4 ResolveSpriteBorder(Sprite? templateSprite, Rect spriteRect) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)templateSprite == (Object)null) { return Vector4.zero; } Vector4 border = templateSprite.border; return new Vector4(Mathf.Clamp(border.x, 0f, ((Rect)(ref spriteRect)).width), Mathf.Clamp(border.y, 0f, ((Rect)(ref spriteRect)).height), Mathf.Clamp(border.z, 0f, ((Rect)(ref spriteRect)).width), Mathf.Clamp(border.w, 0f, ((Rect)(ref spriteRect)).height)); } private static string DescribeSprite(Sprite? sprite) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sprite == (Object)null) { return "<null>"; } return $"{((Object)sprite).name}|rect={DescribeRect(sprite.rect)}|pivot={DescribeVector2(sprite.pivot)}|ppu={sprite.pixelsPerUnit:0.###}|border={DescribeVector4(sprite.border)}"; } private static string DescribeRect(Rect rect) { return $"{((Rect)(ref rect)).x:0.###},{((Rect)(ref rect)).y:0.###},{((Rect)(ref rect)).width:0.###},{((Rect)(ref rect)).height:0.###}"; } private static string DescribeVector2(Vector2 vector) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) return $"{vector.x:0.###},{vector.y:0.###}"; } private static string DescribeVector4(Vector4 vector) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) return $"{vector.x:0.###},{vector.y:0.###},{vector.z:0.###},{vector.w:0.###}"; } private static string BuildPath(Transform? transform) { if ((Object)(object)transform == (Object)null) { return "<null>"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static bool IsSpectateDeadLabel(Transform? transform) { if ((Object)(object)transform == (Object)null) { return false; } string text = BuildPath(transform); if (text.IndexOf("DeathScreen/SpectateUI/", StringComparison.OrdinalIgnoreCase) < 0) { return false; } if (((Object)transform).name.IndexOf("DeadOrAlive", StringComparison.OrdinalIgnoreCase) < 0) { return text.EndsWith("/DeadOrAlive", StringComparison.OrdinalIgnoreCase); } return true; } } internal static class FocusedTextAuditService { private static int _logBudget = 180; public static void AuditLoadedScene(string stage) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) if (_logBudget <= 0) { return; } TMP_Text[] array = Object.FindObjectsOfType<TMP_Text>(true); foreach (TMP_Text val in array) { if (!((Object)(object)val == (Object)null) && ShouldAudit(val.text)) { string sharedFace = "N/A"; Material fontSharedMaterial = val.fontSharedMaterial; Color color; if ((Object)(object)fontSharedMaterial != (Object)null && fontSharedMaterial.HasProperty(ShaderUtilities.ID_FaceColor)) { color = fontSharedMaterial.GetColor(ShaderUtilities.ID_FaceColor); sharedFace = ((object)(Color)(ref color)).ToString(); } string fontFace = "N/A"; Material fontMaterial = val.fontMaterial; if ((Object)(object)fontMaterial != (Object)null && fontMaterial.HasProperty(ShaderUtilities.ID_FaceColor)) { color = fontMaterial.GetColor(ShaderUtilities.ID_FaceColor); fontFace = ((object)(Color)(ref color)).ToString(); } Log(stage, "TMP", ((Object)val).name, ((Graphic)val).color, sharedFace, fontFace, val.text); if (_logBudget <= 0) { return; } } } Text[] array2 = Object.FindObjectsOfType<Text>(true); foreach (Text val2 in array2) { if (!((Object)(object)val2 == (Object)null) && ShouldAudit(val2.text)) { Log(stage, "UGUI.Text", ((Object)val2).name, ((Graphic)val2).color, "N/A", "N/A", val2.text); if (_logBudget <= 0) { return; } } } TextMesh[] array3 = Object.FindObjectsOfType<TextMesh>(true); foreach (TextMesh val3 in array3) { if (!((Object)(object)val3 == (Object)null) && ShouldAudit(val3.text)) { Log(stage, "TextMesh", ((Object)val3).name, val3.color, "N/A", "N/A", val3.text); if (_logBudget <= 0) { break; } } } } private static void Log(string stage, string type, string name, Color color, string sharedFace, string fontFace, string text) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (_logBudget > 0) { _logBudget--; Plugin.Log.LogWarning((object)$"FocusedSceneAudit[{stage}] type={type}, name={name}, color={color}, sharedFace={sharedFace}, fontFace={fontFace}, text='{Trim(text)}'"); } } private static bool ShouldAudit(string? text) { if (string.IsNullOrWhiteSpace(text)) { return false; } if (!ContainsOrdinalIgnoreCase(text, "SYSTEMS ONLINE") && !ContainsOrdinalIgnoreCase(text, "joined the ship") && !ContainsOrdinalIgnoreCase(text, "started the ship") && !ContainsOrdinalIgnoreCase(text, "ENTERING THE ATMOSPHERE") && !ContainsOrdinalIgnoreCase(text, "系统在线") && !ContainsOrdinalIgnoreCase(text, "系统上线") && !ContainsOrdinalIgnoreCase(text, "正在进入大气层")) { return ContainsOrdinalIgnoreCase(text, "进入大气层"); } return true; } private static bool ContainsOrdinalIgnoreCase(string source, string needle) { return source.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0; } private static string Trim(string input) { input = input.Replace('\n', ' '); if (input.Length > 120) { return input.Substring(0, 120); } return input; } } internal static class FontFallbackService { private static readonly Regex CjkRegex = new Regex("[\\u3400-\\u9FFF]", RegexOptions.Compiled); private static readonly Dictionary<int, Color> BaselineColorByInstance = new Dictionary<int, Color>(); private static readonly HashSet<int> FinalRenderSubscribedIds = new HashSet<int>(); private static readonly HashSet<int> SpecialCaseTextIds = new HashSet<int>(); private static readonly HashSet<int> FinalRenderRepairLoggedIds = new HashSet<int>(); private static readonly HashSet<int> RenderAuditLoggedIds = new HashSet<int>(); private static int _renderAuditBudget = 80; private static int _finalRenderRepairLogBudget = 80; private static int _specialCaseLogBudget = 60; private static int _focusedAuditBudget = 120; private static int _systemOnlineProbeLogBudget = 120; private static int _postTranslationProbeLogBudget = 160; private static int _runtimeCjkSweepLogBudget = 180; private static int _canvasGroupBypassLogBudget = 80; private static TMP_FontAsset? _fallbackFont; private static string? _pluginDir; private static bool _globalFallbackApplied; public static bool HasFallbackFont => (Object)(object)_fallbackFont != (Object)null; public static void TryLoadFontAsset(string pluginDir) { _pluginDir = pluginDir; if (TryLoadFontFileAsset(pluginDir)) { ApplyFallbackGlobally(); return; } string text = Path.Combine(pluginDir, "V81TestChn", "fonts", "zh-cn-tmp-font"); if (!File.Exists(text)) { text = Path.Combine(pluginDir, "fonts", "zh-cn-tmp-font"); } if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("Chinese TMP font bundle not found: " + text)); TryLoadSystemFontAsset(); return; } try { AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"Failed to load Chinese TMP font bundle."); TryLoadSystemFontAsset(); return; } string[] allAssetNames = val.GetAllAssetNames(); foreach (string text2 in allAssetNames) { _fallbackFont = val.LoadAsset<TMP_FontAsset>(text2); if ((Object)(object)_fallbackFont != (Object)null) { NormalizeFallbackFontMaterials(); Plugin.Log.LogInfo((object)("Loaded Chinese fallback font: " + ((Object)_fallbackFont).name + " from " + text)); ApplyFallbackGlobally(); return; } } Plugin.Log.LogWarning((object)("No TMP_FontAsset found in Chinese font bundle: " + text)); TryLoadSystemFontAsset(); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to load Chinese font bundle: {arg}"); TryLoadSystemFontAsset(); } } private static bool TryLoadFontFileAsset(string pluginDir) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown string[] array = new string[6] { Path.Combine(pluginDir, "V81TestChn", "fonts", "NotoSansSC-VF.ttf"), Path.Combine(pluginDir, "fonts", "NotoSansSC-VF.ttf"), "C:\\Windows\\Fonts\\NotoSansSC-VF.ttf", "C:\\Windows\\Fonts\\msyh.ttc", "C:\\Windows\\Fonts\\msyhbd.ttc", "C:\\Windows\\Fonts\\simsun.ttc" }; foreach (string text in array) { if (!File.Exists(text)) { continue; } try { if (TryCreateTmpFontAsset(new Font(text), Path.GetFileNameWithoutExtension(text))) { Plugin.Log.LogInfo((object)("Loaded Chinese fallback font from font file: " + text)); return true; } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Font file fallback failed for " + text + ": " + ex.Message)); } } return false; } private static void TryLoadSystemFontAsset() { if ((Object)(object)_fallbackFont != (Object)null) { return; } string[] array = new string[4] { "Noto Sans SC", "Source Han Sans SC", "Microsoft YaHei UI", "Microsoft YaHei" }; foreach (string text in array) { try { if (TryCreateTmpFontAsset(Font.CreateDynamicFontFromOSFont(text, 18), text)) { Plugin.Log.LogInfo((object)("Loaded Chinese fallback font from system font: " + text)); ApplyFallbackGlobally(); return; } } catch (Exception ex) { Plugin.Log.LogDebug((object)("System font fallback failed for " + text + ": " + ex.Message)); } } Plugin.Log.LogWarning((object)"No compatible Chinese system font fallback was loaded."); } private static bool TryCreateTmpFontAsset(Font? font, string label) { if ((Object)(object)font == (Object)null) { return false; } _fallbackFont = TMP_FontAsset.CreateFontAsset(font, 90, 9, (GlyphRenderMode)4165, 4096, 4096, (AtlasPopulationMode)1, true); if ((Object)(object)_fallbackFont == (Object)null) { return false; } ((Object)_fallbackFont).name = "V81TestChn_SystemFallback_" + label; _fallbackFont.atlasPopulationMode = (AtlasPopulationMode)1; NormalizeFallbackFontMaterials(); WarmFallbackCharacters(); return true; } public static void ApplyFallback(TMP_Text? text, string? candidateText = null) { if (!((Object)(object)_fallbackFont == (Object)null) && !((Object)(object)((text != null) ? text.font : null) == (Object)null)) { CaptureHealthyBaseline(text); ApplyFallbackToFont(text.font); } } public static void RegisterTextInstance(TMP_Text? text, string stage) { if (!((Object)(object)text == (Object)null)) { if (IsCriticalTextForRepair(text, text.text)) { EnsureFinalRenderRepair(text); } if (ShouldFocusAudit(text.text)) { LogFocusedAudit(stage, text, text.textInfo); } } } public static void ReconcileRenderedText(TMP_Text? text) { } public static void ApplySystemOnlineProbeFix(TMP_Text? text, string stage, string? candidateText = null) { } public static void RepairPostTranslationText(TMP_Text? text, string stage) { if ((Object)(object)text == (Object)null || string.IsNullOrWhiteSpace(text.text)) { return; } if (IsAtmosphereRelayObject((Component?)(object)text)) { ApplyFallbackToFont(text.font); } else if (!IsSystemOnlineRelayObject((Component?)(object)text) && CjkRegex.IsMatch(text.text)) { ApplyFallbackToFont(text.font); if (ShouldRepairReadableCjkTextLight(text)) { RepairReadableCjkTextLight(text, stage); } } } public static void RepairLoadedCjkTextObjects(string stage) { } public static void ApplySystemOnlineProbeFix(Text? text, string stage, string? candidateText = null) { } public static void ApplySystemOnlineProbeFix(TextMesh? text, string stage, string? candidateText = null) { } public static void SanitizeSystemOnlineAssignedColor(TMP_Text? text, ref Color value, string stage) { } public static void RepairSystemOnlineRelayAppearance(TMP_Text? text) { } public static void OnFontAssetAwake(TMP_FontAsset? fontAsset) { if (!((Object)(object)fontAsset == (Object)null)) { ApplyFallbackToFont(fontAsset); NormalizeMaterial(((TMP_Asset)fontAsset).material); } } public static void ReconcileSubMeshMaterial(TMP_SubMeshUI? subMesh) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)subMesh == (Object)null) { return; } TMP_Text textComponent = subMesh.textComponent; if (!((Object)(object)textComponent == (Object)null) && !string.IsNullOrWhiteSpace(textComponent.text) && CjkRegex.IsMatch(textComponent.text)) { EnsureFinalRenderRepair(textComponent); Material fontSharedMaterial = textComponent.fontSharedMaterial; Material sharedMaterial = subMesh.sharedMaterial; Material val = TryGetSubMeshUiMaterial(subMesh, "ReconcileSubMeshMaterial(UI)"); if ((Object)(object)fontSharedMaterial != (Object)null) { SyncMaterialWithPrimary(sharedMaterial, fontSharedMaterial); SyncMaterialWithPrimary(val, fontSharedMaterial); } ApplyFaceColorFromOwner(sharedMaterial, textComponent); ApplyFaceColorFromOwner(val, textComponent); ((Graphic)subMesh).color = ((Graphic)textComponent).color; AuditIfStillDark("ReconcileSubMeshMaterial(UI)", textComponent); } } public static void ReconcileSubMeshMaterial(TMP_SubMesh? subMesh) { if ((Object)(object)subMesh == (Object)null) { return; } TMP_Text textComponent = subMesh.textComponent; if (!((Object)(object)textComponent == (Object)null) && !string.IsNullOrWhiteSpace(textComponent.text) && CjkRegex.IsMatch(textComponent.text)) { EnsureFinalRenderRepair(textComponent); Material fontSharedMaterial = textComponent.fontSharedMaterial; if ((Object)(object)fontSharedMaterial != (Object)null) { SyncMaterialWithPrimary(subMesh.sharedMaterial, fontSharedMaterial); SyncMaterialWithPrimary(subMesh.material, fontSharedMaterial); } ApplyFaceColorFromOwner(subMesh.sharedMaterial, textComponent); ApplyFaceColorFromOwner(subMesh.material, textComponent); AuditIfStillDark("ReconcileSubMeshMaterial(3D)", textComponent); } } public static void SanitizeAssignedColor(TMP_Text? text, ref Color value, string? candidateText = null) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)text == (Object)null) { return; } string text2 = (string.IsNullOrWhiteSpace(candidateText) ? text.text : candidateText); if (string.IsNullOrWhiteSpace(text2) || IsAtmosphereRelayObject((Component?)(object)text)) { return; } int instanceID = ((Object)text).GetInstanceID(); if (!BaselineColorByInstance.ContainsKey(instanceID)) { TryStoreHealthyBaseline(instanceID, ((Graphic)text).color); } if (!CjkRegex.IsMatch(text2)) { TryStoreHealthyBaseline(instanceID, value); } else { if (!ShouldRepairReadableCjkTextLight(text)) { return; } EnsureFinalRenderRepair(text); if (TryGetHealthyBaseline(instanceID, out var baseline)) { if (value.a < 0.999f || IsNearlyBlack(value)) { value = new Color(baseline.r, baseline.g, baseline.b, baseline.a); } } else if (value.a < 0.35f || IsNearlyBlack(value)) { value = new Color(1f, 1f, 1f, 1f); } } } public static void ApplyFallbackGlobally() { if (!((Object)(object)_fallbackFont == (Object)null) && !_globalFallbackApplied) { List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets; if (fallbackFontAssets != null && !fallbackFontAssets.Contains(_fallbackFont)) { fallbackFontAssets.Add(_fallbackFont); } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); for (int i = 0; i < array.Length; i++) { ApplyFallbackToFont(array[i]); } _globalFallbackApplied = true; Plugin.Log.LogInfo((object)("Applied Chinese fallback font globally: " + ((Object)_fallbackFont).name)); } } private static void ApplyFallbackToFont(TMP_FontAsset? fontAsset) { if (!((Object)(object)_fallbackFont == (Object)null) && !((Object)(object)fontAsset == (Object)null) && fontAsset != _fallbackFont) { if (fontAsset.fallbackFontAssetTable == null) { fontAsset.fallbackFontAssetTable = new List<TMP_FontAsset>(); } if (!fontAsset.fallbackFontAssetTable.Contains(_fallbackFont)) { fontAsset.fallbackFontAssetTable.Add(_fallbackFont); } } } private static void WarmFallbackCharacters() { if ((Object)(object)_fallbackFont == (Object)null) { return; } string text = ((_pluginDir == null) ? null : Path.Combine(_pluginDir, "V81TestChn", "fonts", "zh-cn-charset.txt")); if (text == null || !File.Exists(text)) { text = Path.Combine(PathsRelativePluginRoot(), "fonts", "zh-cn-charset.txt"); } if (!File.Exists(text)) { return; } try { string source = File.ReadAllText(text); source = new string(source.Where((char c) => !char.IsControl(c)).Distinct().ToArray()); string text2 = default(string); if (_fallbackFont.TryAddCharacters(source, ref text2, false) && string.IsNullOrEmpty(text2)) { Plugin.Log.LogInfo((object)$"Prewarmed Chinese fallback font characters: {source.Length}"); } else if (!string.IsNullOrEmpty(text2)) { Plugin.Log.LogWarning((object)$"Chinese fallback font missing {text2.Length} prewarm characters."); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("Failed to prewarm Chinese fallback characters: " + ex.Message)); } } private static string PathsRelativePluginRoot() { return _pluginDir ?? Paths.PluginPath; } private static void NormalizeFallbackFontMaterials() { if (!((Object)(object)_fallbackFont == (Object)null)) { NormalizeMaterial(((TMP_Asset)_fallbackFont).material); } } private static void NormalizeMaterial(Material? material) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty(ShaderUtilities.ID_FaceColor)) { material.SetColor(ShaderUtilities.ID_FaceColor, Color.white); } if (material.HasProperty(ShaderUtilities.ID_OutlineWidth)) { material.SetFloat(ShaderUtilities.ID_OutlineWidth, 0f); } if (material.HasProperty(ShaderUtilities.ID_OutlineColor)) { Color color = material.GetColor(ShaderUtilities.ID_OutlineColor); material.SetColor(ShaderUtilities.ID_OutlineColor, new Color(color.r, color.g, color.b, 0f)); } if (material.HasProperty(ShaderUtilities.ID_FaceDilate)) { material.SetFloat(ShaderUtilities.ID_FaceDilate, 0f); } if (material.HasProperty(ShaderUtilities.ID_UnderlayColor)) { Color color2 = material.GetColor(ShaderUtilities.ID_UnderlayColor); material.SetColor(ShaderUtilities.ID_UnderlayColor, new Color(color2.r, color2.g, color2.b, 0f)); } if (material.HasProperty(ShaderUtilities.ID_UnderlaySoftness)) { material.SetFloat(ShaderUtilities.ID_UnderlaySoftness, 0f); } if (material.HasProperty(ShaderUtilities.ID_UnderlayDilate)) { material.SetFloat(ShaderUtilities.ID_UnderlayDilate, 0f); } material.DisableKeyword("UNDERLAY_ON"); material.DisableKeyword("UNDERLAY_INNER"); material.DisableKeyword("OUTLINE_ON"); } } private static void ImproveReadabilityForOverlayChinese(TMP_Text text, string? candidateText) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)text == (Object)null) { return; } string text2 = (string.IsNullOrWhiteSpace(candidateText) ? text.text : candidateText); if (string.IsNullOrWhiteSpace(text2)) { return; } int instanceID = ((Object)text).GetInstanceID(); if (!BaselineColorByInstance.ContainsKey(instanceID)) { TryStoreHealthyBaseline(instanceID, ((Graphic)text).color); } if (!CjkRegex.IsMatch(text2)) { TryStoreHealthyBaseline(instanceID, ((Graphic)text).color); return; } if (IsAtmosphereHeader(text2)) { ApplyAtmosphereHeaderStyle(text); return; } SyncSubMeshMaterials(text); Color color = ((Graphic)text).color; if (color.a < 0.999f || IsNearlyBlack(color)) { if (TryGetHealthyBaseline(instanceID, out var baseline)) { ((Graphic)text).color = new Color(baseline.r, baseline.g, baseline.b, baseline.a); } else { ((Graphic)text).color = ((color.a < 0.999f || IsNearlyBlack(color)) ? new Color(1f, 1f, 1f, 1f) : new Color(color.r, color.g, color.b, 1f)); } } } private static void RepairReadableCjkTextLight(TMP_Text text, string stage) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)text == (Object)null) && !string.IsNullOrWhiteSpace(text.text) && CjkRegex.IsMatch(text.text)) { CaptureHealthyBaseline(text); Color val = ResolveExpectedColor(text); if (val.a < 0.999f) { val.a = 1f; } bool flag = false; if (NeedsGraphicColorRepair(((Graphic)text).color, val)) { ((Graphic)text).color = val; flag = true; } bool flag2 = RepairReadableFaceMaterials(text, val); if (HasAnomalousCjkVertex(text)) { FixCjkVertexColors(text); } if ((flag || flag2) && _postTranslationProbeLogBudget > 0) { _postTranslationProbeLogBudget--; string text2 = (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name : string.Empty); Plugin.Log.LogWarning((object)$"PostTranslationCjkRepairLight[{stage}] name={((Object)text).name}, font='{text2}', after={((Graphic)text).color}, text='{TrimAuditText(text.text)}'"); } } } private static bool ShouldRepairReadableCjkTextLight(TMP_Text? text) { if ((Object)(object)text == (Object)null) { return false; } if (!IsSystemOnlineRelayObject((Component?)(object)text)) { IsAtmosphereRelayObject((Component?)(object)text); } return false; } private static bool IsNearlyBlack(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (color.r < 0.08f && color.g < 0.08f) { return color.b < 0.08f; } return false; } private static bool IsHealthyColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!IsNearlyBlack(color)) { return color.a >= 0.35f; } return false; } private static bool TryGetHealthyBaseline(int textId, out Color baseline) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (BaselineColorByInstance.TryGetValue(textId, out baseline) && IsHealthyColor(baseline)) { return true; } baseline = default(Color); return false; } private static void TryStoreHealthyBaseline(int textId, Color candidate) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (IsHealthyColor(candidate)) { BaselineColorByInstance[textId] = candidate; } } private static void SyncSubMeshMaterials(TMP_Text text) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) Material fontSharedMaterial = text.fontSharedMaterial; if (!((Object)(object)fontSharedMaterial == (Object)null)) { TMP_SubMeshUI[] componentsInChildren = ((Component)text).GetComponentsInChildren<TMP_SubMeshUI>(true); foreach (TMP_SubMeshUI obj in componentsInChildren) { SyncMaterialWithPrimary(obj.sharedMaterial, fontSharedMaterial); SyncMaterialWithPrimary(TryGetSubMeshUiMaterial(obj, "SyncSubMeshMaterials"), fontSharedMaterial); ((Graphic)obj).color = ((Graphic)text).color; } TMP_SubMesh[] componentsInChildren2 = ((Component)text).GetComponentsInChildren<TMP_SubMesh>(true); foreach (TMP_SubMesh obj2 in componentsInChildren2) { SyncMaterialWithPrimary(obj2.sharedMaterial, fontSharedMaterial); SyncMaterialWithPrimary(obj2.material, fontSharedMaterial); } } } private static void FixCjkVertexColors(TMP_Text text) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (text.textInfo == null || string.IsNullOrEmpty(text.text) || !CjkRegex.IsMatch(text.text)) { return; } Color32 val = Color32.op_Implicit(ResolveExpectedColor(text)); TMP_TextInfo textInfo = text.textInfo; bool flag = false; for (int i = 0; i < textInfo.cha