Decompiled source of LC Chinese Project v0.2.0

BepInEx/plugins/V81TestChn/V81TestChn.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("V81TestChn")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("V81TestChn")]
[assembly: AssemblyTitle("V81TestChn")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace V81TestChn
{
	internal static class AlertTextureReplacementService
	{
		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;
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForFixedSceneLabels>d__42 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string stage;

			private float <elapsed>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<elapsed>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<elapsed>5__2 += 0.25f;
					break;
				}
				if (<elapsed>5__2 < 8f)
				{
					if (SyncFixedSceneLabelsInRelayScene(stage + ".relay-scene") > 0)
					{
						_fixedSceneLabelWatcher = null;
						_fixedSceneLabelWatcherOwner = null;
						return false;
					}
					<>2__current = (object)new WaitForSeconds(0.25f);
					<>1__state = 1;
					return true;
				}
				Plugin.Log.LogWarning((object)("NativeRelay[" + stage + ".relay-scene] target=FixedSceneLabel action=timeout"));
				_fixedSceneLabelWatcher = null;
				_fixedSceneLabelWatcherOwner = null;
				return false;
			}

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

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

		[CompilerGenerated]
		private sealed class <WaitForSystemOnlineTitle>d__41 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public string stage;

			public HUDManager hudManager;

			private float <elapsed>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<elapsed>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					<elapsed>5__2 += 0.1f;
					break;
				}
				if ((Object)(object)hudManager != (Object)null && <elapsed>5__2 < 12f)
				{
					TMP_Text text = FindSystemOnlineTitleByFullPath();
					if (IsExactSystemOnlineTitle(text))
					{
						ApplySystemOnlineNativeTranslation(text, stage + ".watcher");
						_systemOnlineWatcher = null;
						_systemOnlineWatcherOwner = null;
						return false;
					}
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 1;
					return true;
				}
				Plugin.Log.LogWarning((object)("NativeRelay[" + stage + ".watcher] target=SystemOnline action=timeout"));
				_systemOnlineWatcher = null;
				_systemOnlineWatcherOwner = null;
				return false;
			}

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

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

		private const int NativeTextRoleCacheLimit = 4096;

		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 readonly Dictionary<int, CachedNativeTextRole> NativeTextRoleCache = new Dictionary<int, CachedNativeTextRole>();

		private static readonly Dictionary<string, string> FixedSceneLabels = new Dictionary<string, string>(StringComparer.Ordinal)
		{
			["TO MEET PROFIT QUOTA"] = "以达到利润配额",
			["PERFORMANCE REPORT"] = "绩效报告",
			["EMPLOYEE RANK"] = "员工等级",
			["Fines"] = "罚款",
			["(Dead)"] = "(死亡)",
			["Deceased"] = "死亡",
			["[LIFE SUPPORT: OFFLINE]"] = "[生命维持:离线]",
			["You will keep your employee rank. Your ship and credits will be reset."] = "你的员工等级将被保留,但飞船和点数将被重置。"
		};

		public static void Initialize(string pluginDir)
		{
			Plugin.Log.LogInfo((object)"Native relay title translation enabled; SYSTEMS ONLINE uses original TMP object only.");
		}

		public static void ForceApplySystemOnlineOverlay(HUDManager? hudManager, string stage)
		{
			TMP_Text val = FindSystemOnlineTitle(hudManager, allowGlobalFallback: false);
			if ((Object)(object)val != (Object)null)
			{
				ApplySystemOnlineNativeTranslation(val, stage);
				return;
			}
			Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=SystemOnline action=not-found"));
			AuditSystemOnlineBranch(stage, hudManager);
		}

		public static void BeginSystemOnlineExactPathWatcher(HUDManager? hudManager, string stage)
		{
			if (!((Object)(object)hudManager == (Object)null) && _systemOnlineWatcher == null)
			{
				_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)
			{
				Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=SystemOnline action=not-found"));
			}
			else
			{
				ApplySystemOnlineNativeTranslation(val, stage);
			}
		}

		public static void QueueSystemOnlineSync(HUDManager? hudManager, string stage)
		{
		}

		public static void TryApplyEnteringAtmosphereOverlayFromLoadingScreen(HUDManager? hudManager, string stage)
		{
			TMP_Text val = FindEnteringAtmosphereTitle(hudManager);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("NativeRelay[" + stage + "] target=EnteringAtmosphere action=not-found"));
			}
			else
			{
				ApplyEnteringAtmosphereNativeTranslation(val, stage);
			}
		}

		public static void HideEnteringAtmosphereOverlayForHud(HUDManager? hudManager, string stage)
		{
			TMP_Text val = FindEnteringAtmosphereTitle(hudManager);
			if ((Object)(object)val != (Object)null)
			{
				ApplyEnteringAtmosphereNativeTranslation(val, stage);
			}
		}

		public static void SyncEnteringAtmosphereOverlayState(TMP_Text? text, string stage)
		{
			if (!((Object)(object)text == (Object)null) && 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) && _fixedSceneLabelWatcher == null)
			{
				_fixedSceneLabelWatcherOwner = hudManager;
				_fixedSceneLabelWatcher = ((MonoBehaviour)hudManager).StartCoroutine(WaitForFixedSceneLabels(stage));
			}
		}

		public static void Shutdown()
		{
			if (_systemOnlineWatcher != null && (Object)(object)_systemOnlineWatcherOwner != (Object)null)
			{
				((MonoBehaviour)_systemOnlineWatcherOwner).StopCoroutine(_systemOnlineWatcher);
			}
			if (_fixedSceneLabelWatcher != null && (Object)(object)_fixedSceneLabelWatcherOwner != (Object)null)
			{
				((MonoBehaviour)_fixedSceneLabelWatcherOwner).StopCoroutine(_fixedSceneLabelWatcher);
			}
			_systemOnlineWatcher = null;
			_fixedSceneLabelWatcher = null;
			_systemOnlineWatcherOwner = null;
			_fixedSceneLabelWatcherOwner = null;
			NativeTextRoleCache.Clear();
		}

		public static void TryReplaceSystemOnlineText(TMP_Text? text, string stage)
		{
			if ((Object)(object)text == (Object)null)
			{
				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");
			Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=FixedSceneLabel action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text));
			return true;
		}

		public static void TryReplaceSystemOnlineText(Text? text, string stage)
		{
		}

		public static void TryReplaceSystemOnlineText(TextMesh? text, string stage)
		{
		}

		public static void TryReplace(Image? image, string stage)
		{
		}

		public static void TryReplace(RawImage? image, string stage)
		{
		}

		public static void TryReplace(SpriteRenderer? renderer, string stage)
		{
		}

		public static void TryReplace(Material? material, string stage)
		{
		}

		private static void ApplySystemOnlineNativeTranslation(TMP_Text text, string stage)
		{
			if (!((Behaviour)text).enabled)
			{
				((Behaviour)text).enabled = true;
			}
			ApplyLocalizedText(text, ResolveLocalizedText(text.text, "系统在线"), stage, "SystemOnline");
			Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=SystemOnline action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text));
		}

		[IteratorStateMachine(typeof(<WaitForSystemOnlineTitle>d__41))]
		private static IEnumerator WaitForSystemOnlineTitle(HUDManager hudManager, string stage)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForSystemOnlineTitle>d__41(0)
			{
				hudManager = hudManager,
				stage = stage
			};
		}

		[IteratorStateMachine(typeof(<WaitForFixedSceneLabels>d__42))]
		private static IEnumerator WaitForFixedSceneLabels(string stage)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForFixedSceneLabels>d__42(0)
			{
				stage = stage
			};
		}

		private static void ApplyEnteringAtmosphereNativeTranslation(TMP_Text text, string stage)
		{
			ApplyLocalizedText(text, ResolveLocalizedText(text.text, "正在进入大气层..."), stage, "EnteringAtmosphere");
		}

		private static void ApplyHazardLevelNativeTranslation(TMP_Text text, string stage)
		{
			ApplyLocalizedText(text, "危险等级:", stage, "HazardLevel");
		}

		private static void ApplyLocalizedText(TMP_Text text, string localized, string stage, string target)
		{
			if (!string.IsNullOrWhiteSpace(localized))
			{
				if (!string.Equals(text.text, localized, StringComparison.Ordinal))
				{
					text.text = localized;
				}
				FontFallbackService.ApplyFallback(text, localized);
				ApplyLifeSupportOfflineTypography(text, localized);
			}
		}

		private static void ApplyLifeSupportOfflineTypography(TMP_Text text, string localized)
		{
			if (string.Equals(localized, "[生命维持:离线]", StringComparison.Ordinal))
			{
				text.richText = true;
				text.enableWordWrapping = false;
				text.overflowMode = (TextOverflowModes)0;
				text.fontStyle = (FontStyles)0;
				text.characterSpacing = Math.Max(text.characterSpacing, 6f);
				text.wordSpacing = Math.Max(text.wordSpacing, 8f);
			}
		}

		private static TMP_Text? FindSystemOnlineTitle(HUDManager? hudManager, bool allowGlobalFallback)
		{
			if ((Object)(object)hudManager != (Object)null)
			{
				if ((Object)(object)((Component)hudManager).transform != (Object)null)
				{
					Transform obj = ((Component)hudManager).transform.Find("BottomMiddle/SystemsOnline/TipLeft1");
					TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
					if (IsExactSystemOnlineTitle(val))
					{
						return val;
					}
				}
				TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val2 in componentsInChildren)
				{
					if (IsExactSystemOnlineTitle(val2))
					{
						return val2;
					}
				}
			}
			if (allowGlobalFallback)
			{
				TMP_Text val3 = FindSystemOnlineTitleByFullPath();
				if (IsExactSystemOnlineTitle(val3))
				{
					return val3;
				}
				TMP_Text[] componentsInChildren = Resources.FindObjectsOfTypeAll<TMP_Text>();
				foreach (TMP_Text val4 in componentsInChildren)
				{
					if (IsExactSystemOnlineTitle(val4))
					{
						return val4;
					}
				}
			}
			return null;
		}

		private static TMP_Text? FindSystemOnlineTitleByFullPath()
		{
			GameObject val = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/BottomMiddle/SystemsOnline/TipLeft1");
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.GetComponent<TMP_Text>();
		}

		private static TMP_Text? FindEnteringAtmosphereTitle(HUDManager? hudManager)
		{
			if ((Object)(object)hudManager?.LoadingScreen == (Object)null)
			{
				return null;
			}
			TMP_Text[] componentsInChildren = ((Component)hudManager.LoadingScreen).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (IsEnteringAtmosphereTitleObject(val))
				{
					return val;
				}
			}
			return null;
		}

		private static TMP_Text? FindHazardLevelTitle(HUDManager? hudManager)
		{
			if ((Object)(object)hudManager == (Object)null)
			{
				return null;
			}
			TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (IsHazardLevelTitle(val.text))
				{
					return val;
				}
			}
			return null;
		}

		private static bool IsSystemOnlineObject(TMP_Text? text)
		{
			return 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))
			{
				return string.Equals(a, "危险等级:", StringComparison.Ordinal);
			}
			return true;
		}

		private static string ResolveLocalizedText(string? current, string fallback)
		{
			if (!string.IsNullOrWhiteSpace(current) && TranslationService.TryTranslate(current, out string translated))
			{
				return translated;
			}
			return fallback;
		}

		private static bool TryResolveFixedSceneLabel(string? current, out string localized)
		{
			localized = string.Empty;
			if (string.IsNullOrWhiteSpace(current))
			{
				return false;
			}
			if (FixedSceneLabels.TryGetValue(current.Trim(), out localized) && !string.IsNullOrWhiteSpace(localized))
			{
				return true;
			}
			return false;
		}

		private static int SyncFixedSceneLabelsInRelayScene(string stage)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Scene sceneByName = SceneManager.GetSceneByName("SampleSceneRelay");
			if (!((Scene)(ref sceneByName)).IsValid() || !((Scene)(ref sceneByName)).isLoaded)
			{
				return 0;
			}
			int num = 0;
			GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects();
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				TMP_Text[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<TMP_Text>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					if (TryReplaceFixedSceneLabel(componentsInChildren[j], stage))
					{
						num++;
					}
				}
			}
			return num;
		}

		private static bool HasNamedAncestor(Transform? transform, string expectedName)
		{
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				if (string.Equals(((Object)val).name, expectedName, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static void AuditSystemOnlineBranch(string stage, HUDManager? hudManager)
		{
			int num = 0;
			if ((Object)(object)hudManager != (Object)null)
			{
				TMP_Text[] componentsInChildren = ((Component)hudManager).GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val in componentsInChildren)
				{
					if (HasNamedAncestor(val.transform, "SystemsOnline"))
					{
						num++;
						Plugin.Log.LogInfo((object)$"NativeRelay[{stage}] target=SystemOnline action=audit exact={IsExactSystemOnlineTitle(val)} name={((Object)val).name} path={BuildPath(val.transform)} text={val.text}");
					}
				}
			}
			_ = 0;
		}

		private static void ApplyDynamicFieldTranslation(TMP_Text? text, string stage, string target)
		{
			if (!((Object)(object)text == (Object)null) && !string.IsNullOrWhiteSpace(text.text) && TranslationService.TryTranslate(text.text, out string translated) && !string.IsNullOrWhiteSpace(translated))
			{
				if (!string.Equals(text.text, translated, StringComparison.Ordinal))
				{
					text.text = translated;
				}
				FontFallbackService.ApplyFallback(text, translated);
				Plugin.Log.LogInfo((object)("NativeRelay[" + stage + "] target=" + target + " action=applied name=" + ((Object)text).name + " path=" + BuildPath(text.transform) + " text=" + text.text));
			}
		}

		private static string BuildPath(Transform? transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "<null>";
			}
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private static bool IsExactSystemOnlineTitle(TMP_Text? text)
		{
			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)
		{
			if (NativeTextRoleCache.Count >= 4096)
			{
				NativeTextRoleCache.Clear();
			}
			NativeTextRoleCache[((Object)text).GetInstanceID()] = new CachedNativeTextRole(GetParentInstanceId(text.transform), role);
		}

		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 CustomLocalizationExtensionService
	{
		private enum MatchKind
		{
			None,
			Exact,
			Contains,
			Regex
		}

		private sealed class RegexEntry
		{
			public string Pattern { get; }

			public Regex Regex { get; }

			public string Replacement { get; }

			public bool Disabled { get; set; }

			public bool WarnedTimeout { get; set; }

			public RegexEntry(string pattern, Regex regex, string replacement)
			{
				Pattern = pattern;
				Regex = regex;
				Replacement = replacement;
			}
		}

		private sealed class StyleRule
		{
			public MatchKind Kind { get; }

			public string Pattern { get; }

			public Regex? Regex { get; set; }

			public Color? Color { get; set; }

			public float? FontSize { get; set; }

			public bool? RichText { get; set; }

			public bool Disabled { get; set; }

			public bool WarnedTimeout { get; set; }

			public bool HasRegex => Kind == MatchKind.Regex;

			public StyleRule(MatchKind kind, string pattern)
			{
				Kind = kind;
				Pattern = pattern;
			}

			public bool IsMatch(string value)
			{
				if (Disabled)
				{
					return false;
				}
				try
				{
					return Kind switch
					{
						MatchKind.Exact => string.Equals(value, Pattern, StringComparison.Ordinal), 
						MatchKind.Contains => value.IndexOf(Pattern, StringComparison.Ordinal) >= 0, 
						MatchKind.Regex => Regex != null && Regex.IsMatch(value), 
						_ => false, 
					};
				}
				catch (RegexMatchTimeoutException)
				{
					Disabled = true;
					if (!WarnedTimeout)
					{
						WarnedTimeout = true;
						Plugin.Log.LogWarning((object)("CustomLocalization regex timeout; disabled style rule '" + Pattern + "'."));
					}
					return false;
				}
			}
		}

		private sealed class CachedStyleLookup
		{
			public string Value { get; }

			public bool AllowRegexStyle { get; }

			public bool Matched { get; }

			public StyleRule? Style { get; }

			public CachedStyleLookup(string value, bool allowRegexStyle, bool matched, StyleRule? style)
			{
				Value = value;
				AllowRegexStyle = allowRegexStyle;
				Matched = matched;
				Style = style;
			}
		}

		[CompilerGenerated]
		private sealed class <ResolveCustomLocalizationDirectories>d__45 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private string pluginDir;

			public string <>3__pluginDir;

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

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

			[DebuggerHidden]
			public <ResolveCustomLocalizationDirectories>d__45(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "V81TestChn", "custom-localization");
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "custom-localization");
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = Path.Combine(Paths.ConfigPath, "V81TestChn", "custom-localization");
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = Path.Combine(Paths.ConfigPath, "V81TestChn", "custom-translations");
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>2__current = Path.Combine(Paths.ConfigPath, "translations", "custom");
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					return false;
				}
			}

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

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

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				<ResolveCustomLocalizationDirectories>d__45 <ResolveCustomLocalizationDirectories>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ResolveCustomLocalizationDirectories>d__ = this;
				}
				else
				{
					<ResolveCustomLocalizationDirectories>d__ = new <ResolveCustomLocalizationDirectories>d__45(0);
				}
				<ResolveCustomLocalizationDirectories>d__.pluginDir = <>3__pluginDir;
				return <ResolveCustomLocalizationDirectories>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		private const int StyleCacheLimit = 2048;

		private const int DefaultMaxExactRules = 4096;

		private const int DefaultMaxIgnoreCaseRules = 4096;

		private const int DefaultMaxRegexRules = 64;

		private const int DefaultMaxStyleRules = 64;

		private const int DefaultMaxLoadedFiles = 32;

		private const int DefaultMaxConfigFileBytes = 262144;

		private static readonly TimeSpan RegexTimeout = TimeSpan.FromMilliseconds(25.0);

		private static readonly Dictionary<string, string> ExactEntries = new Dictionary<string, string>(StringComparer.Ordinal);

		private static readonly Dictionary<string, string> ExactIgnoreCaseEntries = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private static readonly List<RegexEntry> RegexEntries = new List<RegexEntry>();

		private static readonly List<StyleRule> StyleRules = new List<StyleRule>();

		private static readonly Dictionary<int, CachedStyleLookup> StyleCache = new Dictionary<int, CachedStyleLookup>();

		private static ConfigEntry<bool>? _enabled;

		private static ConfigEntry<bool>? _preferCustomTranslations;

		private static ConfigEntry<bool>? _enableRegex;

		private static ConfigEntry<int>? _maxExactRules;

		private static ConfigEntry<int>? _maxIgnoreCaseRules;

		private static ConfigEntry<int>? _maxRegexRules;

		private static ConfigEntry<int>? _maxStyleRules;

		private static ConfigEntry<int>? _maxLoadedFiles;

		private static ConfigEntry<int>? _maxConfigFileBytes;

		private static bool _warnedRegexDisabled;

		private static bool _warnedExactLimit;

		private static bool _warnedIgnoreCaseLimit;

		private static bool _hasStyleRules;

		private static bool _hasGlobalStyleRules;

		public static bool PreferCustomTranslations
		{
			get
			{
				ConfigEntry<bool>? enabled = _enabled;
				if (enabled != null && enabled.Value)
				{
					return _preferCustomTranslations?.Value ?? false;
				}
				return false;
			}
		}

		public static bool EnableRegex
		{
			get
			{
				ConfigEntry<bool>? enabled = _enabled;
				if (enabled != null && enabled.Value)
				{
					return _enableRegex?.Value ?? false;
				}
				return false;
			}
		}

		public static bool HasStyleRules
		{
			get
			{
				ConfigEntry<bool>? enabled = _enabled;
				if (enabled != null && enabled.Value)
				{
					return _hasStyleRules;
				}
				return false;
			}
		}

		public static bool HasGlobalStyleRules
		{
			get
			{
				ConfigEntry<bool>? enabled = _enabled;
				if (enabled != null && enabled.Value)
				{
					return _hasGlobalStyleRules;
				}
				return false;
			}
		}

		public static void Initialize(string pluginDir, ConfigFile config)
		{
			_enabled = config.Bind<bool>("CustomLocalization", "Enabled", true, "Load optional custom localization cfg files from plugin/config custom-localization directories.");
			_preferCustomTranslations = config.Bind<bool>("CustomLocalization", "PreferCustomTranslations", false, "When true, custom exact translations are checked before built-in translations. Regex translations are still gated by EnableRegex.");
			_enableRegex = config.Bind<bool>("CustomLocalization", "EnableRegex", false, "Enable custom regex translations and regex style rules. Disabled by default to keep global text paths cheap.");
			_maxExactRules = config.Bind<int>("CustomLocalization", "MaxExactRules", 4096, "Maximum custom exact translation rules to load.");
			_maxIgnoreCaseRules = config.Bind<int>("CustomLocalization", "MaxIgnoreCaseRules", 4096, "Maximum custom ignorecase translation rules to load.");
			_maxRegexRules = config.Bind<int>("CustomLocalization", "MaxRegexRules", 64, "Maximum custom regex translation rules to load.");
			_maxStyleRules = config.Bind<int>("CustomLocalization", "MaxStyleRules", 64, "Maximum custom style rules to load.");
			_maxLoadedFiles = config.Bind<int>("CustomLocalization", "MaxLoadedFiles", 32, "Maximum custom localization cfg files to load.");
			_maxConfigFileBytes = config.Bind<int>("CustomLocalization", "MaxConfigFileBytes", 262144, "Maximum size in bytes for each custom localization cfg file.");
			Load(pluginDir);
		}

		public static void Shutdown()
		{
			Clear();
			_enabled = null;
			_preferCustomTranslations = null;
			_enableRegex = null;
			_maxExactRules = null;
			_maxIgnoreCaseRules = null;
			_maxRegexRules = null;
			_maxStyleRules = null;
			_maxLoadedFiles = null;
			_maxConfigFileBytes = null;
		}

		public static void Clear()
		{
			ExactEntries.Clear();
			ExactIgnoreCaseEntries.Clear();
			RegexEntries.Clear();
			StyleRules.Clear();
			ClearStyleCache();
			_warnedRegexDisabled = false;
			_warnedExactLimit = false;
			_warnedIgnoreCaseLimit = false;
			_hasStyleRules = false;
			_hasGlobalStyleRules = false;
		}

		public static bool TryTranslateFastExact(string? source, out string translated)
		{
			translated = source ?? string.Empty;
			ConfigEntry<bool>? enabled = _enabled;
			if (enabled == null || !enabled.Value || string.IsNullOrEmpty(source))
			{
				return false;
			}
			if (ExactEntries.TryGetValue(source, out translated) || ExactIgnoreCaseEntries.TryGetValue(source, out translated))
			{
				return !string.Equals(source, translated, StringComparison.Ordinal);
			}
			return false;
		}

		public static bool TryTranslate(string? source, out string translated, bool allowRegex)
		{
			translated = source ?? string.Empty;
			ConfigEntry<bool>? enabled = _enabled;
			if (enabled == null || !enabled.Value || string.IsNullOrEmpty(source))
			{
				return false;
			}
			if (TryTranslateFastExact(source, out translated))
			{
				return true;
			}
			if (!allowRegex || !EnableRegex || RegexEntries.Count == 0)
			{
				return false;
			}
			foreach (RegexEntry regexEntry in RegexEntries)
			{
				if (regexEntry.Disabled)
				{
					continue;
				}
				try
				{
					if (!regexEntry.Regex.IsMatch(source))
					{
						continue;
					}
					translated = regexEntry.Regex.Replace(source, regexEntry.Replacement);
					return !string.Equals(source, translated, StringComparison.Ordinal);
				}
				catch (RegexMatchTimeoutException)
				{
					regexEntry.Disabled = true;
					if (!regexEntry.WarnedTimeout)
					{
						regexEntry.WarnedTimeout = true;
						Plugin.Log.LogWarning((object)("CustomLocalization regex timeout; disabled rule '" + regexEntry.Pattern + "'."));
					}
				}
			}
			return false;
		}

		public static void ApplyStyle(TMP_Text? text, string? value, bool allowRegexStyle = false)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)text == (Object)null) && TryFindStyle((Component)(object)text, value, allowRegexStyle, out StyleRule style))
			{
				if (style.RichText.HasValue)
				{
					text.richText = style.RichText.Value;
				}
				if (style.Color.HasValue)
				{
					((Graphic)text).color = style.Color.Value;
				}
				if (style.FontSize.HasValue)
				{
					text.fontSize = style.FontSize.Value;
				}
			}
		}

		public static void ApplyStyle(Text? text, string? value, bool allowRegexStyle = false)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)text == (Object)null) && TryFindStyle((Component)(object)text, value, allowRegexStyle, out StyleRule style))
			{
				if (style.RichText.HasValue)
				{
					text.supportRichText = style.RichText.Value;
				}
				if (style.Color.HasValue)
				{
					((Graphic)text).color = style.Color.Value;
				}
				if (style.FontSize.HasValue)
				{
					text.fontSize = Mathf.RoundToInt(style.FontSize.Value);
				}
			}
		}

		public static void ApplyStyle(TextMesh? text, string? value, bool allowRegexStyle = false)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)text == (Object)null) && TryFindStyle((Component)(object)text, value, allowRegexStyle, out StyleRule style))
			{
				if (style.RichText.HasValue)
				{
					text.richText = style.RichText.Value;
				}
				if (style.Color.HasValue)
				{
					text.color = style.Color.Value;
				}
				if (style.FontSize.HasValue)
				{
					text.fontSize = Mathf.RoundToInt(style.FontSize.Value);
				}
			}
		}

		private static void Load(string pluginDir)
		{
			Clear();
			ConfigEntry<bool>? enabled = _enabled;
			if (enabled == null || !enabled.Value)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			int maxLoadedFiles = GetMaxLoadedFiles();
			foreach (string item in ResolveCustomLocalizationDirectories(pluginDir))
			{
				if (!Directory.Exists(item))
				{
					continue;
				}
				foreach (string item2 in Directory.EnumerateFiles(item, "*.cfg", SearchOption.AllDirectories))
				{
					if (num2 >= maxLoadedFiles)
					{
						Plugin.Log.LogWarning((object)$"CustomLocalization MaxLoadedFiles={maxLoadedFiles} reached; remaining cfg files skipped.");
						LogLoadSummary(num);
						return;
					}
					num2++;
					if (LoadCfgFile(item2))
					{
						num++;
					}
				}
			}
			LogLoadSummary(num);
		}

		private static void LogLoadSummary(int filesLoaded)
		{
			Plugin.Log.LogInfo((object)$"CustomLocalization loaded files={filesLoaded}; exact={ExactEntries.Count}; ignorecase={ExactIgnoreCaseEntries.Count}; regex={RegexEntries.Count}; style={StyleRules.Count}.");
		}

		[IteratorStateMachine(typeof(<ResolveCustomLocalizationDirectories>d__45))]
		private static IEnumerable<string> ResolveCustomLocalizationDirectories(string pluginDir)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ResolveCustomLocalizationDirectories>d__45(-2)
			{
				<>3__pluginDir = pluginDir
			};
		}

		private static bool LoadCfgFile(string file)
		{
			bool flag = false;
			try
			{
				FileInfo fileInfo = new FileInfo(file);
				int maxConfigFileBytes = GetMaxConfigFileBytes();
				if (fileInfo.Length > maxConfigFileBytes)
				{
					Plugin.Log.LogWarning((object)$"CustomLocalization skipped '{file}' because it is {fileInfo.Length} bytes; MaxConfigFileBytes={maxConfigFileBytes}.");
					return false;
				}
				foreach (string item in File.ReadLines(file))
				{
					string text = item.Trim();
					if (text.Length != 0 && !text.StartsWith("#", StringComparison.Ordinal) && !text.StartsWith("//", StringComparison.Ordinal))
					{
						flag |= TryAddLine(text, file);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("CustomLocalization failed reading '" + file + "': " + ex.GetType().Name + ": " + ex.Message));
			}
			return flag;
		}

		private static bool TryAddLine(string line, string file)
		{
			string text;
			int length;
			if (line.StartsWith("style:", StringComparison.OrdinalIgnoreCase))
			{
				text = line;
				length = "style:".Length;
				return TryAddStyleRule(text.Substring(length, text.Length - length), file);
			}
			int num = FindUnescapedSeparator(line, '=');
			if (num <= 0)
			{
				return false;
			}
			string text2 = line.Substring(0, num).Trim();
			text = line;
			length = num + 1;
			string text3 = UnescapeCustomValue(text.Substring(length, text.Length - length));
			if (text2.StartsWith("regex:", StringComparison.OrdinalIgnoreCase) || text2.StartsWith("r:", StringComparison.OrdinalIgnoreCase))
			{
				string text4;
				if (!text2.StartsWith("regex:", StringComparison.OrdinalIgnoreCase))
				{
					text = text2;
					length = "r:".Length;
					text4 = text.Substring(length, text.Length - length);
				}
				else
				{
					text = text2;
					length = "regex:".Length;
					text4 = text.Substring(length, text.Length - length);
				}
				return TryAddRegex(UnescapeCustomRegexPattern(text4.Trim()).Trim(), text3, file);
			}
			if (text2.StartsWith("ignorecase:", StringComparison.OrdinalIgnoreCase) || text2.StartsWith("i:", StringComparison.OrdinalIgnoreCase))
			{
				string value;
				if (!text2.StartsWith("ignorecase:", StringComparison.OrdinalIgnoreCase))
				{
					text = text2;
					length = "i:".Length;
					value = text.Substring(length, text.Length - length);
				}
				else
				{
					text = text2;
					length = "ignorecase:".Length;
					value = text.Substring(length, text.Length - length);
				}
				return TryAddExact(UnescapeCustomValue(value).Trim(), text3, ignoreCase: true, file);
			}
			string text5 = text2;
			if (text5.StartsWith("exact:", StringComparison.OrdinalIgnoreCase))
			{
				text = text5;
				length = "exact:".Length;
				text5 = text.Substring(length, text.Length - length).Trim();
			}
			text5 = UnescapeCustomValue(text5).Trim();
			return TryAddExact(text5, text3, ignoreCase: false, file);
		}

		private static bool TryAddExact(string key, string value, bool ignoreCase, string file)
		{
			if (string.IsNullOrWhiteSpace(key))
			{
				return false;
			}
			if (ignoreCase)
			{
				if (!ExactIgnoreCaseEntries.ContainsKey(key) && ExactIgnoreCaseEntries.Count >= GetMaxIgnoreCaseRules())
				{
					WarnIgnoreCaseLimitOnce(file);
					return false;
				}
				ExactIgnoreCaseEntries[key] = value;
				return true;
			}
			if (!ExactEntries.ContainsKey(key) && ExactEntries.Count >= GetMaxExactRules())
			{
				WarnExactLimitOnce(file);
				return false;
			}
			ExactEntries[key] = value;
			return true;
		}

		private static bool TryAddRegex(string pattern, string replacement, string file)
		{
			if (string.IsNullOrWhiteSpace(pattern))
			{
				return false;
			}
			if (!EnableRegex)
			{
				WarnRegexDisabledOnce();
				return false;
			}
			int maxRegexRules = GetMaxRegexRules();
			if (RegexEntries.Count >= maxRegexRules)
			{
				Plugin.Log.LogWarning((object)$"CustomLocalization skipped regex in '{file}' because MaxRegexRules={maxRegexRules} was reached.");
				return false;
			}
			try
			{
				RegexEntries.Add(new RegexEntry(pattern, new Regex(pattern, RegexOptions.Compiled | RegexOptions.CultureInvariant, RegexTimeout), replacement));
				return true;
			}
			catch (Exception ex) when (((ex is ArgumentException || ex is RegexMatchTimeoutException) ? 1 : 0) != 0)
			{
				Plugin.Log.LogWarning((object)("CustomLocalization skipped invalid regex in '" + file + "': " + ex.GetType().Name + ": " + ex.Message));
				return false;
			}
		}

		private static bool TryAddStyleRule(string payload, string file)
		{
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = SplitUnescaped(payload, '|');
			if (list.Count == 0)
			{
				return false;
			}
			int maxStyleRules = GetMaxStyleRules();
			if (StyleRules.Count >= maxStyleRules)
			{
				Plugin.Log.LogWarning((object)$"CustomLocalization skipped style rule in '{file}' because MaxStyleRules={maxStyleRules} was reached.");
				return false;
			}
			string text = list[0].Trim();
			int num = FindUnescapedSeparator(text, ':');
			if (num <= 0 || num >= text.Length - 1)
			{
				return false;
			}
			MatchKind matchKind = ParseMatchKind(UnescapeCustomValue(text.Substring(0, num)));
			string text2 = text;
			int num2 = num + 1;
			string value = text2.Substring(num2, text2.Length - num2).Trim();
			string text3 = ((matchKind == MatchKind.Regex) ? UnescapeCustomRegexPattern(value) : UnescapeCustomValue(value));
			text3 = text3.Trim();
			if (matchKind == MatchKind.None || string.IsNullOrWhiteSpace(text3))
			{
				return false;
			}
			if (matchKind == MatchKind.Regex && !EnableRegex)
			{
				WarnRegexDisabledOnce();
				return false;
			}
			StyleRule styleRule = new StyleRule(matchKind, text3);
			Color val = default(Color);
			for (int i = 1; i < list.Count; i++)
			{
				int num3 = FindUnescapedSeparator(list[i], '=');
				if (num3 <= 0)
				{
					continue;
				}
				string text4 = UnescapeCustomValue(list[i].Substring(0, num3)).Trim();
				text2 = list[i];
				num2 = num3 + 1;
				string text5 = UnescapeCustomValue(text2.Substring(num2, text2.Length - num2)).Trim();
				float result;
				bool result2;
				if (text4.Equals("color", StringComparison.OrdinalIgnoreCase) && ColorUtility.TryParseHtmlString(text5, ref val))
				{
					if (val.a <= 0f)
					{
						Plugin.Log.LogWarning((object)("CustomLocalization style in '" + file + "' has alpha=0 and will be invisible."));
					}
					styleRule.Color = val;
				}
				else if (text4.Equals("fontSize", StringComparison.OrdinalIgnoreCase) && float.TryParse(text5, NumberStyles.Float, CultureInfo.InvariantCulture, out result) && result > 0f)
				{
					styleRule.FontSize = Mathf.Clamp(result, 4f, 128f);
				}
				else if (text4.Equals("richText", StringComparison.OrdinalIgnoreCase) && bool.TryParse(text5, out result2))
				{
					styleRule.RichText = result2;
				}
			}
			if (!styleRule.Color.HasValue && !styleRule.FontSize.HasValue && !styleRule.RichText.HasValue)
			{
				return false;
			}
			if (matchKind == MatchKind.Regex)
			{
				try
				{
					styleRule.Regex = new Regex(text3, RegexOptions.Compiled | RegexOptions.CultureInvariant, RegexTimeout);
				}
				catch (Exception ex) when (((ex is ArgumentException || ex is RegexMatchTimeoutException) ? 1 : 0) != 0)
				{
					Plugin.Log.LogWarning((object)("CustomLocalization skipped invalid style regex in '" + file + "': " + ex.GetType().Name + ": " + ex.Message));
					return false;
				}
			}
			StyleRules.Add(styleRule);
			_hasStyleRules = true;
			if (!styleRule.HasRegex)
			{
				_hasGlobalStyleRules = true;
			}
			ClearStyleCache();
			return true;
		}

		private static bool TryFindStyle(Component component, string? value, bool allowRegexStyle, out StyleRule style)
		{
			style = null;
			ConfigEntry<bool>? enabled = _enabled;
			if (enabled == null || !enabled.Value || string.IsNullOrEmpty(value))
			{
				return false;
			}
			int instanceID = ((Object)component).GetInstanceID();
			if (TryGetCachedStyle(instanceID, value, allowRegexStyle, out var matched, out style))
			{
				return matched;
			}
			bool flag = TryFindStyle(value, allowRegexStyle, out style);
			CacheStyleResult(instanceID, value, allowRegexStyle, flag, style);
			return flag;
		}

		private static bool TryFindStyle(string value, bool allowRegexStyle, out StyleRule style)
		{
			style = null;
			foreach (StyleRule styleRule in StyleRules)
			{
				if ((!styleRule.HasRegex || allowRegexStyle) && styleRule.IsMatch(value))
				{
					style = styleRule;
					return true;
				}
			}
			return false;
		}

		private static bool TryGetCachedStyle(int componentId, string value, bool allowRegexStyle, out bool matched, out StyleRule style)
		{
			style = null;
			matched = false;
			if (!StyleCache.TryGetValue(componentId, out CachedStyleLookup value2) || !string.Equals(value2.Value, value, StringComparison.Ordinal) || value2.AllowRegexStyle != allowRegexStyle)
			{
				return false;
			}
			style = value2.Style;
			matched = value2.Matched;
			return true;
		}

		private static void CacheStyleResult(int componentId, string value, bool allowRegexStyle, bool matched, StyleRule? style)
		{
			if (StyleCache.Count >= 2048)
			{
				StyleCache.Clear();
			}
			StyleCache[componentId] = new CachedStyleLookup(value, allowRegexStyle, matched, style);
		}

		private static void ClearStyleCache()
		{
			StyleCache.Clear();
		}

		public static void ClearStyleCacheOnly()
		{
			ClearStyleCache();
		}

		public static void ClearRuntimeCaches()
		{
			ClearStyleCache();
		}

		private static int FindUnescapedSeparator(string value, char separator)
		{
			bool flag = false;
			bool flag2 = false;
			for (int i = 0; i < value.Length; i++)
			{
				char c = value[i];
				if (flag)
				{
					flag = false;
					continue;
				}
				switch (c)
				{
				case '\\':
					flag = true;
					continue;
				case '<':
					flag2 = true;
					continue;
				case '>':
					flag2 = false;
					continue;
				}
				if (!flag2 && c == separator)
				{
					return i;
				}
			}
			return -1;
		}

		private static List<string> SplitUnescaped(string value, char separator)
		{
			List<string> list = new List<string>();
			int num2;
			for (int i = 0; i <= value.Length; i += num2 + 1)
			{
				string text = value;
				int num = i;
				num2 = FindUnescapedSeparator(text.Substring(num, text.Length - num), separator);
				if (num2 < 0)
				{
					text = value;
					num = i;
					list.Add(text.Substring(num, text.Length - num));
					break;
				}
				list.Add(value.Substring(i, num2));
			}
			return list;
		}

		private static string UnescapeCustomValue(string value)
		{
			if (value.IndexOf('\\') < 0)
			{
				return value;
			}
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			bool flag = false;
			foreach (char c in value)
			{
				if (!flag)
				{
					if (c == '\\')
					{
						flag = true;
					}
					else
					{
						stringBuilder.Append(c);
					}
					continue;
				}
				StringBuilder stringBuilder2 = stringBuilder;
				stringBuilder2.Append(c switch
				{
					'n' => '\n', 
					'r' => '\r', 
					't' => '\t', 
					_ => c, 
				});
				flag = false;
			}
			if (flag)
			{
				stringBuilder.Append('\\');
			}
			return stringBuilder.ToString();
		}

		private static string UnescapeCustomRegexPattern(string value)
		{
			if (value.IndexOf('\\') < 0)
			{
				return value;
			}
			StringBuilder stringBuilder = new StringBuilder(value.Length);
			bool flag = false;
			foreach (char c in value)
			{
				if (!flag)
				{
					if (c == '\\')
					{
						flag = true;
					}
					else
					{
						stringBuilder.Append(c);
					}
					continue;
				}
				if ((c == '=' || c == '\\' || c == '|') ? true : false)
				{
					stringBuilder.Append(c);
				}
				else
				{
					stringBuilder.Append('\\');
					stringBuilder.Append(c);
				}
				flag = false;
			}
			if (flag)
			{
				stringBuilder.Append('\\');
			}
			return stringBuilder.ToString();
		}

		private static void WarnRegexDisabledOnce()
		{
			if (!_warnedRegexDisabled)
			{
				_warnedRegexDisabled = true;
				Plugin.Log.LogWarning((object)"CustomLocalization.EnableRegex=false; skipped custom regex rule(s).");
			}
		}

		private static void WarnExactLimitOnce(string file)
		{
			if (!_warnedExactLimit)
			{
				_warnedExactLimit = true;
				Plugin.Log.LogWarning((object)$"CustomLocalization skipped exact rule in '{file}' because MaxExactRules={GetMaxExactRules()} was reached.");
			}
		}

		private static void WarnIgnoreCaseLimitOnce(string file)
		{
			if (!_warnedIgnoreCaseLimit)
			{
				_warnedIgnoreCaseLimit = true;
				Plugin.Log.LogWarning((object)$"CustomLocalization skipped ignorecase rule in '{file}' because MaxIgnoreCaseRules={GetMaxIgnoreCaseRules()} was reached.");
			}
		}

		private static int GetMaxExactRules()
		{
			return Math.Max(0, _maxExactRules?.Value ?? 4096);
		}

		private static int GetMaxIgnoreCaseRules()
		{
			return Math.Max(0, _maxIgnoreCaseRules?.Value ?? 4096);
		}

		private static int GetMaxRegexRules()
		{
			return Math.Max(0, _maxRegexRules?.Value ?? 64);
		}

		private static int GetMaxStyleRules()
		{
			return Math.Max(0, _maxStyleRules?.Value ?? 64);
		}

		private static int GetMaxLoadedFiles()
		{
			return Math.Max(0, _maxLoadedFiles?.Value ?? 32);
		}

		private static int GetMaxConfigFileBytes()
		{
			return Math.Max(1024, _maxConfigFileBytes?.Value ?? 262144);
		}

		private static MatchKind ParseMatchKind(string value)
		{
			if (value.Equals("exact", StringComparison.OrdinalIgnoreCase))
			{
				return MatchKind.Exact;
			}
			if (value.Equals("contains", StringComparison.OrdinalIgnoreCase))
			{
				return MatchKind.Contains;
			}
			if (!value.Equals("regex", StringComparison.OrdinalIgnoreCase) && !value.Equals("r", StringComparison.OrdinalIgnoreCase))
			{
				return MatchKind.None;
			}
			return MatchKind.Regex;
		}
	}
	internal static class TranslationService
	{
		internal static class ChatDynamicTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				string text = StripRichTextTagsCheap(source).Trim();
				if (!text.EndsWith(" joined the ship.", StringComparison.OrdinalIgnoreCase) && !text.EndsWith(" started the ship.", StringComparison.OrdinalIgnoreCase) && !text.EndsWith(" disconnected.", StringComparison.OrdinalIgnoreCase) && !text.EndsWith(" was left behind.", StringComparison.OrdinalIgnoreCase) && !text.EndsWith(" was kicked.", StringComparison.OrdinalIgnoreCase))
				{
					return text.EndsWith(" died.", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}

			public static bool Translate(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				string text = source.Trim();
				if (TryUnwrapColorTag(text, out string openTag, out string body, out string closeTag) && Translate(body, out string translated2))
				{
					translated = openTag + translated2 + closeTag;
					return true;
				}
				(string, string)[] array = new(string, string)[6]
				{
					(" joined the ship.", " 加入了飞船。"),
					(" started the ship.", " 启动了飞船。"),
					(" disconnected.", " 断开了连接。"),
					(" was left behind.", " 被抛下了。"),
					(" was kicked.", " 被踢出了。"),
					(" died.", " 死亡了。")
				};
				for (int i = 0; i < array.Length; i++)
				{
					var (text2, text3) = array[i];
					if (text.EndsWith(text2, StringComparison.OrdinalIgnoreCase) && text.Length > text2.Length)
					{
						string text4 = text;
						int length = text2.Length;
						translated = text4.Substring(0, text4.Length - length) + text3;
						return true;
					}
				}
				return false;
			}

			private static bool TryUnwrapColorTag(string source, out string openTag, out string body, out string closeTag)
			{
				openTag = string.Empty;
				body = source;
				closeTag = string.Empty;
				if (!source.StartsWith("<color=", StringComparison.OrdinalIgnoreCase) || !source.EndsWith("</color>", StringComparison.OrdinalIgnoreCase))
				{
					return false;
				}
				int num = source.IndexOf('>');
				if (num <= 0)
				{
					return false;
				}
				openTag = source.Substring(0, num + 1);
				closeTag = source.Substring(source.Length - "</color>".Length, "</color>".Length);
				body = source.Substring(num + 1, source.Length - num - 1 - "</color>".Length);
				return true;
			}
		}

		internal static class ControlTipTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				if (!LooksLikeControlTipTextCheap(source))
				{
					return LooksLikeSuitChangePromptCheap(source);
				}
				return true;
			}

			public static bool Translate(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				if (TranslateSuitChangePrompt(source, out translated))
				{
					return true;
				}
				string source2 = source.Trim();
				Match match = SafeRegexMatch(source2, "^Drop\\s+(?<item>.+?)\\s*[:\\uff1a]\\s*(?<key>\\[[^\\]]+\\])$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match.Success)
				{
					string text = BuildTerminalLocalizedItemName(match.Groups["item"].Value.Trim());
					translated = "丢弃 " + text + ":" + match.Groups["key"].Value.Trim();
					return true;
				}
				Match match2 = SafeRegexMatch(source2, "^(?<action>.+?)\\s*[:\\uff1a]\\s*(?<key>\\[[^\\]]+\\])(?<suffix>.*)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match2.Success)
				{
					return false;
				}
				bool impliesHold;
				string key = NormalizeAction(match2.Groups["action"].Value, out impliesHold);
				if (!ControlTipActionEntries.TryGetValue(key, out string value))
				{
					return false;
				}
				string text2 = match2.Groups["key"].Value.Trim();
				string text3 = NormalizeSuffix(match2.Groups["suffix"].Value, impliesHold);
				translated = value + ":" + text2 + text3;
				return true;
			}

			private static bool TranslateSuitChangePrompt(string source, out string translated)
			{
				translated = source;
				Match match = SafeRegexMatch(StripRichTextTags(source).Trim(), "^(?:Change|\\u66f4\\u6362\\u670d\\u88c5)\\s*[:\\uff1a]\\s*(?<suit>.+?)\\s*$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match.Success)
				{
					return false;
				}
				string text = match.Groups["suit"].Value.Trim();
				if (text.Length == 0)
				{
					return false;
				}
				translated = "更换服装:" + BuildTerminalLocalizedItemName(text);
				return true;
			}

			public static bool TranslateStandalone(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				bool impliesHold;
				string key = NormalizeAction(StripRichTextTags(source), out impliesHold);
				if (!ControlTipActionEntries.TryGetValue(key, out translated))
				{
					return false;
				}
				if (impliesHold)
				{
					translated += "(长按)";
				}
				return true;
			}

			public static bool TranslateStandaloneFast(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				string text = StripRichTextTagsCheap(source).Trim();
				if (text.Length == 0)
				{
					return false;
				}
				bool flag = false;
				if (text.EndsWith(" hold", StringComparison.OrdinalIgnoreCase))
				{
					flag = true;
					string text2 = text;
					int length = " hold".Length;
					text = text2.Substring(0, text2.Length - length).TrimEnd();
				}
				if (!ControlTipActionEntries.TryGetValue(text, out translated))
				{
					return false;
				}
				if (flag)
				{
					translated += "(长按)";
				}
				return true;
			}

			private static bool LooksLikeSuitChangePromptCheap(string? source)
			{
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				string text = StripRichTextTagsCheap(source).TrimStart();
				if (!text.StartsWith("Change:", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("Change:", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("更换服装:", StringComparison.Ordinal))
				{
					return text.StartsWith("更换服装:", StringComparison.Ordinal);
				}
				return true;
			}

			private static string NormalizeAction(string action, out bool impliesHold)
			{
				impliesHold = false;
				string text = SafeRegexReplace(action, "\\s+", " ", RegexOptions.CultureInvariant).Trim();
				if (text.EndsWith(" hold", StringComparison.OrdinalIgnoreCase))
				{
					impliesHold = true;
					string text2 = text;
					int length = " hold".Length;
					text = text2.Substring(0, text2.Length - length).TrimEnd();
				}
				return text;
			}

			private static string NormalizeSuffix(string suffix, bool actionImpliesHold)
			{
				string text = SafeRegexReplace(suffix ?? string.Empty, "\\s+", " ", RegexOptions.CultureInvariant).Trim();
				if (actionImpliesHold || text.Contains("Hold", StringComparison.OrdinalIgnoreCase) || text.Contains("长按", StringComparison.Ordinal))
				{
					return "(长按)";
				}
				if (text.Length != 0)
				{
					return " " + text;
				}
				return string.Empty;
			}
		}

		internal static class EndGameDynamicTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				if (!LooksLikeEndgameStatTextCheap(source) && !LooksLikeVoteTextCheap(source) && !LooksLikeDaysLeftTextCheap(source) && (source == null || source.IndexOf("Dead", StringComparison.OrdinalIgnoreCase) < 0))
				{
					if (source == null)
					{
						return false;
					}
					return source.IndexOf("YOU ARE FIRED", StringComparison.OrdinalIgnoreCase) >= 0;
				}
				return true;
			}

			public static bool Translate(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				if (!TranslateStatLine(source, out translated) && !TranslatePlayersFired(source, out translated) && !HudDynamicTranslator.TranslateVotes(source, out translated) && !HudDynamicTranslator.TranslateDaysLeft(source, out translated))
				{
					return TranslatePlayerStatus(source, out translated);
				}
				return true;
			}

			public static bool TranslateStatLine(string source, out string translated)
			{
				translated = source;
				string source2 = source.Trim();
				Match match = SafeRegexMatch(source2, "^(?<count>\\d+)\\s+(?:casualties|\\u4eba\\u4f24\\u4ea1)\\s*[:\\uff1a]\\s*(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match.Success)
				{
					translated = match.Groups["count"].Value + " 人伤亡:" + match.Groups["value"].Value.Trim();
					return true;
				}
				Match match2 = SafeRegexMatch(source2, "^(?<open>[<\\(])(?<count>\\d+)\\s+bodies recovered(?<close>[>\\)])$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match2.Success)
				{
					translated = match2.Groups["open"].Value + match2.Groups["count"].Value + " 具尸体已回收" + match2.Groups["close"].Value;
					return true;
				}
				Match match3 = SafeRegexMatch(source2, "^(?<count>\\d+)\\s+bodies recovered$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match3.Success)
				{
					translated = match3.Groups["count"].Value + " 具尸体已回收";
					return true;
				}
				Match match4 = SafeRegexMatch(source2, "^DUE:\\s*(?<amount>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match4.Success)
				{
					translated = "应付:" + match4.Groups["amount"].Value.Trim();
					return true;
				}
				Match match5 = SafeRegexMatch(source2, "^Days on the job\\s*:\\s*(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match5.Success)
				{
					translated = "工作天数:" + match5.Groups["value"].Value.Trim();
					return true;
				}
				Match match6 = SafeRegexMatch(source2, "^Scrap value collected\\s*:\\s*(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match6.Success)
				{
					translated = "收集废料价值:" + match6.Groups["value"].Value.Trim();
					return true;
				}
				Match match7 = SafeRegexMatch(source2, "^Deaths\\s*:\\s*(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match7.Success)
				{
					translated = "死亡次数:" + match7.Groups["value"].Value.Trim();
					return true;
				}
				Match match8 = SafeRegexMatch(source2, "^Steps taken\\s*:\\s*(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match8.Success)
				{
					translated = "行走步数:" + match8.Groups["value"].Value.Trim();
					return true;
				}
				return false;
			}

			public static bool TranslatePlayersFired(string source, out string translated)
			{
				translated = source;
				string a = source.Trim();
				if (string.Equals(a, "YOU ARE FIRED.", StringComparison.OrdinalIgnoreCase))
				{
					translated = "你被解雇了!";
					return true;
				}
				if (string.Equals(a, "You did not meet the profit quota before the deadline.", StringComparison.OrdinalIgnoreCase))
				{
					translated = "你未能在截止日期前达到目标金额";
					return true;
				}
				return false;
			}

			public static bool TranslatePlayerStatus(string source, out string translated)
			{
				translated = source;
				string source2 = source.Trim();
				if (TranslateStatusToken(source2, out translated))
				{
					return true;
				}
				Match match = SafeRegexMatch(source2, "^(?<name>[\\s\\S]+?)(?<sep>\\r?\\n|\\s+)\\(?(?<status>Dead|Deceased|Missing)\\)?$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match.Success || !TranslateStatusToken(match.Groups["status"].Value, out string translated2))
				{
					return false;
				}
				translated = match.Groups["name"].Value.TrimEnd() + match.Groups["sep"].Value + translated2;
				return true;
			}

			private static bool TranslateStatusToken(string source, out string translated)
			{
				translated = source.Trim() switch
				{
					"(Dead)" => "(死亡)", 
					"Dead" => "(死亡)", 
					"Deceased" => "(死亡)", 
					"(Deceased)" => "(死亡)", 
					"Missing" => "(失踪)", 
					"(Missing)" => "(失踪)", 
					_ => string.Empty, 
				};
				return translated.Length > 0;
			}
		}

		internal static class HudDynamicTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				if (!LooksLikeRandomSeedTextCheap(source) && !LooksLikeVoteTextCheap(source))
				{
					return LooksLikeDaysLeftTextCheap(source);
				}
				return true;
			}

			public static bool Translate(DynamicTextDomain domain, string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				return domain switch
				{
					DynamicTextDomain.HudScanner => TranslateScanValue(source, out translated) || TranslateFast(source, out translated), 
					DynamicTextDomain.HudRewards => TranslateRewardLine(source, out translated) || TranslateFast(source, out translated), 
					_ => TranslateFast(source, out translated), 
				};
			}

			public static bool TranslateFast(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				if (!TranslateRandomSeedFast(source, out translated) && !TranslateVotesFast(source, out translated))
				{
					return TranslateDaysLeftFast(source, out translated);
				}
				return true;
			}

			public static bool TranslateRandomSeed(string source, out string translated)
			{
				translated = source;
				Match match = SafeRegexMatch(StripRichTextTags(source).Trim(), "^Random\\s+seed\\s*:\\s*(?<seed>[+-]?\\d+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match.Success)
				{
					return false;
				}
				translated = "随机种子:" + match.Groups["seed"].Value;
				return true;
			}

			public static bool TranslateVotes(string source, out string translated)
			{
				translated = source;
				Match match = SafeRegexMatch(StripRichTextTags(source).Trim(), "^(?<open>[\\(\\uff08]?)(?<votes>\\d+\\s*/\\s*\\d+)\\s+Votes?(?<close>[\\)\\uff09]?)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match.Success)
				{
					return false;
				}
				string text = SafeRegexReplace(match.Groups["votes"].Value, "\\s+", string.Empty, RegexOptions.CultureInvariant);
				bool flag = match.Groups["open"].Value.Length > 0 || match.Groups["close"].Value.Length > 0;
				translated = (flag ? ("(" + text + " 票)") : (text + " 票"));
				return true;
			}

			public static bool TranslateDaysLeft(string source, out string translated)
			{
				translated = source;
				Match match = SafeRegexMatch(StripRichTextTags(source).Trim(), "^(?<days>\\d+)\\s+Days?\\s+Left$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match.Success)
				{
					return false;
				}
				translated = "剩余 " + match.Groups["days"].Value + " 天";
				return true;
			}

			public static bool TranslateScanValue(string source, out string translated)
			{
				translated = source;
				Match match = SafeRegexMatch(StripRichTextTags(source).Trim(), "^VALUE\\s*:\\s*(?<value>.+?)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match.Success)
				{
					return false;
				}
				translated = "价值:" + match.Groups["value"].Value.Trim();
				return true;
			}

			public static bool TranslateRewardLine(string source, out string translated)
			{
				translated = source;
				string text = source.Trim();
				if (text.Length == 0)
				{
					return false;
				}
				Match match = SafeRegexMatch(text, "^TOTAL\\s*[:\\uff1a]\\s*(?<amount>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match.Success)
				{
					translated = "总计:" + match.Groups["amount"].Value.Trim();
					return true;
				}
				Match match2 = SafeRegexMatch(StripRichTextTags(text), "^Value\\s*[:\\uff1a]\\s*(?<value>.+)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match2.Success)
				{
					translated = "价值:" + match2.Groups["value"].Value.Trim();
					return true;
				}
				Match match3 = SafeRegexMatch(text, "^(?<item>.+?)\\s+collected!$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match3.Success)
				{
					string text2 = BuildTerminalLocalizedItemName(match3.Groups["item"].Value.Trim());
					translated = text2 + "已收集!";
					return true;
				}
				Match match4 = SafeRegexMatch(text, "^(?<amount>\\$?\\s*[+-]?\\d+(?:\\.\\d+)?)\\s+Collected$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (match4.Success)
				{
					translated = SafeRegexReplace(match4.Groups["amount"].Value, "\\s+", string.Empty, RegexOptions.CultureInvariant) + " 已收集";
					return true;
				}
				Match match5 = SafeRegexMatch(text, "^(?<item>.+?)\\s*(?<count>\\(x\\d+\\))?\\s*[:\\uff1a]\\s*(?<value>\\$?\\s*[+-]?\\d+(?:\\.\\d+)?)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match5.Success)
				{
					return false;
				}
				string text3 = match5.Groups["item"].Value.Trim();
				if (text3.Equals("DUE", StringComparison.OrdinalIgnoreCase) || text3.Equals("VALUE", StringComparison.OrdinalIgnoreCase) || text3.Equals("Random seed", StringComparison.OrdinalIgnoreCase) || text3.Equals("DEADLINE", StringComparison.OrdinalIgnoreCase) || text3.Equals("PROFIT QUOTA", StringComparison.OrdinalIgnoreCase))
				{
					return false;
				}
				string text4 = BuildTerminalLocalizedItemName(text3);
				string text5 = match5.Groups["count"].Value.Trim();
				string text6 = SafeRegexReplace(match5.Groups["value"].Value, "\\s+", string.Empty, RegexOptions.CultureInvariant);
				translated = ((text5.Length == 0) ? (text4 + ":" + text6) : (text4 + " " + text5 + ":" + text6));
				return true;
			}

			private static bool TranslateRandomSeedFast(string source, out string translated)
			{
				translated = source;
				string text = StripRichTextTagsCheap(source).Trim();
				if (!text.StartsWith("Random seed:", StringComparison.OrdinalIgnoreCase))
				{
					return false;
				}
				string text2 = text;
				int length = "Random seed:".Length;
				string text3 = text2.Substring(length, text2.Length - length).Trim();
				if (!LooksLikeSignedInteger(text3))
				{
					return false;
				}
				translated = "随机种子:" + text3;
				return true;
			}

			private static bool TranslateVotesFast(string source, out string translated)
			{
				translated = source;
				string text = StripRichTextTagsCheap(source).Trim();
				int num;
				if (text.Length >= 2)
				{
					if (text[0] == '(')
					{
						if (text[text.Length - 1] == ')')
						{
							num = 1;
							goto IL_0061;
						}
					}
					if (text[0] == '(')
					{
						num = ((text[text.Length - 1] == ')') ? 1 : 0);
					}
					else
					{
						num = 0;
					}
				}
				else
				{
					num = 0;
				}
				goto IL_0061;
				IL_0061:
				bool flag = (byte)num != 0;
				string text2;
				string text3;
				if (!flag)
				{
					text2 = text;
				}
				else
				{
					text3 = text;
					text2 = text3.Substring(1, text3.Length - 1 - 1).Trim();
				}
				string text4 = text2;
				int num2 = (text4.EndsWith(" Votes", StringComparison.OrdinalIgnoreCase) ? " Votes".Length : (text4.EndsWith(" Vote", StringComparison.OrdinalIgnoreCase) ? " Vote".Length : 0));
				if (num2 == 0)
				{
					return false;
				}
				text3 = text4;
				int num3 = num2;
				string text5 = RemoveAsciiWhitespace(text3.Substring(0, text3.Length - num3));
				int num4 = text5.IndexOf('/');
				if (num4 > 0 && num4 < text5.Length - 1 && AllDigits(text5.Substring(0, num4)))
				{
					text3 = text5;
					num3 = num4 + 1;
					if (AllDigits(text3.Substring(num3, text3.Length - num3)))
					{
						translated = (flag ? ("(" + text5 + " 票)") : (text5 + " 票"));
						return true;
					}
				}
				return false;
			}

			private static bool TranslateDaysLeftFast(string source, out string translated)
			{
				translated = source;
				string text = StripRichTextTagsCheap(source).Trim();
				int num = (text.EndsWith(" Days Left", StringComparison.OrdinalIgnoreCase) ? " Days Left".Length : (text.EndsWith(" Day Left", StringComparison.OrdinalIgnoreCase) ? " Day Left".Length : 0));
				if (num == 0)
				{
					return false;
				}
				string text2 = text;
				int num2 = num;
				string text3 = text2.Substring(0, text2.Length - num2).Trim();
				if (!AllDigits(text3))
				{
					return false;
				}
				translated = "剩余 " + text3 + " 天";
				return true;
			}
		}

		internal static class PlanetInfoDynamicTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				return LooksLikePlanetInfoTextCheap(source);
			}

			public static bool Translate(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (!string.IsNullOrWhiteSpace(source))
				{
					return TranslateLine(source, out translated);
				}
				return false;
			}

			public static bool TranslateFast(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source) || !CanHandleCheap(source))
				{
					return false;
				}
				if (source.IndexOf('\n') < 0)
				{
					return TranslateLineFast(source, out translated);
				}
				bool flag = false;
				StringBuilder stringBuilder = new StringBuilder(source.Length + 16);
				int num = 0;
				while (num <= source.Length)
				{
					int num2 = source.IndexOf('\n', num);
					int num3 = ((num2 < 0) ? source.Length : num2);
					int num4 = num;
					string text = source.Substring(num4, num3 - num4);
					bool flag2 = text.EndsWith("\r", StringComparison.Ordinal);
					string source2;
					if (!flag2)
					{
						source2 = text;
					}
					else
					{
						string text2 = text;
						source2 = text2.Substring(0, text2.Length - 1);
					}
					if (TranslateLineFast(source2, out string translated2))
					{
						stringBuilder.Append(translated2);
						if (flag2)
						{
							stringBuilder.Append('\r');
						}
						flag = true;
					}
					else
					{
						stringBuilder.Append(text);
					}
					if (num2 < 0)
					{
						break;
					}
					stringBuilder.Append('\n');
					num = num2 + 1;
				}
				if (!flag)
				{
					return false;
				}
				translated = stringBuilder.ToString();
				return true;
			}

			public static bool TranslateLine(string source, out string translated)
			{
				translated = source;
				string text = StripRichTextTags(source).Trim();
				if (text.Length == 0)
				{
					return false;
				}
				(string, string, bool)[] array = new(string, string, bool)[13]
				{
					("CELESTIAL BODY:", "天体:", false),
					("CELESTIAL_BODY:", "天体:", false),
					("天体:", "天体:", false),
					("天体:", "天体:", false),
					("POPULATION:", "人口:", true),
					("人口:", "人口:", true),
					("人口:", "人口:", true),
					("CONDITIONS:", "环境:", true),
					("环境:", "环境:", true),
					("环境:", "环境:", true),
					("FAUNA:", "生态:", true),
					("生态:", "生态:", true),
					("生态:", "生态:", true)
				};
				for (int i = 0; i < array.Length; i++)
				{
					var (text2, text3, flag) = array[i];
					if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
					{
						string text4 = text;
						int length = text2.Length;
						string text5 = text4.Substring(length, text4.Length - length).Trim();
						translated = ((text5.Length == 0) ? text3 : (text3 + " " + (flag ? TranslateKnownValue(text5) : text5)));
						return true;
					}
				}
				return false;
			}

			public static string TranslateKnownValue(string value)
			{
				if (TryTranslateExact(value, out string translated) && !string.Equals(translated, value, StringComparison.Ordinal))
				{
					return SanitizeTranslatedText(translated);
				}
				if (TryTranslateRegex(value, out string translated2) && !string.Equals(translated2, value, StringComparison.Ordinal))
				{
					return SanitizeTranslatedText(translated2);
				}
				if (TryTranslateKnownPlanetName(value, out string translated3))
				{
					return translated3;
				}
				string text = TranslateKnownValueCore(NormalizeLoose(value));
				if (text.Length != 0)
				{
					return text;
				}
				return value;
			}

			private static bool TranslateLineFast(string source, out string translated)
			{
				translated = source;
				int num = source.Length - source.TrimStart().Length;
				string leading = ((num > 0) ? source.Substring(0, num) : string.Empty);
				string trimmed = StripRichTextTagsCheap(source).Trim();
				if (trimmed.Length == 0)
				{
					return false;
				}
				string rewritten = source;
				bool result = TryRewrite("CELESTIAL BODY:", "天体:", translateValue: false) || TryRewrite("CELESTIAL_BODY:", "天体:", translateValue: false) || TryRewrite("天体:", "天体:", translateValue: false) || TryRewrite("天体:", "天体:", translateValue: false) || TryRewrite("POPULATION:", "人口:", translateValue: true) || TryRewrite("人口:", "人口:", translateValue: true) || TryRewrite("人口:", "人口:", translateValue: true) || TryRewrite("CONDITIONS:", "环境:", translateValue: true) || TryRewrite("环境:", "环境:", translateValue: true) || TryRewrite("环境:", "环境:", translateValue: true) || TryRewrite("FAUNA:", "生态:", translateValue: true) || TryRewrite("生态:", "生态:", translateValue: true) || TryRewrite("生态:", "生态:", translateValue: true);
				translated = rewritten;
				return result;
				bool TryRewrite(string label, string localizedLabel, bool translateValue)
				{
					if (!trimmed.StartsWith(label, StringComparison.OrdinalIgnoreCase))
					{
						return false;
					}
					string text = trimmed;
					int length = label.Length;
					string text2 = text.Substring(length, text.Length - length).Trim();
					rewritten = ((text2.Length == 0) ? (leading + localizedLabel) : (leading + localizedLabel + " " + (translateValue ? TranslateKnownValueFast(text2) : text2)));
					return true;
				}
			}

			private static string TranslateKnownValueFast(string value)
			{
				if (TryTranslateExact(value, out string translated) && !string.Equals(translated, value, StringComparison.Ordinal))
				{
					return SanitizeTranslatedText(translated);
				}
				string text = TranslateKnownValueCore(NormalizeLoose(value));
				if (text.Length != 0)
				{
					return text;
				}
				return value;
			}

			private static string TranslateKnownValueCore(string normalized)
			{
				return normalized switch
				{
					"None" => "无", 
					"Unknown" => "未知", 
					"Abandoned" => "废弃", 
					"Arid. Thick haze, worsened by industrial artifacts." => "干旱。浓雾因工业废弃物而加重。", 
					"Arid. Low habitability, worsened by industrial artifacts." => "干旱。宜居性低,并因工业废弃物而加重。", 
					"Waning forests. Abandoned facilities littered across the landscape." => "衰败森林,废弃设施遍布地表。", 
					"Rumored active machinery left behind." => "传闻有活跃机械遗留。", 
					"Dominated by a few species." => "由少数物种主导。", 
					"Jagged and weathered terrain." => "崎岖且风化的地形。", 
					"Ecosystem supports territorial behaviour." => "生态系统支持领地行为。", 
					"Ecosystem supports territorial behavior." => "生态系统支持领地行为。", 
					_ => string.Empty, 
				};
			}
		}

		internal static class TerminalDynamicTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				string text = source.Trim();
				bool flag = text.StartsWith("Ordered ", StringComparison.OrdinalIgnoreCase) && (text.IndexOf("new balance", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("新余额", StringComparison.Ordinal) >= 0 || text.IndexOf("新餘額", StringComparison.Ordinal) >= 0);
				if (!(text.StartsWith("You have requested to order ", StringComparison.OrdinalIgnoreCase) || flag) && !text.StartsWith("The Company is buying", StringComparison.OrdinalIgnoreCase) && !text.Equals("Cancelled order.", StringComparison.OrdinalIgnoreCase))
				{
					return text.Equals("You have cancelled the order.", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}

			public static bool Translate(DynamicTextDomain domain, string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				if (!TranslateOrderRequest(source, out translated) && !TranslateOrderedItemConfirmation(source, out translated) && !TranslateTerminalStatus(source, out translated) && !TranslateCompanyBuyingStatus(source, out translated))
				{
					return TryTranslateMapScreenDescription(source, out translated);
				}
				return true;
			}

			public static bool TranslateTerminalStatus(string source, out string translated)
			{
				translated = source;
				string text = source.Trim();
				if (text.Equals("Cancelled order.", StringComparison.OrdinalIgnoreCase))
				{
					translated = "已取消订单。";
					return true;
				}
				if (text.Equals("You have cancelled the order.", StringComparison.OrdinalIgnoreCase))
				{
					translated = "你已取消订单。";
					return true;
				}
				return false;
			}

			public static bool TranslateCompanyBuyingStatus(string source, out string translated)
			{
				translated = source;
				string source2 = source.Replace("\r\n", "\n").Trim();
				Match match = SafeRegexMatch(source2, "^The Company is buying at (?<percent>.+?)\\.\\s*Do you want to route the autopilot to the Company building\\?\\s*Please CONFIRM or DENY\\.?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match.Success)
				{
					translated = "公司当前收购比例为 " + match.Groups["percent"].Value.Trim() + "。是否将自动驾驶航线设为公司大楼?\n请输入 CONFIRM 或 DENY。";
					return true;
				}
				Match match2 = SafeRegexMatch(source2, "^The Company is buying(?: your goods)? at (?<percent>.+?)\\.$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
				if (!match2.Success)
				{
					return false;
				}
				translated = "公司当前收购比例为 " + match2.Groups["percent"].Value.Trim() + "。";
				return true;
			}

			public static bool TranslateOrderRequest(string source, out string translated)
			{
				translated = source;
				string text = source.Replace("\r\n", "\n").Trim();
				Match match = SafeRegexMatch(text, "^You have requested to order (?<item>.+?)\\.\\s*(?<warranty>You have a free warranty!\\s*)?(?:(?:Total cost(?: of items?)?|商品总价)\\s*:?\\s*(?<cost>.+?)\\.)\\s*Please CONFIRM or DENY\\.?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match.Success)
				{
					string text2 = BuildTerminalLocalizedItemName(match.Groups["item"].Value);
					string text3 = (match.Groups["warranty"].Success ? "\n你享有免费保修!" : string.Empty);
					string text4 = NormalizeTransactionCost(match.Groups["cost"].Value);
					translated = "\n\n你已请求订购 " + text2 + "。" + text3 + "\n商品总价:" + text4 + "。\n\n请输入 CONFIRM 或 DENY。\n\n";
					return true;
				}
				Match match2 = SafeRegexMatch(text, "^(?:\\u60a8|\\u4f60)\\s*(?:\\u5df2)?\\u8bf7\\u6c42\\u8ba2\\u8d2d\\s*(?<item>.+?)[\\u3002.]\\s*(?<warranty>\\u4f60\\u4eab\\u6709\\u514d\\u8d39\\u4fdd\\u4fee\\uff01\\s*)?(?:\\u5546\\u54c1\\u603b\\u4ef7|\\u7269\\u54c1\\u603b\\u4ef7|\\u5355\\u4ef6\\u603b\\u4ef7)\\s*[:\\uff1a.\\s]*(?<cost>\\$?\\s*[+-]?\\d+(?:\\.\\d+)?)(?:[\\s::.。]*)\\s*\\u8bf7\\u8f93\\u5165\\s+CONFIRM\\s+\\u6216\\s+DENY[\\u3002.]?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match2.Success)
				{
					string text5 = BuildTerminalLocalizedItemName(match2.Groups["item"].Value);
					string text6 = (match2.Groups["warranty"].Success ? "\n你享有免费保修!" : string.Empty);
					string text7 = NormalizeTransactionCost(match2.Groups["cost"].Value);
					translated = "\n\n你已请求订购 " + text5 + "。" + text6 + "\n商品总价:" + text7 + "。\n\n请输入 CONFIRM 或 DENY。\n\n";
					return true;
				}
				Match match3 = SafeRegexMatch(text, "^You have a free warranty!\\s+(?:(?:Total cost(?: of items?)?|商品总价)\\s*:?\\s*(?<cost>.+?)\\.)\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match3.Success)
				{
					translated = "你享有免费保修!\n商品总价:" + NormalizeTransactionCost(match3.Groups["cost"].Value) + "。";
					return true;
				}
				Match match4 = SafeRegexMatch(text, "^You have requested to order (?<item>.+?)\\.\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match4.Success)
				{
					translated = "你已请求订购 " + BuildTerminalLocalizedItemName(match4.Groups["item"].Value) + "。";
					return true;
				}
				Match match5 = SafeRegexMatch(text, "^(?:您|你)已请求订购\\s+(?<item>.+?)[。.]?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match5.Success)
				{
					translated = "你已请求订购 " + BuildTerminalLocalizedItemName(match5.Groups["item"].Value) + "。";
					return true;
				}
				if (string.Equals(text, "You have a free warranty!", StringComparison.OrdinalIgnoreCase))
				{
					translated = "你享有免费保修!";
					return true;
				}
				Match match6 = SafeRegexMatch(text, "^(?:Total cost(?: of items?)?|商品总价)\\s*:?\\s*(?<cost>.+?)\\.?\\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
				if (match6.Success)
				{
					translated = "商品总价:" + NormalizeTransactionCost(match6.Groups["cost"].Value) + "。";
					return true;
				}
				if (SafeRegexMatch(text, "^Please\\s+CONFIRM\\s+or\\s+DENY\\.?$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant).Success)
				{
					translated = "请输入 CONFIRM 或 DENY。";
					return true;
				}
				return false;
			}

			public static string NormalizeTransactionCost(string cost)
			{
				string text = SafeRegexReplace(cost ?? string.Empty, "\\s+", " ", RegexOptions.CultureInvariant).Trim();
				Match match = SafeRegexMatch(text, "(?<cost>\\$?\\s*[+-]?\\d+(?:\\.\\d+)?)", RegexOptions.CultureInvariant);
				if (!match.Success)
				{
					return text.Trim(' ', '.', ':', ':', '。');
				}
				return SafeRegexReplace(match.Groups["cost"].Value, "\\s+", string.Empty, RegexOptions.CultureInvariant);
			}

			public static bool TranslateOrderedItemConfirmation(string source, out string translated)
			{
				translated = source;
				if (!TrySafeRegexMatch(OrderedTerminalItemConfirmationRegex, source, out Match match) || !match.Success)
				{
					return false;
				}
				string text = BuildTerminalLocalizedItemName(match.Groups["item"].Value.Trim());
				string text2 = match.Groups["credits"].Value.Trim();
				string text3 = match.Groups["rest"].Value.Trim();
				if (text3.Length == 0)
				{
					translated = "已订购 " + text + "。\n你的新余额为 " + text2 + "。";
					return true;
				}
				string text4 = TranslateOrderDetail(text3);
				translated = "已订购 " + text + "。\n你的新余额为 " + text2 + "。\n\n" + text4;
				return true;
			}

			public static string StandardizeCruiserWarrantyText(string source)
			{
				if (string.IsNullOrEmpty(source) || (!source.Contains("warranty", StringComparison.OrdinalIgnoreCase) && !source.Contains("Cruiser", StringComparison.OrdinalIgnoreCase)))
				{
					return source;
				}
				return SafeRegexReplace(TerminalCruiserWarrantyRegex, source, "公司对此产品质量非常有信心,因此提供终身保修。\n如果你的巡航车丢失或损坏,可以获得一次免费替换。\n在载具运送途中无法购买物品。");
			}

			public static string TranslateOrderDetail(string source)
			{
				if (string.IsNullOrWhiteSpace(source))
				{
					return string.Empty;
				}
				string text = SafeRegexReplace(source, "\\s+", " ").Trim();
				string text2 = StandardizeCruiserWarrantyText(text);
				if (!string.Equals(text2, text, StringComparison.Ordinal))
				{
					return SanitizeTranslatedText(text2);
				}
				return SanitizeTranslatedText(StandardizeCruiserWarrantyText(TranslateOrderDetailPhrases(TranslateTerminalOutputBody(text))));
			}

			public static string TranslateOrderDetailPhrases(string source)
			{
				string source2 = source;
				source2 = ReplaceIgnoreCase(source2, "Press [B] to rearrange objects in your ship and [V] to confirm.", "按 [B] 在飞船内整理物品,按 [V] 确认。");
				source2 = ReplaceIgnoreCase(source2, "Press [B] to rearrange fish in your ship and [V] to confirm.", "按 [B] 在飞船内整理金鱼,按 [V] 确认。");
				source2 = ReplaceIgnoreCase(source2, "Press the button to activate the teleporter. It will teleport whoever is currently being monitored on the ship's radar. You will not be able to keep any of your held items through the teleport. It takes about 10 seconds to recharge.", "按下按钮即可启动传送器。它会传送当前在飞船雷达监视中的目标。传送过程中将无法保留手持物品。冷却时间约 10 秒。");
				source2 = ReplaceIgnoreCase(source2, "Press the button and step onto the inverse teleporter while it activates.", "启动时按下按钮并踏上逆向传送器。");
				source2 = ReplaceIgnoreCase(source2, "Use the light switch to enable cozy lights.", "使用灯光开关启用温馨灯串。");
				source2 = ReplaceIgnoreCase(source2, "Use the light switch to enable the disco.", "使用灯光开关启用迪斯科球。");
				source2 = ReplaceIgnoreCase(source2, "Your electric chair can be activated by any powerful source of voltage!", "电椅可由任何强大电压源激活!");
				source2 = ReplaceIgnoreCase(source2, "Hold the cord to activate the loud horn.", "拉住绳索即可启动扬声喇叭。");
				string translated;
				return TranslateSignalTransmitterInstructions(source2, out translated) ? translated : source2;
			}

			public static bool TranslateSignalTransmitterInstructions(string source, out string translated)
			{
				translated = SafeRegexReplace(SignalTransmitterInstructionsRegex, source, "信号发射器可通过 \"transmit\" 命令激活,后接不超过 10 个字符的消息。");
				return !string.Equals(translated, source, StringComparison.Ordinal);
			}
		}

		internal static class WeightUnitTranslator
		{
			public static bool CanHandleCheap(string? source)
			{
				if (string.IsNullOrWhiteSpace(source))
				{
					return false;
				}
				string text = StripRichTextTagsCheap(source).Trim();
				if (text.Equals("lb", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				if (!text.EndsWith("lb", StringComparison.OrdinalIgnoreCase))
				{
					return false;
				}
				string text2 = text;
				return LooksLikeSimpleNumber(text2.Substring(0, text2.Length - 2).Trim());
			}

			public static bool Translate(string? source, out string translated)
			{
				translated = source ?? string.Empty;
				if (string.IsNullOrEmpty(source) || !CanHandleCheap(source))
				{
					return false;
				}
				translated = Normalize(source);
				return !string.Equals(translated, source, StringComparison.Ordinal);
			}

			public static string Normalize(string? source)
			{
				if (string.IsNullOrEmpty(source))
				{
					return source ?? string.Empty;
				}
				StringBuilder stringBuilder = null;
				for (int i = 0; i < source.Length - 1; i++)
				{
					if ((source[i] != 'l' && source[i] != 'L') || (source[i + 1] != 'b' && source[i + 1] != 'B') || HasAsciiLetterBefore(source, i) || HasAsciiLetterAfter(source, i + 1))
					{
						stringBuilder?.Append(source[i]);
						continue;
					}
					if (stringBuilder == null)
					{
						stringBuilder = new StringBuilder(source.Length);
					}
					if (stringBuilder.Length == 0 && i > 0)
					{
						stringBuilder.Append(source, 0, i);
					}
					stringBuilder.Append('磅');
					i++;
				}
				if (stringBuilder == null)
				{
					return source;
				}
				char c;
				if (source.Length > 0)
				{
					c = source[source.Length - 1];
					if (source.Length >= 2)
					{
						if (source[source.Length - 2] != 'l')
						{
							if (source[source.Length - 2] != 'L')
							{
								goto IL_010e;
							}
						}
						if (c == 'b' || c == 'B')
						{
							goto IL_0116;
						}
					}
					goto IL_010e;
				}
				goto IL_0116;
				IL_010e:
				stringBuilder.Append(c);
				goto IL_0116;
				IL_0116:
				return stringBuilder.ToString();
			}

			private static bool LooksLikeSimpleNumber(string value)
			{
				if (string.IsNullOrWhiteSpace(value))
				{
					return false;
				}
				bool result = false;
				bool flag = false;
				for (int i = 0; i < value.Length; i++)
				{
					char c = value[i];
					if ((c == '+' || c == '-') && i == 0)
					{
						continue;
					}
					if (c == '.' && !flag)
					{
						flag = true;
						continue;
					}
					if (!char.IsDigit(c))
					{
						return false;
					}
					result = true;
				}
				return result;
			}
		}

		private enum KnownSlowCfgRegexKind
		{
			PurchasedItemsOnRoute,
			PurchasedVehicleOnRoute,
			ColonAll,
			ColonNone
		}

		private sealed class RegexEntry
		{
			public Regex? Regex { get; }

			public KnownSlowCfgRegexKind? Kind { get; }

			public string Pattern { get; }

			public string Replacement { get; }

			public bool Disabled { get; private set; }

			public RegexEntry(string pattern, Regex regex, string replacement)
			{
				Regex = regex;
				Kind = null;
				Pattern = pattern;
				Replacement = replacement;
			}

			public RegexEntry(string pattern, KnownSlowCfgRegexKind kind, string replacement)
			{
				Regex = null;
				Kind = kind;
				Pattern = pattern;
				Replacement = replacement;
			}

			public void DisableAfterTimeout()
			{
				Disabled = true;
			}
		}

		[CompilerGenerated]
		private sealed class <ResolveCfgDirectories>d__182 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

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

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

			[DebuggerHidden]
			public <ResolveCfgDirectories>d__182(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = Path.Combine(Paths.ConfigPath, "translations", "zh-CN");
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = Path.Combine(Paths.ConfigPath, "translations", "zh-Hans");
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					return false;
				}
			}

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

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

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <ResolveCfgDirectories>d__182(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <ResolveJsonPaths>d__180 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private string pluginDir;

			public string <>3__pluginDir;

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

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

			[DebuggerHidden]
			public <ResolveJsonPaths>d__180(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "V81TestChn", "translations", "zh-CN.json");
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "translations", "zh-CN.json");
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					return false;
				}
			}

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

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

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				<ResolveJsonPaths>d__180 <ResolveJsonPaths>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ResolveJsonPaths>d__ = this;
				}
				else
				{
					<ResolveJsonPaths>d__ = new <ResolveJsonPaths>d__180(0);
				}
				<ResolveJsonPaths>d__.pluginDir = <>3__pluginDir;
				return <ResolveJsonPaths>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <ResolvePluginCfgDirectories>d__181 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private string pluginDir;

			public string <>3__pluginDir;

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

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

			[DebuggerHidden]
			public <ResolvePluginCfgDirectories>d__181(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "V81TestChn", "translations-cfg", "zh-CN");
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "V81TestChn", "translations-cfg", "zh-Hans");
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = Path.Combine(pluginDir, "tr