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 v3.2.9
BepInEx/plugins/V81TestChn/V81TestChn.dll
Decompiled a week 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.Globalization; using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using TMPro; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.TextCore; using UnityEngine.TextCore.LowLevel; using UnityEngine.UI; using UnityEngine.Video; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [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+d32fd5429c8f37de0d7070c097765cf20cabdf1a")] [assembly: AssemblyProduct("V81TestChn")] [assembly: AssemblyTitle("V81TestChn")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 { private enum NativeTextRole { None, SystemOnline, EnteringAtmosphere } private readonly struct CachedNativeTextRole { public int ParentId { get; } public NativeTextRole Role { get; } public CachedNativeTextRole(int parentId, NativeTextRole role) { ParentId = parentId; Role = role; } } private const int NativeTextRoleCacheLimit = 16384; 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 HUDManager? _systemOnlineWatcherOwner; private static HUDManager? _fixedSceneLabelWatcherOwner; private static bool _fixedSceneLabelSceneLoadedSubscribed; private static string _fixedSceneLabelSceneLoadedStage = "SceneLoaded"; private static readonly BoundedCache<int, CachedNativeTextRole> NativeTextRoleCache = new BoundedCache<int, CachedNativeTextRole>(16384); 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) { if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.LogRuntimeLocalizationEvent("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); } else if (Plugin.RuntimeLocalizationLogsEnabled) { 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)) { ResetSystemOnlineWatcherIfStale(hudManager); if (_systemOnlineWatcher == null) { _systemOnlineWatcherOwner = hudManager; _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) { if (Plugin.RuntimeLocalizationLogsEnabled) { 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) { if (Plugin.RuntimeLocalizationLogsEnabled) { 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) && GetNativeTextRole(text) == NativeTextRole.EnteringAtmosphere) { 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) && SyncFixedSceneLabelsInRelayScene(stage + ".initial") <= 0) { _fixedSceneLabelWatcherOwner = hudManager; _fixedSceneLabelSceneLoadedStage = stage; if (!_fixedSceneLabelSceneLoadedSubscribed) { SceneManager.sceneLoaded += OnRelaySceneLoadedForFixedLabels; _fixedSceneLabelSceneLoadedSubscribed = true; } } } public static void Shutdown() { try { if (_systemOnlineWatcher != null && (Object)(object)_systemOnlineWatcherOwner != (Object)null) { ((MonoBehaviour)_systemOnlineWatcherOwner).StopCoroutine(_systemOnlineWatcher); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("NativeRelay shutdown failed stopping SystemOnline watcher: " + ex.GetType().Name + ": " + ex.Message)); } try { if (_fixedSceneLabelWatcher != null && (Object)(object)_fixedSceneLabelWatcherOwner != (Object)null) { ((MonoBehaviour)_fixedSceneLabelWatcherOwner).StopCoroutine(_fixedSceneLabelWatcher); } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("NativeRelay shutdown failed stopping fixed scene label watcher: " + ex2.GetType().Name + ": " + ex2.Message)); } _systemOnlineWatcher = null; _fixedSceneLabelWatcher = null; _systemOnlineWatcherOwner = null; _fixedSceneLabelWatcherOwner = null; if (_fixedSceneLabelSceneLoadedSubscribed) { SceneManager.sceneLoaded -= OnRelaySceneLoadedForFixedLabels; _fixedSceneLabelSceneLoadedSubscribed = false; } _fixedSceneLabelSceneLoadedStage = "SceneLoaded"; NativeTextRoleCache.Clear(); } private static void OnRelaySceneLoadedForFixedLabels(Scene scene, LoadSceneMode mode) { if (string.Equals(((Scene)(ref scene)).name, "SampleSceneRelay", StringComparison.Ordinal)) { SyncFixedSceneLabelsInRelayScene(_fixedSceneLabelSceneLoadedStage + ".scene-loaded"); SceneManager.sceneLoaded -= OnRelaySceneLoadedForFixedLabels; _fixedSceneLabelSceneLoadedSubscribed = false; _fixedSceneLabelWatcherOwner = null; _fixedSceneLabelSceneLoadedStage = "SceneLoaded"; } } private static void ResetSystemOnlineWatcherIfStale(HUDManager currentHud) { if (_systemOnlineWatcher == null) { _systemOnlineWatcherOwner = null; } else if (!((Object)(object)_systemOnlineWatcherOwner == (Object)(object)currentHud)) { StopStaleWatcher(_systemOnlineWatcherOwner, _systemOnlineWatcher, "SystemOnline"); _systemOnlineWatcher = null; _systemOnlineWatcherOwner = null; } } private static void ResetFixedSceneLabelWatcherIfStale(HUDManager currentHud) { if (_fixedSceneLabelWatcher == null) { _fixedSceneLabelWatcherOwner = null; } else if (!((Object)(object)_fixedSceneLabelWatcherOwner == (Object)(object)currentHud)) { StopStaleWatcher(_fixedSceneLabelWatcherOwner, _fixedSceneLabelWatcher, "FixedSceneLabel"); _fixedSceneLabelWatcher = null; _fixedSceneLabelWatcherOwner = null; } } private static void StopStaleWatcher(HUDManager? owner, Coroutine watcher, string label) { if ((Object)(object)owner == (Object)null) { return; } try { ((MonoBehaviour)owner).StopCoroutine(watcher); } catch (Exception ex) { Plugin.Log.LogWarning((object)("NativeRelay stale " + label + " watcher stop failed: " + ex.GetType().Name + ": " + ex.Message)); } } public static void TryReplaceSystemOnlineText(TMP_Text? text, string stage) { if ((Object)(object)text == (Object)null || !MightBeNativeRelayCandidate(text)) { return; } switch (GetNativeTextRole(text)) { case NativeTextRole.SystemOnline: ApplySystemOnlineNativeTranslation(text, stage); return; case NativeTextRole.EnteringAtmosphere: ApplyEnteringAtmosphereNativeTranslation(text, stage); return; } 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"); if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.LogRuntimeLocalizationEvent("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) { } private static bool MightBeNativeRelayCandidate(TMP_Text text) { if (string.Equals(((Object)text).name, "TipLeft1", StringComparison.OrdinalIgnoreCase) || string.Equals(((Object)text).name, "LoadText", StringComparison.OrdinalIgnoreCase)) { return true; } string text2 = text.text; if (string.IsNullOrWhiteSpace(text2) || text2.Length > 160) { return false; } int i; for (i = 0; i < text2.Length && char.IsWhiteSpace(text2[i]); i++) { } if (i >= text2.Length) { return false; } switch (char.ToUpperInvariant(text2[i])) { case '(': case 'D': case 'E': case 'F': case 'H': case 'P': case 'T': case 'Y': case '[': return true; default: return false; } } 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"); if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.LogRuntimeLocalizationEvent("NativeRelay[" + stage + "] target=SystemOnline action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text); } } private static IEnumerator WaitForSystemOnlineTitle(HUDManager hudManager, string stage) { float elapsed = 0f; while ((Object)(object)hudManager != (Object)null && elapsed < 12f) { TMP_Text text = FindSystemOnlineTitleByHudPath(hudManager); if (IsExactSystemOnlineTitle(text)) { ApplySystemOnlineNativeTranslation(text, stage + ".watcher"); _systemOnlineWatcher = null; _systemOnlineWatcherOwner = null; yield break; } yield return (object)new WaitForSeconds(0.25f); elapsed += 0.25f; } if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + ".watcher] target=SystemOnline action=timeout")); } _systemOnlineWatcher = null; _systemOnlineWatcherOwner = null; } private static IEnumerator WaitForFixedSceneLabels(string stage) { for (float elapsed = 0f; elapsed < 8f; elapsed += 0.5f) { if (SyncFixedSceneLabelsInRelayScene(stage + ".relay-scene") > 0) { _fixedSceneLabelWatcher = null; _fixedSceneLabelWatcherOwner = null; yield break; } yield return (object)new WaitForSeconds(0.5f); } if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.Log.LogWarning((object)("NativeRelay[" + stage + ".relay-scene] target=FixedSceneLabel action=timeout")); } _fixedSceneLabelWatcher = null; _fixedSceneLabelWatcherOwner = null; } 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? FindSystemOnlineTitleByHudPath(HUDManager? hudManager) { if ((Object)(object)((hudManager != null) ? ((Component)hudManager).transform : null) == (Object)null) { return null; } Transform val = ((Component)hudManager).transform.Find("BottomMiddle/SystemsOnline/TipLeft1"); if (!((Object)(object)val == (Object)null)) { return ((Component)val).GetComponent<TMP_Text>(); } return null; } 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 GetNativeTextRole(text) == NativeTextRole.SystemOnline; } 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) { return GetNativeTextRole(text) == NativeTextRole.EnteringAtmosphere; } 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) && !string.Equals(a, "风险级别:", StringComparison.Ordinal) && !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++; if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.LogRuntimeLocalizationEvent($"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.TryTranslateKnownDynamicTextTargeted(DynamicTextDomain.PlanetInfo, text.text, out string translated) || TranslationService.TryTranslate(text.text, out translated)) && !string.IsNullOrWhiteSpace(translated)) { if (!string.Equals(text.text, translated, StringComparison.Ordinal)) { text.text = translated; } FontFallbackService.ApplyFallback(text, translated); if (Plugin.RuntimeLocalizationLogsEnabled) { Plugin.LogRuntimeLocalizationEvent("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) { return GetNativeTextRole(text) == NativeTextRole.SystemOnline; } private static NativeTextRole GetNativeTextRole(TMP_Text? text) { if ((Object)(object)text == (Object)null) { return NativeTextRole.None; } if (TryGetCachedNativeTextRole(text, out var role)) { return role; } role = ResolveNativeTextRole(text); CacheNativeTextRole(text, role); return role; } private static bool TryGetCachedNativeTextRole(TMP_Text text, out NativeTextRole role) { int parentInstanceId = GetParentInstanceId(text.transform); if (NativeTextRoleCache.TryGetValue(((Object)text).GetInstanceID(), out var value) && value.ParentId == parentInstanceId) { role = value.Role; return true; } role = NativeTextRole.None; return false; } private static NativeTextRole ResolveNativeTextRole(TMP_Text text) { if (string.Equals(((Object)text).name, "LoadText", StringComparison.OrdinalIgnoreCase) && HasNamedAncestor(text.transform, "LoadingText")) { return NativeTextRole.EnteringAtmosphere; } if (string.Equals(((Object)text).name, "TipLeft1", StringComparison.OrdinalIgnoreCase) && IsSystemOnlinePath(text.transform)) { return NativeTextRole.SystemOnline; } return NativeTextRole.None; } private static void CacheNativeTextRole(TMP_Text text, NativeTextRole role) { int instanceID = ((Object)text).GetInstanceID(); NativeTextRoleCache.Set(instanceID, new CachedNativeTextRole(GetParentInstanceId(text.transform), role), RuntimePerformanceSettings.ComponentTextCacheLimit); } private static int GetParentInstanceId(Transform? transform) { if (!((Object)(object)((transform != null) ? transform.parent : null) == (Object)null)) { return ((Object)transform.parent).GetInstanceID(); } return 0; } } internal static class ClipboardManualLocalizationService { private sealed class TextureSpec { public string FileName { get; } public int Width { get; } public int Height { get; } public bool PrecompressedBc3 { get; } public TextureSpec(string fileName, int width = 0, int height = 0, bool precompressedBc3 = false) { FileName = fileName; Width = width; Height = height; PrecompressedBc3 = precompressedBc3; } } private sealed class RendererState { public Renderer Renderer { get; } public Material[] OriginalMaterials { get; } public List<Material> LocalizedMaterials { get; } public RendererState(Renderer renderer, Material[] originalMaterials, List<Material> localizedMaterials) { Renderer = renderer; OriginalMaterials = originalMaterials; LocalizedMaterials = localizedMaterials; } } private const int MaxTextureFileBytes = 8388608; private const int MaxTextureDimension = 4096; private static readonly Dictionary<string, TextureSpec> TextureFiles = new Dictionary<string, TextureSpec>(StringComparer.OrdinalIgnoreCase) { ["Manual1"] = new TextureSpec("ClipboardManualPage1.png"), ["Manual2"] = new TextureSpec("ClipboardManualPage2.png"), ["Manual3"] = new TextureSpec("ClipboardManualPage3.png"), ["Manual4"] = new TextureSpec("ClipboardManualPage4.png"), ["CruiserManual1"] = new TextureSpec("CruiserManualPage1.bc3", 900, 1260, precompressedBc3: true), ["CruiserManual2"] = new TextureSpec("CruiserManualPage2.bc3", 900, 1260, precompressedBc3: true), ["CruiserManual3"] = new TextureSpec("CruiserManualPage3.bc3", 900, 1260, precompressedBc3: true), ["CruiserManual4"] = new TextureSpec("CruiserManualPage4.bc3", 900, 1260, precompressedBc3: true) }; private static readonly Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> FailedTextures = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<int, RendererState> RendererStates = new Dictionary<int, RendererState>(); private static string _textureDirectory = string.Empty; private static bool _initialized; public static void Initialize(string pluginDir) { _textureDirectory = Path.Combine(pluginDir, "textures"); _initialized = true; FailedTextures.Clear(); } public static void Apply(GrabbableObject? grabbableObject) { if (!_initialized || Plugin.IsRuntimeShuttingDown) { return; } ClipboardItem val = (ClipboardItem)(object)((grabbableObject is ClipboardItem) ? grabbableObject : null); if (val == null) { return; } Animator clipboardAnimator = val.clipboardAnimator; if (!((Object)(object)clipboardAnimator == (Object)null)) { PruneDestroyedRendererStates(); SkinnedMeshRenderer[] componentsInChildren = ((Component)clipboardAnimator).GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyToRenderer((Renderer?)(object)componentsInChildren[i]); } } } public static void ApplyVehicle(VehicleController? vehicle) { if (_initialized && !Plugin.IsRuntimeShuttingDown && !((Object)(object)vehicle == (Object)null)) { PruneDestroyedRendererStates(); Renderer[] componentsInChildren = ((Component)vehicle).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyToRenderer(componentsInChildren[i]); } } } public static void Shutdown() { foreach (RendererState value in RendererStates.Values) { try { if ((Object)(object)value.Renderer != (Object)null) { value.Renderer.sharedMaterials = value.OriginalMaterials; } } catch { } foreach (Material localizedMaterial in value.LocalizedMaterials) { DestroyUnityObject((Object?)(object)localizedMaterial); } } RendererStates.Clear(); foreach (Texture2D value2 in Textures.Values) { DestroyUnityObject((Object?)(object)value2); } Textures.Clear(); FailedTextures.Clear(); _textureDirectory = string.Empty; _initialized = false; } public static void OnSceneUnloaded() { PruneDestroyedRendererStates(); } private static void ApplyToRenderer(Renderer? renderer) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown if ((Object)(object)renderer == (Object)null) { return; } int instanceID = ((Object)renderer).GetInstanceID(); if (RendererStates.ContainsKey(instanceID)) { return; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { return; } Material[] array = (Material[])sharedMaterials.Clone(); List<Material> list = new List<Material>(); for (int i = 0; i < sharedMaterials.Length; i++) { Material val = sharedMaterials[i]; if (!((Object)(object)val == (Object)null) && TryResolveTexture(((Object)val).name, out Texture2D texture)) { Material val2 = new Material(val) { name = NormalizeMaterialName(((Object)val).name) + " (zh-CN)" }; SetTexture(val2, texture); array[i] = val2; list.Add(val2); } } if (list.Count != 0) { renderer.sharedMaterials = array; RendererStates[instanceID] = new RendererState(renderer, sharedMaterials, list); } } private static void PruneDestroyedRendererStates() { List<int> list = null; foreach (KeyValuePair<int, RendererState> rendererState in RendererStates) { if ((Object)(object)rendererState.Value.Renderer != (Object)null) { continue; } if (list == null) { list = new List<int>(); } list.Add(rendererState.Key); foreach (Material localizedMaterial in rendererState.Value.LocalizedMaterials) { DestroyUnityObject((Object?)(object)localizedMaterial); } } if (list == null) { return; } foreach (int item in list) { RendererStates.Remove(item); } } private static bool TryResolveTexture(string? materialName, out Texture2D texture) { string text = NormalizeMaterialName(materialName); if (Textures.TryGetValue(text, out texture)) { return true; } if (FailedTextures.Contains(text) || !TextureFiles.TryGetValue(text, out TextureSpec value)) { texture = null; return false; } Texture2D val = LoadTexture(text, value); if ((Object)(object)val == (Object)null) { FailedTextures.Add(text); texture = null; return false; } Textures[text] = val; texture = val; return true; } private static string NormalizeMaterialName(string? materialName) { if (string.IsNullOrWhiteSpace(materialName)) { return string.Empty; } string text = materialName.Trim(); if (text.EndsWith(" (Instance)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - " (Instance)".Length); } if (text.EndsWith(" (zh-CN)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - " (zh-CN)".Length); } return text; } private static void SetTexture(Material material, Texture2D texture) { if (material.HasProperty("_BaseColorMap")) { material.SetTexture("_BaseColorMap", (Texture)(object)texture); } if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", (Texture)(object)texture); } material.mainTexture = (Texture)(object)texture; } private static Texture2D? LoadTexture(string materialName, TextureSpec spec) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown string fileName = spec.FileName; string text = Path.Combine(_textureDirectory, fileName); Texture2D val = null; try { FileInfo fileInfo = new FileInfo(text); if (!fileInfo.Exists) { Plugin.Log.LogWarning((object)("Clipboard manual texture is missing: " + fileName)); return null; } if (fileInfo.Length <= 0 || (!spec.PrecompressedBc3 && fileInfo.Length > 8388608)) { Plugin.Log.LogWarning((object)$"Clipboard manual texture has an invalid file size: {fileName} ({fileInfo.Length} bytes)"); return null; } if (spec.PrecompressedBc3) { val = PrecompressedTextureLoader.LoadBc3(text, spec.Width, spec.Height, mipChain: false, out string error); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("Clipboard manual texture could not be loaded: " + fileName + " (" + error + ")")); return null; } } else { byte[] array = File.ReadAllBytes(text); val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array, true)) { Plugin.Log.LogWarning((object)("Clipboard manual texture could not be decoded: " + fileName)); DestroyUnityObject((Object?)(object)val); return null; } if (((Texture)val).width <= 0 || ((Texture)val).height <= 0 || ((Texture)val).width > 4096 || ((Texture)val).height > 4096) { Plugin.Log.LogWarning((object)$"Clipboard manual texture dimensions are invalid: {fileName} ({((Texture)val).width}x{((Texture)val).height})"); DestroyUnityObject((Object?)(object)val); return null; } } ((Object)val).name = materialName + " (zh-CN)"; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return val; } catch (Exception ex) { DestroyUnityObject((Object?)(object)val); Plugin.Log.LogWarning((object)("Clipboard manual texture load failed for " + fileName + ": " + ex.GetType().Name + ": " + ex.Message)); return null; } } private static void DestroyUnityObject(Object? value) { if (!(value == (Object)null)) { if (Application.isPlaying) { Object.Destroy(value); } else { Object.DestroyImmediate(value); } } } } internal static class EnvironmentTextureLocalizationService { private sealed class TextureSpec { public string OriginalName { get; } public string FileName { get; } public int Width { get; } public int Height { get; } public bool PrecompressedBc1 { get; } public bool PrecompressedBc3 { get; } public bool PrecompressedBc7 { get; } public bool MipChain { get; } public TextureSpec(string originalName, string fileName, int width, int height, bool precompressedBc1 = false, bool precompressedBc3 = false, bool precompressedBc7 = false, bool mipChain = true) { OriginalName = originalName; FileName = fileName; Width = width; Height = height; PrecompressedBc1 = precompressedBc1; PrecompressedBc3 = precompressedBc3; PrecompressedBc7 = precompressedBc7; MipChain = mipChain; } } private sealed class RendererState { public Renderer Renderer { get; } public Material[] OriginalMaterials { get; } public List<int> LocalizedMaterialIds { get; } public RendererState(Renderer renderer, Material[] originalMaterials, List<int> localizedMaterialIds) { Renderer = renderer; OriginalMaterials = originalMaterials; LocalizedMaterialIds = localizedMaterialIds; } } private sealed class MaterialState { public WeakReference<Material> Original { get; } public Material Localized { get; } public MaterialState(Material original, Material localized) { Original = new WeakReference<Material>(original); Localized = localized; } public bool HasOriginal(Material material) { if (Original.TryGetTarget(out Material target) && (Object)(object)target != (Object)null) { return (Object)(object)target == (Object)(object)material; } return false; } public bool HasLiveOriginal() { if (Original.TryGetTarget(out Material target)) { return (Object)(object)target != (Object)null; } return false; } } private sealed class FireExitState { public Renderer Renderer { get; } public Material[] OriginalMaterials { get; } public GameObject Overlay { get; } public FireExitState(Renderer renderer, Material[] originalMaterials, GameObject overlay) { Renderer = renderer; OriginalMaterials = originalMaterials; Overlay = overlay; } } private const int MaxTextureFileBytes = 16777216; private const string FireExitLabelFileName = "FireExitDoorLabelLocalized.png"; private static readonly string[] TexturePropertyNames = new string[2] { "_BaseColorMap", "_MainTex" }; private static readonly List<Renderer> RendererScanBuffer = new List<Renderer>(); private static readonly HashSet<int> ActiveLocalizedMaterialIds = new HashSet<int>(); private static readonly HashSet<int> UnchangedMaterialIdsThisPass = new HashSet<int>(); private static readonly Dictionary<string, TextureSpec> TextureSpecs = new Dictionary<string, TextureSpec>(StringComparer.OrdinalIgnoreCase) { ["posters"] = new TextureSpec("posters", "ShipPostersLocalized.png", 1024, 1024), ["TipsPoster2"] = new TextureSpec("TipsPoster2", "ShipTipsPosterLocalized.png", 796, 1024), ["ToiletPaperTex"] = new TextureSpec("ToiletPaperTex", "ToiletPaperTexLocalized.png", 1024, 1024), ["CashRegisterTex"] = new TextureSpec("CashRegisterTex", "CashRegisterTexLocalized.png", 1024, 1024), ["FlashbangBottleTexture"] = new TextureSpec("FlashbangBottleTexture", "FlashbangBottleTextureLocalized.png", 1024, 1024), ["WelcomeMatTex"] = new TextureSpec("WelcomeMatTex", "WelcomeMatTexLocalized.png", 1024, 1024), ["AirhornTex"] = new TextureSpec("AirhornTex", "AirhornTexLocalized.png", 512, 512), ["TetraChemicalTex"] = new TextureSpec("TetraChemicalTex", "TetraChemicalTexLocalized.png", 2048, 2048), ["SprayCanTex"] = new TextureSpec("SprayCanTex", "SprayCanTexLocalized.png", 1024, 1024), ["StopSignTex"] = new TextureSpec("StopSignTex", "StopSignTexLocalized.png", 1024, 1024), ["YieldSignTex"] = new TextureSpec("YieldSignTex", "YieldSignTexLocalized.png", 512, 512), ["SodaCanTex1"] = new TextureSpec("SodaCanTex1", "SodaCanTex1Localized.png", 1024, 1024), ["ToothpasteTex"] = new TextureSpec("ToothpasteTex", "ToothpasteTexLocalized.png", 1024, 1024), ["WeedKillerBottleTex"] = new TextureSpec("WeedKillerBottleTex", "WeedKillerBottleTexLocalized.png", 1024, 1024), ["WhoopieCushionTex"] = new TextureSpec("WhoopieCushionTex", "WhoopieCushionTexLocalized.png", 1024, 1024), ["YellowMineDoorTex"] = new TextureSpec("YellowMineDoorTex", "YellowMineDoorTexLocalized.png", 1024, 1024), ["ChemicalBottle1"] = new TextureSpec("ChemicalBottle1", "ChemicalBottle1Localized.png", 1024, 1024), ["powerBoxTextures"] = new TextureSpec("powerBoxTextures", "powerBoxTexturesLocalized.png", 1024, 820), ["PlayerLevelStickers"] = new TextureSpec("PlayerLevelStickers", "PlayerLevelStickersLocalized.png", 256, 512), ["PlayerLevelStickers 1"] = new TextureSpec("PlayerLevelStickers 1", "PlayerVipEmployeeStickerLocalized.png", 512, 128), ["CompanyCruiserCombined4Diffuse 1"] = new TextureSpec("CompanyCruiserCombined4Diffuse 1", "CompanyCruiserDestroyedDiffuseLocalized.dxt1", 4096, 4096, precompressedBc1: true), ["CompanyCruiserCombined4DiffuseDirtyV2"] = new TextureSpec("CompanyCruiserCombined4DiffuseDirtyV2", "CompanyCruiserIntactDiffuseLocalized.bc7", 4096, 4096, precompressedBc1: false, precompressedBc3: false, precompressedBc7: true) }; private static readonly Dictionary<string, Texture2D> LocalizedTextures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> FailedTextures = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<int, RendererState> RendererStates = new Dictionary<int, RendererState>(); private static readonly Dictionary<int, MaterialState> MaterialStates = new Dictionary<int, MaterialState>(); private static readonly Dictionary<int, FireExitState> FireExitStates = new Dictionary<int, FireExitState>(); private static Texture2D? _fireExitLabelTexture; private static Material? _fireExitLabelMaterial; private static Material? _fireExitHiddenMaterial; private static Mesh? _fireExitOverlayMesh; private static string _textureDirectory = string.Empty; private static bool _initialized; public static void Initialize(string pluginDir) { _textureDirectory = Path.Combine(pluginDir, "textures"); _initialized = true; } public static void ApplyShipEnvironment(StartOfRound? startOfRound) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!CanApply() || (Object)(object)startOfRound == (Object)null) { return; } PruneDestroyedRendererStates(); PruneUnusedMaterialStates(); Scene scene = ((Component)startOfRound).gameObject.scene; if (!((Scene)(ref scene)).IsValid() || !((Scene)(ref scene)).isLoaded) { return; } GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if ((Object)(object)val == (Object)null) { continue; } RendererScanBuffer.Clear(); val.GetComponentsInChildren<Renderer>(true, RendererScanBuffer); foreach (Renderer item in RendererScanBuffer) { ApplyToRenderer(item); } } RendererScanBuffer.Clear(); } public static void ApplyVehicle(VehicleController? vehicle) { if (!CanApply() || (Object)(object)vehicle == (Object)null) { return; } PruneDestroyedRendererStates(); PruneUnusedMaterialStates(); RendererScanBuffer.Clear(); ((Component)vehicle).GetComponentsInChildren<Renderer>(false, RendererScanBuffer); foreach (Renderer item in RendererScanBuffer) { ApplyToRenderer(item); } RendererScanBuffer.Clear(); } public static void ApplyLevelEnvironment(RoundManager? roundManager) { //IL_0032: 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) if (!CanApply() || (Object)(object)roundManager == (Object)null) { return; } PruneDestroyedRendererStates(); PruneDestroyedFireExitStates(); PruneUnusedMaterialStates(); UnchangedMaterialIdsThisPass.Clear(); try { for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (!((Scene)(ref sceneAt)).IsValid() || !((Scene)(ref sceneAt)).isLoaded) { continue; } GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if ((Object)(object)val == (Object)null) { continue; } RendererScanBuffer.Clear(); val.GetComponentsInChildren<Renderer>(true, RendererScanBuffer); foreach (Renderer item in RendererScanBuffer) { ApplyToRenderer(item, cacheUnchangedMaterials: true); TryApplyFireExitDoor(item); } } } } finally { RendererScanBuffer.Clear(); UnchangedMaterialIdsThisPass.Clear(); } } public static void ApplyGrabbableObject(GrabbableObject? grabbableObject) { if (!CanApply() || (Object)(object)grabbableObject == (Object)null || !IsLocalizedScrap(((Object)((Component)grabbableObject).gameObject).name)) { return; } PruneDestroyedRendererStates(); PruneUnusedMaterialStates(); RendererScanBuffer.Clear(); ((Component)grabbableObject).GetComponentsInChildren<Renderer>(true, RendererScanBuffer); foreach (Renderer item in RendererScanBuffer) { ApplyToRenderer(item); } RendererScanBuffer.Clear(); } public static void ApplyShipDecoration(AutoParentToShip? shipDecoration) { if (!CanApply() || (Object)(object)shipDecoration == (Object)null || !IsLocalizedShipDecoration(((Object)((Component)shipDecoration).gameObject).name)) { return; } PruneDestroyedRendererStates(); PruneUnusedMaterialStates(); RendererScanBuffer.Clear(); ((Component)shipDecoration).GetComponentsInChildren<Renderer>(true, RendererScanBuffer); foreach (Renderer item in RendererScanBuffer) { ApplyToRenderer(item); } RendererScanBuffer.Clear(); } public static void ApplyPlayerBadges(PlayerControllerB? playerController) { if (CanApply() && !((Object)(object)playerController == (Object)null)) { PruneDestroyedRendererStates(); PruneUnusedMaterialStates(); ApplyToRenderer(((Object)(object)playerController.playerBadgeMesh != (Object)null) ? ((Component)playerController.playerBadgeMesh).GetComponent<Renderer>() : null); ApplyToRenderer((Renderer?)(object)playerController.playerBetaBadgeMesh); } } public static void Shutdown() { foreach (RendererState value in RendererStates.Values) { try { if ((Object)(object)value.Renderer != (Object)null) { value.Renderer.sharedMaterials = value.OriginalMaterials; } } catch { } } RendererStates.Clear(); foreach (FireExitState value2 in FireExitStates.Values) { try { if ((Object)(object)value2.Renderer != (Object)null) { value2.Renderer.sharedMaterials = value2.OriginalMaterials; } } catch { } DestroyUnityObject((Object?)(object)value2.Overlay); } FireExitStates.Clear(); foreach (MaterialState value3 in MaterialStates.Values) { DestroyUnityObject((Object?)(object)value3.Localized); } MaterialStates.Clear(); RendererScanBuffer.Clear(); ActiveLocalizedMaterialIds.Clear(); UnchangedMaterialIdsThisPass.Clear(); foreach (Texture2D value4 in LocalizedTextures.Values) { DestroyUnityObject((Object?)(object)value4); } LocalizedTextures.Clear(); FailedTextures.Clear(); DestroyUnityObject((Object?)(object)_fireExitLabelMaterial); DestroyUnityObject((Object?)(object)_fireExitHiddenMaterial); DestroyUnityObject((Object?)(object)_fireExitOverlayMesh); DestroyUnityObject((Object?)(object)_fireExitLabelTexture); _fireExitLabelMaterial = null; _fireExitHiddenMaterial = null; _fireExitOverlayMesh = null; _fireExitLabelTexture = null; _textureDirectory = string.Empty; _initialized = false; } public static void OnSceneUnloaded() { PruneDestroyedRendererStates(); PruneDestroyedFireExitStates(); PruneUnusedMaterialStates(); } private static bool CanApply() { if (_initialized) { return !Plugin.IsRuntimeShuttingDown; } return false; } private static bool IsLocalizedScrap(string? objectName) { if (string.IsNullOrWhiteSpace(objectName)) { return false; } if (!objectName.StartsWith("ToiletPaperRolls", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("CashRegisterItem", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("DiyFlashbang", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("Airhorn", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("TZPChemical", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("SprayPaint", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("StopSign", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("YieldSign", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("RedSodaCan", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("Toothpaste", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("WeedKillerItem", StringComparison.OrdinalIgnoreCase) && !objectName.StartsWith("WhoopieCushion", StringComparison.OrdinalIgnoreCase)) { return objectName.StartsWith("ChemicalJug", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsLocalizedShipDecoration(string? objectName) { if (!string.IsNullOrWhiteSpace(objectName)) { return objectName.StartsWith("WelcomeMatContainer", StringComparison.OrdinalIgnoreCase); } return false; } private static void TryApplyFireExitDoor(Renderer? renderer) { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Expected O, but got Unknown if ((Object)(object)renderer == (Object)null || FireExitStates.ContainsKey(((Object)renderer).GetInstanceID()) || !string.Equals(((Object)((Component)renderer).gameObject).name, "Cube.001", StringComparison.Ordinal) || (Object)(object)((Component)renderer).transform.parent == (Object)null || !((Object)((Component)((Component)renderer).transform.parent).gameObject).name.StartsWith("FireExitDoor", StringComparison.OrdinalIgnoreCase)) { return; } MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>(); Mesh val = ((component != null) ? component.sharedMesh : null); Material[] sharedMaterials = renderer.sharedMaterials; if ((Object)(object)val == (Object)null || !string.Equals(((Object)val).name, "Cube.001", StringComparison.Ordinal) || val.subMeshCount != 3 || sharedMaterials == null || sharedMaterials.Length != 3) { return; } Material val2 = EnsureFireExitHiddenMaterial(); Material val3 = EnsureFireExitLabelMaterial(); Mesh val4 = EnsureFireExitOverlayMesh(); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null) { return; } GameObject val5 = null; try { Material[] array = (Material[])sharedMaterials.Clone(); array[2] = val2; renderer.sharedMaterials = array; val5 = new GameObject("FireExitDoorLabel (zh-CN)") { layer = ((Component)renderer).gameObject.layer }; val5.transform.SetParent(((Component)renderer).transform, false); val5.AddComponent<MeshFilter>().sharedMesh = val4; MeshRenderer obj = val5.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = val3; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ((Renderer)obj).lightProbeUsage = (LightProbeUsage)0; ((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0; FireExitStates[((Object)renderer).GetInstanceID()] = new FireExitState(renderer, sharedMaterials, val5); } catch (Exception ex) { renderer.sharedMaterials = sharedMaterials; DestroyUnityObject((Object?)(object)val5); Plugin.Log.LogWarning((object)("Fire-exit localization failed: " + ex.GetType().Name + ": " + ex.Message)); } } private static Texture2D? EnsureFireExitLabelTexture() { if ((Object)(object)_fireExitLabelTexture != (Object)null) { return _fireExitLabelTexture; } string text = Path.Combine(_textureDirectory, "FireExitDoorLabelLocalized.png"); try { FileInfo fileInfo = new FileInfo(text); if (!fileInfo.Exists || fileInfo.Length <= 0 || fileInfo.Length > 1048576) { throw new InvalidDataException("missing or invalid fire-exit label texture"); } Texture2D val = LoadTextureData(File.ReadAllBytes(text), useRuntimeCompression: true) ?? LoadTextureData(File.ReadAllBytes(text), useRuntimeCompression: false); if ((Object)(object)val == (Object)null || ((Texture)val).width != 512 || ((Texture)val).height != 128) { DestroyUnityObject((Object?)(object)val); throw new InvalidDataException("fire-exit label texture must be 512x128"); } ((Object)val).name = "FireExitDoorLabel (zh-CN)"; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; _fireExitLabelTexture = val; return val; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Fire-exit label load failed: " + ex.GetType().Name + ": " + ex.Message)); return null; } } private static Shader? FindTransparentShader() { return Shader.Find("Unlit/Transparent") ?? Shader.Find("Sprites/Default"); } private static Material? EnsureFireExitLabelMaterial() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_004b: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if ((Object)(object)_fireExitLabelMaterial != (Object)null) { return _fireExitLabelMaterial; } Shader val = FindTransparentShader(); Texture2D val2 = EnsureFireExitLabelTexture(); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return null; } _fireExitLabelMaterial = new Material(val) { name = "FireExitDoorLabelMaterial (zh-CN)", mainTexture = (Texture)(object)val2, color = Color.white, renderQueue = 3000 }; return _fireExitLabelMaterial; } private static Material? EnsureFireExitHiddenMaterial() { //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_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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if ((Object)(object)_fireExitHiddenMaterial != (Object)null) { return _fireExitHiddenMaterial; } Shader val = FindTransparentShader(); if ((Object)(object)val == (Object)null) { return null; } _fireExitHiddenMaterial = new Material(val) { name = "FireExitDoorOriginalTextHidden (zh-CN)", color = Color.clear, renderQueue = 3000 }; return _fireExitHiddenMaterial; } private static Mesh EnsureFireExitOverlayMesh() { //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_0024: Expected O, but got Unknown //IL_003c: 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_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_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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00c5: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00f6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fireExitOverlayMesh != (Object)null) { return _fireExitOverlayMesh; } Mesh val = new Mesh { name = "FireExitDoorLabelQuad (zh-CN)" }; val.vertices = (Vector3[])(object)new Vector3[4] { new Vector3(1.08f, -34f, -43.6f), new Vector3(1.08f, 34f, -43.6f), new Vector3(1.08f, 34f, -27.8f), new Vector3(1.08f, -34f, -27.8f) }; val.uv = (Vector2[])(object)new Vector2[4] { new Vector2(1f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 0f) }; val.triangles = new int[6] { 0, 1, 2, 0, 2, 3 }; val.RecalculateBounds(); _fireExitOverlayMesh = val; return val; } private static void ApplyToRenderer(Renderer? renderer, bool cacheUnchangedMaterials = false) { if ((Object)(object)renderer == (Object)null || RendererStates.ContainsKey(((Object)renderer).GetInstanceID())) { return; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { return; } Material[] array = (Material[])sharedMaterials.Clone(); List<int> list = null; bool flag = false; for (int i = 0; i < sharedMaterials.Length; i++) { Material val = sharedMaterials[i]; Material orCreateLocalizedMaterial = GetOrCreateLocalizedMaterial(val, cacheUnchangedMaterials); if (!((Object)(object)orCreateLocalizedMaterial == (Object)null) && orCreateLocalizedMaterial != val) { array[i] = orCreateLocalizedMaterial; if (list == null) { list = new List<int>(); } int instanceID = ((Object)val).GetInstanceID(); if (!list.Contains(instanceID)) { list.Add(instanceID); } flag = true; } } if (flag) { renderer.sharedMaterials = array; RendererStates[((Object)renderer).GetInstanceID()] = new RendererState(renderer, sharedMaterials, list ?? new List<int>()); } } private static Material? GetOrCreateLocalizedMaterial(Material? original, bool cacheUnchangedMaterials) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown if ((Object)(object)original == (Object)null) { return null; } int instanceID = ((Object)original).GetInstanceID(); if (cacheUnchangedMaterials && UnchangedMaterialIdsThisPass.Contains(instanceID)) { return original; } if (MaterialStates.TryGetValue(instanceID, out MaterialState value)) { if (value.HasOriginal(original)) { return value.Localized; } DestroyUnityObject((Object?)(object)value.Localized); MaterialStates.Remove(instanceID); } Material val = null; bool flag = false; string[] texturePropertyNames = TexturePropertyNames; foreach (string text in texturePropertyNames) { if (!original.HasProperty(text) || !TryResolveSpec(original.GetTexture(text), out TextureSpec spec)) { continue; } Texture2D val2 = EnsureTextureLoaded(spec, original.GetTexture(text)); if (!((Object)(object)val2 == (Object)null)) { if (val == null) { val = new Material(original); } val.SetTexture(text, (Texture)(object)val2); flag = true; } } if (!flag && original.HasProperty("_MainTex") && TryResolveSpec(original.mainTexture, out TextureSpec spec2)) { Texture2D val3 = EnsureTextureLoaded(spec2, original.mainTexture); if ((Object)(object)val3 != (Object)null) { val = new Material(original) { mainTexture = (Texture)(object)val3 }; flag = true; } } if (!flag || (Object)(object)val == (Object)null) { DestroyUnityObject((Object?)(object)val); if (cacheUnchangedMaterials) { UnchangedMaterialIdsThisPass.Add(instanceID); } return original; } UnchangedMaterialIdsThisPass.Remove(instanceID); ((Object)val).name = NormalizeName(((Object)original).name) + " (zh-CN)"; if (MaterialStates.TryGetValue(instanceID, out MaterialState value2)) { DestroyUnityObject((Object?)(object)value2.Localized); } MaterialStates[instanceID] = new MaterialState(original, val); return val; } private static Texture2D? EnsureTextureLoaded(TextureSpec spec, Texture? originalTexture) { //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) if (LocalizedTextures.TryGetValue(spec.OriginalName, out Texture2D value)) { return value; } if (FailedTextures.Contains(spec.OriginalName)) { return null; } string text = Path.Combine(_textureDirectory, spec.FileName); Texture2D val = null; try { FileInfo fileInfo = new FileInfo(text); if (!fileInfo.Exists) { throw new FileNotFoundException("localized texture file is missing", text); } if (fileInfo.Length <= 0 || (!spec.PrecompressedBc1 && !spec.PrecompressedBc3 && !spec.PrecompressedBc7 && fileInfo.Length > 16777216)) { throw new InvalidDataException($"invalid file size ({fileInfo.Length} bytes)"); } if (spec.PrecompressedBc1) { val = PrecompressedTextureLoader.LoadBc1(text, spec.Width, spec.Height, spec.MipChain, out string error); if ((Object)(object)val == (Object)null) { throw new InvalidDataException(error ?? "precompressed BC1 load failed"); } } else if (spec.PrecompressedBc3) { val = PrecompressedTextureLoader.LoadBc3(text, spec.Width, spec.Height, spec.MipChain, out string error2); if ((Object)(object)val == (Object)null) { throw new InvalidDataException(error2 ?? "precompressed BC3 load failed"); } } else if (spec.PrecompressedBc7) { val = PrecompressedTextureLoader.LoadBc7(text, spec.Width, spec.Height, spec.MipChain, out string error3); if ((Object)(object)val == (Object)null) { throw new InvalidDataException(error3 ?? "precompressed BC7 load failed"); } } else { byte[] data = File.ReadAllBytes(text); val = LoadTextureData(data, useRuntimeCompression: true) ?? LoadTextureData(data, useRuntimeCompression: false); } if ((Object)(object)val == (Object)null || ((Texture)val).width != spec.Width || ((Texture)val).height != spec.Height) { string arg = (((Object)(object)val == (Object)null) ? "decode failed" : $"{((Texture)val).width}x{((Texture)val).height}"); throw new InvalidDataException($"expected {spec.Width}x{spec.Height}, got {arg}"); } ((Object)val).name = spec.OriginalName + " (zh-CN)"; if ((Object)(object)originalTexture != (Object)null) { ((Texture)val).wrapMode = originalTexture.wrapMode; ((Texture)val).filterMode = originalTexture.filterMode; ((Texture)val).anisoLevel = originalTexture.anisoLevel; ((Texture)val).mipMapBias = originalTexture.mipMapBias; } LocalizedTextures[spec.OriginalName] = val; return val; } catch (Exception ex) { DestroyUnityObject((Object?)(object)val); FailedTextures.Add(spec.OriginalName); Plugin.Log.LogWarning((object)("Environment texture localization failed for " + spec.FileName + ": " + ex.GetType().Name + ": " + ex.Message)); return null; } } private static Texture2D? LoadTextureData(byte[] data, bool useRuntimeCompression) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Texture2D val = null; try { TextureFormat val2 = (TextureFormat)((useRuntimeCompression && SystemInfo.SupportsTextureFormat((TextureFormat)12)) ? 12 : 4); int num = (((int)val2 == 12) ? 4 : 2); val = new Texture2D(num, num, val2, true); if (ImageConversion.LoadImage(val, data, true)) { return val; } DestroyUnityObject((Object?)(object)val); return null; } catch { DestroyUnityObject((Object?)(object)val); return null; } } private static bool TryResolveSpec(Texture? texture, out TextureSpec spec) { return TextureSpecs.TryGetValue(NormalizeName((texture != null) ? ((Object)texture).name : null), out spec); } private static string NormalizeName(string? name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } string text = name.Trim(); if (text.EndsWith(" (Instance)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - " (Instance)".Length); } if (text.EndsWith(" (zh-CN)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - " (zh-CN)".Length); } return text; } private static void PruneDestroyedRendererStates() { List<int> list = null; foreach (KeyValuePair<int, RendererState> rendererState in RendererStates) { if (!((Object)(object)rendererState.Value.Renderer != (Object)null)) { if (list == null) { list = new List<int>(); } list.Add(rendererState.Key); } } if (list == null) { return; } foreach (int item in list) { RendererStates.Remove(item); } } private static void PruneDestroyedFireExitStates() { List<int> list = null; foreach (KeyValuePair<int, FireExitState> fireExitState in FireExitStates) { if (!((Object)(object)fireExitState.Value.Renderer != (Object)null) || !((Object)(object)fireExitState.Value.Overlay != (Object)null)) { if (list == null) { list = new List<int>(); } list.Add(fireExitState.Key); } } if (list == null) { return; } foreach (int item in list) { FireExitStates.Remove(item); } } private static void PruneUnusedMaterialStates() { ActiveLocalizedMaterialIds.Clear(); foreach (RendererState value in RendererStates.Values) { if ((Object)(object)value.Renderer == (Object)null) { continue; } foreach (int localizedMaterialId in value.LocalizedMaterialIds) { ActiveLocalizedMaterialIds.Add(localizedMaterialId); } } List<int> list = null; foreach (KeyValuePair<int, MaterialState> materialState in MaterialStates) { if (!((Object)(object)materialState.Value.Localized != (Object)null) || !materialState.Value.HasLiveOriginal() || !ActiveLocalizedMaterialIds.Contains(materialState.Key)) { if (list == null) { list = new List<int>(); } list.Add(materialState.Key); DestroyUnityObject((Object?)(object)materialState.Value.Localized); } } if (list != null) { foreach (int item in list) { MaterialStates.Remove(item); } } ActiveLocalizedMaterialIds.Clear(); } private static void DestroyUnityObject(Object? value) { if (!(value == (Object)null)) { if (Application.isPlaying) { Object.Destroy(value); } else { Object.DestroyImmediate(value); } } } } internal static class PrecompressedTextureLoader { public static Texture2D? LoadBc1(string path, int width, int height, bool mipChain, out string? error) { return LoadCompressed(path, width, height, mipChain, (TextureFormat)10, 8, "DXT1/BC1", out error); } public static Texture2D? LoadBc3(string path, int width, int height, bool mipChain, out string? error) { return LoadCompressed(path, width, height, mipChain, (TextureFormat)12, 16, "DXT5/BC3", out error); } public static Texture2D? LoadBc7(string path, int width, int height, bool mipChain, out string? error) { return LoadCompressed(path, width, height, mipChain, (TextureFormat)25, 16, "BC7", out error); } private static Texture2D? LoadCompressed(string path, int width, int height, bool mipChain, TextureFormat format, int bytesPerBlock, string formatName, out string? error) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_008e: Expected O, but got Unknown error = null; Texture2D val = null; try { if (!SystemInfo.SupportsTextureFormat(format)) { error = formatName + " is not supported by this graphics device"; return null; } FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Exists) { error = "precompressed texture file is missing"; return null; } long num = CalculateCompressedByteCount(width, height, mipChain, bytesPerBlock); if (fileInfo.Length != num) { error = $"expected {num} bytes, got {fileInfo.Length}"; return null; } byte[] array = File.ReadAllBytes(path); val = new Texture2D(width, height, format, mipChain); val.LoadRawTextureData(array); val.Apply(false, true); return val; } catch (Exception ex) { DestroyUnityObject((Object?)(object)val); error = ex.GetType().Name + ": " + ex.Message; return null; } } public static long CalculateBc3ByteCount(int width, int height, bool mipChain) { return CalculateCompressedByteCount(width, height, mipChain, 16); } public static long CalculateBc7ByteCount(int width, int height, bool mipChain) { return CalculateCompressedByteCount(width, height, mipChain, 16); } public static long CalculateBc1ByteCount(int width, int height, bool mipChain) { return CalculateCompressedByteCount(width, height, mipChain, 8); } private static long CalculateCompressedByteCount(int width, int height, bool mipChain, int bytesPerBlock) { long num = 0L; while (true) { num += (long)Math.Max(1, (width + 3) / 4) * (long)Math.Max(1, (height + 3) / 4) * bytesPerBlock; if (!mipChain || (width == 1 && height == 1)) { break; } width = Math.Max(1, width / 2); height = Math.Max(1, height / 2); } return num; } private static void DestroyUnityObject(Object? value) { if (!(value == (Object)null)) { if (Application.isPlaying) { Object.Destroy(value); } else { Object.DestroyImmediate(value); } } } } internal static class RadiationWarningAuditService { internal const string WarningRootPathSuffix = "IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease"; private static ConfigEntry<bool>? _enabled; private static ConfigEntry<int>? _sampleCount; private static ConfigEntry<float>? _sampleIntervalSeconds; private static HUDManager? _activeHudManager; private static Coroutine? _activeAuditCoroutine; public static void Initialize(ConfigFile config) { _enabled = config.Bind<bool>("90 诊断 - 辐射警告审计", "Enabled", false, "启用辐射警告原始 UI 子树的限量采样诊断。默认关闭,避免运行时枚举 UI 子树。"); _sampleCount = config.Bind<int>("90 诊断 - 辐射警告审计", "SampleCount", 5, "辐射警告触发后采样的次数上限。"); _sampleIntervalSeconds = config.Bind<float>("90 诊断 - 辐射警告审计", "SampleIntervalSeconds", 0.2f, "两次辐射警告诊断采样之间的间隔,单位为秒。"); } public static void Shutdown() { try { if (_activeAuditCoroutine != null && (Object)(object)_activeHudManager != (Object)null) { ((MonoBehaviour)_activeHudManager).StopCoroutine(_activeAuditCoroutine); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("RadiationWarningAuditService shutdown failed while stopping coroutine: " + ex.GetType().Name + ": " + ex.Message)); } finally { _activeAuditCoroutine = null; _activeHudManager = null; _enabled = null; _sampleCount = null; _sampleIntervalSeconds = null; } } public static void OnRadiationWarningTriggered(HUDManager hudManager, string stage) { if ((Object)(object)hudManager == (Object)null) { return; } ConfigEntry<bool>? enabled = _enabled; if (enabled == null || !enabled.Value) { return; } if ((Object)(object)FindWarningRoot(hudManager) == (Object)null) { Plugin.Log.LogWarning((object)("RadiationAudit[" + stage + "] action=root-not-found suffix=IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease")); return; } if (_activeAuditCoroutine != null && (Object)(object)_activeHudManager != (Object)null) { ((MonoBehaviour)_activeHudManager).StopCoroutine(_activeAuditCoroutine); _activeAuditCoroutine = null; } _activeHudManager = hudManager; _activeAuditCoroutine = ((MonoBehaviour)hudManager).StartCoroutine(SampleWarningSubtree(hudManager, stage, _sampleCount?.Value ?? 0, _sampleIntervalSeconds?.Value ?? 0f)); } private static IEnumerator SampleWarningSubtree(HUDManager hudManager, string stage, int sampleCount, float sampleIntervalSeconds) { int boundedSampleCount = Mathf.Max(1, sampleCount); float boundedIntervalSeconds = Mathf.Max(0f, sampleIntervalSeconds); for (int sampleIndex = 0; sampleIndex < boundedSampleCount; sampleIndex++) { if ((Object)(object)hudManager == (Object)null) { break; } Transform val = FindWarningRoot(hudManager); if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)string.Format("RadiationAudit[{0}] sample={1} action=sampling-stopped-root-lost suffix={2}", stage, sampleIndex, "IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease")); break; } AuditImages(val, stage, sampleIndex); AuditRawImages(val, stage, sampleIndex); AuditSpriteRenderers(val, stage, sampleIndex); AuditGraphicMaterials(val, stage, sampleIndex); AuditRendererMaterials(val, stage, sampleIndex); if (sampleIndex + 1 < boundedSampleCount) { yield return (object)((!(boundedIntervalSeconds > 0f)) ? ((WaitForSeconds)null) : new WaitForSeconds(boundedIntervalSeconds)); } } _activeAuditCoroutine = null; _activeHudManager = null; } private static void AuditGraphicMaterials(Transform root, string stage, int sampleIndex) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) HashSet<int> hashSet = new HashSet<int>(); Graphic[] componentsInChildren = ((Component)root).GetComponentsInChildren<Graphic>(true); foreach (Graphic val in componentsInChildren) { Material material; try { material = val.material; } catch (Exception ex) { Plugin.Log.LogWarning((object)$"RadiationAudit[{stage}] sample={sampleIndex} component=GraphicMaterial path={BuildPath(((Component)val).transform)} active={((Component)val).gameObject.activeInHierarchy} enabled={((Behaviour)val).enabled} alpha={val.color.a:0.###} material=<error> texture=<error> error={ex.GetType().Name}:{ex.Message}"); continue; } if ((Object)(object)material != (Object)null) { hashSet.Add(((Object)material).GetInstanceID()); } } } private static void AuditRendererMaterials(Transform root, string stage, int sampleIndex) { Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = componentsInChildren[i].sharedMaterials; if (sharedMaterials != null && sharedMaterials.Length != 0) { for (int j = 0; j < sharedMaterials.Length; j++) { _ = sharedMaterials[j]; } } } } private static void AuditImages(Transform root, string stage, int sampleIndex) { Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { Sprite obj = val.overrideSprite ?? val.sprite; if (obj != null) { _ = obj.texture; } } } private static void AuditRawImages(Transform root, string stage, int sampleIndex) { RawImage[] componentsInChildren = ((Component)root).GetComponentsInChildren<RawImage>(true); for (int i = 0; i < componentsInChildren.Length; i++) { _ = componentsInChildren[i]; } } private static void AuditSpriteRenderers(Transform root, string stage, int sampleIndex) { SpriteRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<SpriteRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { _ = componentsInChildren[i].sprite; } } private static Transform? FindWarningRoot(HUDManager hudManager) { Animator radiationGraphicAnimator = hudManager.radiationGraphicAnimator; Transform val = ((radiationGraphicAnimator != null) ? ((Component)radiationGraphicAnimator).transform : null); if (HasExpectedRootPath(val)) { return val; } Transform[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (HasExpectedRootPath(val2)) { return val2; } } return null; } private static bool HasExpectedRootPath(Transform? transform) { if ((Object)(object)transform == (Object)null) { return false; } return BuildPath(transform).EndsWith("IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease", StringComparison.OrdinalIgnoreCase); } private static string DescribeName(Object? obj) { if (!string.IsNullOrWhiteSpace((obj != null) ? obj.name : null)) { return obj.name; } return "<null>"; } 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; } } internal static class RadiationWarningPlaybackService { private sealed class PlaybackState { public Transform Root { get; } public Image PanelImage { get; } public Sprite? OriginalRawOverrideSprite { get; } public Sprite? LastAppliedLocalizedSprite { get; set; } public string? LastAppliedOriginalSpriteName { get; set; } public bool CleanupCompleted { get; set; } public PlaybackState(Transform root, Image panelImage, Sprite? originalRawOverrideSprite) { Root = root; PanelImage = panelImage; OriginalRawOverrideSprite = originalRawOverrideSprite; } } private const string TextureSubfolder = "textures"; private const string WarningRootPathSuffix = "IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease"; private const string PanelObjectName = "Panel"; private const float OriginalClipDurationSeconds = 1.7166667f; private const float DefaultFollowDurationSeconds = 1.85f; private const float MaxFollowDurationSeconds = 5f; private const long MaxTextureBytes = 8388608L; private const long MaxTexturePixels = 16777216L; private static readonly Dictionary<string, string[]> OriginalSpriteFrameFiles = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase) { ["RedUIPanelGlitchB"] = FrameFileNameCandidates("RedUIPanelGlitchB", "C864CEDFD2-470F6C25C6"), ["RedUIPanelGlitchBWarning"] = FrameFileNameCandidates("RedUIPanelGlitchBWarning", "E5C5C6E52B-F9F9EA9261"), ["RedUIPanelGlitchBWarningRadiation"] = FrameFileNameCandidates("RedUIPanelGlitchBWarningRadiation", "FFCC97E055-2C688E6DC8"), ["RedUIPanelGlitchBWarningRadiationB"] = FrameFileNameCandidates("RedUIPanelGlitchBWarningRadiationB", "7D4ED37952-95F686DE01"), ["RedUIPanelGlitchBWarningRadiationC"] = FrameFileNameCandidates("RedUIPanelGlitchBWarningRadiationC", "7FBAA1AA30-9E2C036778"), ["RedUIPanelGlitchBWarningRadiationD"] = FrameFileNameCandidates("RedUIPanelGlitchBWarningRadiationD", "4877939F7B-47E20481B0") }; private static readonly Dictionary<string, Texture2D?> TextureCache = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Texture2D?> ResolvedFrameTextureCache = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, Sprite?> SpriteCache = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase); private static string? _textureDirectory; private static ConfigEntry<bool>? _enabled; private static ConfigEntry<float>? _followDurationSeconds; private static HUDManager? _activeHudManager; private static Coroutine? _activePlaybackCoroutine; private static PlaybackState? _activePlaybackState; public static void Initialize(string pluginDir, ConfigFile config) { _textureDirectory = Path.Combine(pluginDir, "textures"); _enabled = config.Bind<bool>("04 资源 - 辐射警告", "Enabled", true, "启用跟随原版动画的辐射警告贴图替换。"); _followDurationSeconds = config.Bind<float>("04 资源 - 辐射警告", "FollowDurationSeconds", 1.85f, "跟随原版 RadiationIncreaseWarning 动画并替换本地化贴图的持续时间,单位为秒。"); foreach (string key in OriginalSpriteFrameFiles.Keys) { ResolveFrameTexture(key, "Initialize"); } Plugin.Log.LogInfo((object)$"RadiationPlayback initialized mode=animator-follow clipSeconds={1.7166667f:0.###}"); } public static void OnRadiationWarningTriggered(HUDManager hudManager, string stage) { if ((Object)(object)hudManager == (Object)null) { return; } ConfigEntry<bool>? enabled = _enabled; if (enabled == null || !enabled.Value) { return; } if (_activePlaybackCoroutine != null) { Plugin.Log.LogInfo((object)("RadiationPlayback[" + stage + "] action=duplicate-trigger-restart mode=animator-follow")); CleanupActivePlayback(stage, "duplicate-restart"); } Transform val = FindWarningRoot(hudManager); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("RadiationPlayback[" + stage + "] action=root-not-found suffix=IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease")); return; } Image val2 = FindWarningPanel(val); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)("RadiationPlayback[" + stage + "] action=panel-not-found path=" + BuildPath(val) + " child=Panel")); } else if (HasAllLocalizedTextures(stage)) { PlaybackState playbackState = new PlaybackState(val, val2, ReadRawOverrideSprite(val2)); _activeHudManager = hudManager; _activePlaybackState = playbackState; _activePlaybackCoroutine = ((MonoBehaviour)hudManager).StartCoroutine(FollowAnimatorSpriteCurve(playbackState, stage)); } } public static void Shutdown() { CleanupActivePlayback("Shutdown", "shutdown"); ClearCachedAssets(); } public static void ResetForHudLifecycle(HUDManager hudManager, string stage) { if (!((Object)(object)hudManager == (Object)null) && (_activePlaybackCoroutine != null || _activePlaybackState != null)) { CleanupActivePlayback(stage, "hud-reset"); } } private static IEnumerator FollowAnimatorSpriteCurve(PlaybackState playbackState, string stage) { float followDurationSeconds = GetFollowDurationSeconds(); float endTime = Time.realtimeSinceStartup + followDurationSeconds; Plugin.Log.LogInfo((object)$"RadiationPlayback[{stage}] FollowAnimatorSpriteCurve started path={BuildPath(playbackState.Root)} panel={BuildPath(((Component)playbackState.PanelImage).transform)} duration={followDurationSeconds:0.###}"); try { while ((Object)(object)playbackState.PanelImage != (Object)null && Time.realtimeSinceStartup <= endTime) { ApplyCurrentAnimatorSpriteSubstitution(playbackState, stage); yield return null; } if ((Object)(object)playbackState.PanelImage != (Object)null) { ApplyCurrentAnimatorSpriteSubstitution(playbackState, stage); } Plugin.Log.LogInfo((object)("RadiationPlayback[" + stage + "] FollowAnimatorSpriteCurve finished path=" + BuildPath(playbackState.Root))); } finally { CleanupPlaybackState(playbackState, stage, "finally"); } } private static float GetFollowDurationSeconds() { float num = _followDurationSeconds?.Value ?? 1.85f; if (float.IsNaN(num) || float.IsInfinity(num)) { num = 1.85f; } return Mathf.Clamp(num, 1.7166667f, 5f); } private static void ApplyCurrentAnimatorSpriteSubstitution(PlaybackState playbackState, string stage) { Image panelImage = playbackState.PanelImage; Sprite sprite = panelImage.sprite; string text = NormalizeSpriteName((sprite != null) ? ((Object)sprite).name : null); if (string.IsNullOrWhiteSpace(text)) { return; } if (!OriginalSpriteFrameFiles.ContainsKey(text)) { ClearLocalizedOverrideIfOwned(playbackState, "unmapped-original"); return; } Texture2D val = ResolveFrameTexture(text, stage); if (!((Object)(object)val == (Object)null)) { Sprite val2 = ResolveLocalizedSprite(text, sprite, val); if (!((Object)(object)val2 == (Object)null) && ReadRawOverrideSprite(panelImage) != val2) { panelImage.overrideSprite = val2; ((Graphic)panelImage).SetVerticesDirty(); ((Graphic)panelImage).SetMaterialDirty(); string.Equals(playbackState.LastAppliedOriginalSpriteName, text, StringComparison.OrdinalIgnoreCase); playbackState.LastAppliedOriginalSpriteName = text; playbackState.LastAppliedLocalizedSprite = val2; } } } private static void CleanupActivePlayback(string stage, string reason) { Coroutine activePlaybackCoroutine = _activePlaybackCoroutine; HUDManager activeHudManager = _activeHudManager; PlaybackState activePlaybackState = _activePlaybackState; _activePlaybackCoroutine = null; _activeHudManager = null; _activePlaybackState = null; if (activePlaybackCoroutine != null && (Object)(object)activeHudManager != (Object)null) { ((MonoBehaviour)activeHudManager).StopCoroutine(activePlaybackCoroutine); } if (activePlaybackState != null) { CleanupPlaybackState(activePlaybackState, stage, reason); } } private static void CleanupPlaybackState(PlaybackState playbackState, string stage, string reason) { if (!playbackState.CleanupCompleted) { playbackState.CleanupCompleted = true; ClearLocalizedOverrideIfOwned(playbackState, reason); if (_activePlaybackState == playbackState) { _activePlaybackState = null; _activePlaybackCoroutine = null; _activeHudManager = null; } string text = (((Object)(object)playbackState.PanelImage != (Object)null) ? BuildPath(((Component)playbackState.PanelImage).transform) : "<null>"); Plugin.Log.LogInfo((object)("RadiationPlayback[" + stage + "] action=restore reason=" + reason + " path=" + BuildPath(playbackState.Root) + " panel=" + text)); } } private static void ClearLocalizedOverrideIfOwned(PlaybackState playbackState, string reason) { Image panelImage = playbackState.PanelImage; if (!((Object)(object)panelImage == (Object)null)) { Sprite val = ReadRawOverrideSprite(panelImage); if ((Object)(object)val != (Object)null && val != playbackState.LastAppliedLocalizedSprite && !IsCachedLocalizedSprite(val)) { Plugin.Log.LogInfo((object)("RadiationPlayback action=skip-restore reason=" + reason + " currentOverride=" + ((Object)val).name)); return; } panelImage.overrideSprite = playbackState.OriginalRawOverrideSprite; ((Graphic)panelImage).SetVerticesDirty(); ((Graphic)panelImage).SetMaterialDirty(); } } private static bool HasAllLocalizedTextures(string stage) { foreach (string key in OriginalSpriteFrameFiles.Keys) { if ((Object)(object)ResolveFrameTexture(key, stage) == (Object)null) { return false; } } return true; } private static string[] FrameFileNameCandidates(string baseName, string contentHash) { return new string[2] { baseName + " [" + contentHash + "].png", baseName + "[" + contentHash + "].png" }; } private static string? ResolveFrameFileName(string originalSpriteName, string stage) { if (!OriginalSpriteFrameFiles.TryGetValue(originalSpriteName, out string[] value)) { return null; } string[] array = value; foreach (string text in array) { if ((Object)(object)LoadTexture(text) != (Object)null) { return text; } } Plugin.Log.LogWarning((object)("RadiationPlayback[" + stage + "] action=incomplete-frame-set original=" + originalSpriteName + " candidates=" + string.Join("|", value) + " nativeFallback=true")); return null; } private static Texture2D? ResolveFrameTexture(string originalSpriteName, string stage) { if (ResolvedFrameTextureCache.TryGetValue(originalSpriteName, out Texture2D value)) { return value; } string text = ResolveFrameFileName(originalSpriteName, stage); if (text == null) { ResolvedFrameTextureCache[originalSpriteName] = null; return null; } Texture2D val = LoadTexture(text); ResolvedFrameTextureCache[originalSpriteName] = val; return val; } private static Image? FindWarningPanel(Transform root) { Transform obj = root.Find("Panel"); Image val = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null); if ((Object)(object)val != (Object)null) { return val; } Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true); foreach (Image val2 in componentsInChildren) { if (string.Equals(((Object)val2).name, "Panel", StringComparison.OrdinalIgnoreCase)) { return val2; } } return null; } private static Sprite? ResolveLocalizedSprite(string originalSpriteName, Sprite? originalSprite, Texture2D texture) { string key = BuildSpriteCacheKey(originalSpriteName, originalSprite, texture); if (SpriteCache.TryGetValue(key, out Sprite value)) { return value; } Sprite val = CreateLocalizedSprite(texture, originalSprite); SpriteCache[key] = val; return val; } private static string BuildSpriteCacheKey(string originalSpriteName, Sprite? originalSprite, Texture2D texture) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)originalSprite == (Object)null) { return originalSpriteName + ":" + ((Object)texture).name + ":fallback"; } Rect rect = originalSprite.rect; return $"{originalSpriteName}:{((Object)texture).name}:{((Rect)(ref rect)).x}:{((Rect)(ref rect)).y}:{((Rect)(ref rect)).width}:{((Rect)(ref rect)).height}:{originalSprite.pivot.x}:{originalSprite.pivot.y}:{originalSprite.pixelsPerUnit}"; } private static Sprite? CreateLocalizedSprite(Texture2D texture, Sprite? template) { //IL_00c0: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)template != (Object)null) { Rect rect = template.rect; if (((Rect)(ref rect)).width > 0f && ((Rect)(ref rect)).height > 0f && ((Rect)(ref rect)).xMax <= (float)((Texture)texture).width && ((Rect)(ref rect)).yMax <= (float)((Texture)texture).height) { Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(template.pivot.x / ((Rect)(ref rect)).width, template.pivot.y / ((Rect)(ref rect)).height); Sprite obj = Sprite.Create(texture, rect, val, template.pixelsPerUnit, 0u, (SpriteMeshType)0, template.border); ((Object)obj).name = ((Object)texture).name; return obj; } } Sprite obj2 = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f); ((Object)obj2).name = ((Object)texture).name; return obj2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("RadiationPlayback[Sprite] action=create-failed texture=" + ((Object)texture).name + " error=" + ex.GetType().Name + ": " + ex.Message)); return null; } } private static bool IsCachedLocalizedSprite(Sprite sprite) { foreach (Sprite value in SpriteCache.Values) { if (value == sprite) { return true; } } return false; } private static Sprite? ReadRawOverrideSprite(Image image) { try { return image.m_OverrideSprite; } catch (Exception ex) { Plugin.Log.LogWarning((object)("RadiationPlayback[Image] action=read-raw-override-failed error=" + ex.GetType().Name + ": " + ex.Message)); return null; } } private static Transform? FindWarningRoot(HUDManager hudManager) { Animator radiationGraphicAnimator = hudManager.radiationGraphicAnimator; Transform val = ((radiationGraphicAnimator != null) ? ((Component)radiationGraphicAnimator).transform : null); if (HasExpectedRootPath(val)) { return val; } Transform[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (HasExpectedRootPath(val2)) { return val2; } } return null; } private static bool HasExpectedRootPath(Transform? transform) { if ((Object)(object)transform == (Object)null) { return false; } return BuildPath(transform).EndsWith("IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease", StringComparison.OrdinalIgnoreCase); } private static Texture2D? LoadTexture(string fileName) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown if (TextureCache.TryGetValue(fileName, out Texture2D value)) { return value; } if (string.IsNullOrWhiteSpace(_textureDirectory)) { return null; } string text = Path.Combine(_textureDirectory, fileName); if (!File.Exists(text)) { TextureCache[fileName] = null; return null; } Texture2D val = null; try { FileInfo fileInfo = new FileInfo(text); if (fileInfo.Length > 8388608) { Plugin.Log.LogWarning((object)$"RadiationPlayback[Texture] action=file-too-large file={fileName} bytes={fileInfo.Length} max={8388608L}"); TextureCache[fileName] = null; return null; } byte[] array = File.ReadAllBytes(text); val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array, false)) { Object.Destroy((Object)(object)val); val = null; TextureCache[fileName] = null; return null; } if (IsDecodedTextureTooLarge(val)) { Plugin.Log.LogWarning((object)("RadiationPlayback[Texture] action=decoded-texture-too-large file=" + fileName + " " + $"width={((Texture)val).width} height={((Texture)val).height} pixels={(long)((Texture)val).width * (long)((Texture)val).height} maxPixels={16777216L}")); Object.Destroy((Object)(object)val); val = null; TextureCache[fileName] = null; return null; } ((Object)val).name = Path.GetFileNameWithoutExtension(fileName); ((Texture)val).wrapMode = (TextureWrapMode)1; TextureCache[fileName] = val; Texture2D result = val; val = null; return result; } catch (Exception ex) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } Plugin.Log.LogWarning((object)("RadiationPlayback[Texture] action=load-failed file=" + fileName + " error=" + ex.GetType().Name + ": " + ex.Message)); TextureCache[fileName] = null; return null; } } private static void ClearCachedAssets() { HashSet<int> hashSet = new HashSet<int>(); foreach (Sprite value in SpriteCache.Values) { if (!((Object)(object)value == (Object)null) && hashSet.Add(((Object)value).GetInstanceID())) { Object.Destroy((Object)(object)value); } } HashSet<int> destroyedTextureIds = new HashSet<int>(); foreach (Texture2D value2 in TextureCache.Values) { DestroyTextureOnce(value2, destroyedTextureIds); } foreach (Texture2D value3 in ResolvedFrameTextureCache.Values) { DestroyTextureOnce(value3, destroyedTextureIds); } SpriteCache.Clear(); TextureCache.Clear(); ResolvedFrameTextureCache.Clear(); } private static bool IsDecodedTextureTooLarge(Texture2D texture) { if (((Texture)texture).width <= 0 || ((Texture)texture).height <= 0) { return true; } return (long)((Texture)texture).width * (long)((Texture)texture).height > 16777216; } private static void DestroyTextureOnce(Texture2D? texture, HashSet<int> destroyedTextureIds) { if (!((Object)(object)texture == (Object)null) && destroyedTextureIds.Add(((Object)texture).GetInstanceID())) { Object.Destroy((Object)(object)texture); } }