Decompiled source of MixedCaseMapMarkers v2.0.0

plugins\MixedCaseMapMarkers\MixedCaseMapMarkers.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MixedCaseMapMarkers.Fonts;
using TMPro;
using UnityEngine;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[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("LexPy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("MixedCaseMapMarkers")]
[assembly: AssemblyTitle("MixedCaseMapMarkers")]
[assembly: AssemblyVersion("2.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MixedCaseMapMarkers
{
	[BepInPlugin("com.lexpy.mixedcasemapmarkers", "MixedCaseMapMarkers", "2.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.lexpy.mixedcasemapmarkers";

		public const string PluginName = "MixedCaseMapMarkers";

		public const string PluginVersion = "2.0.0";

		private Harmony? _harmony;

		internal static ManualLogSource? Log { get; private set; }

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("com.lexpy.mixedcasemapmarkers");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"MixedCaseMapMarkers 2.0.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			MixedCaseFont.Dispose();
			_harmony = null;
			Log = null;
		}
	}
}
namespace MixedCaseMapMarkers.Patches
{
	internal static class MapMarkerController
	{
		private static readonly FieldInfo? NameInputField = AccessTools.Field(typeof(Minimap), "m_nameInput");

		private static readonly FieldInfo? PinNamePrefabField = AccessTools.Field(typeof(Minimap), "m_pinNamePrefab");

		private static TMP_FontAsset? _observedMarkerFont;

		private static FontStyles _observedMarkerStyle;

		private static FontWeight _observedMarkerWeight = (FontWeight)400;

		private static bool _observedMarkerStyleCaptured;

		private static bool _inputLogged;

		private static bool _inputRoutingLogged;

		private static bool _markerLogged;

		private static bool _markerCaseLogged;

		private static bool _markerRenderLogged;

		private static bool _missingInputLogged;

		private static bool _missingMarkerFontLogged;

		private static bool _transientSkipLogged;

		public static int CaptureChildCount(RectTransform? root)
		{
			if (root == null)
			{
				return -1;
			}
			return ((Transform)root).childCount;
		}

		public static void ConfigureInput(Minimap minimap)
		{
			if ((Object)(object)minimap == (Object)null)
			{
				return;
			}
			GameObject root = GetRoot(NameInputField?.GetValue(minimap));
			if ((Object)(object)root == (Object)null)
			{
				LogOnce(ref _missingInputLogged, "Valheim's m_nameInput object could not be found.", warning: true);
				return;
			}
			TMP_FontAsset val = _observedMarkerFont ?? FindFont(PinNamePrefabField?.GetValue(minimap));
			if ((Object)(object)val == (Object)null)
			{
				LogOnce(ref _missingMarkerFontLogged, "Valheim's map-marker font could not be found.", warning: true);
				return;
			}
			TMP_InputField[] componentsInChildren = root.GetComponentsInChildren<TMP_InputField>(true);
			foreach (TMP_InputField val2 in componentsInChildren)
			{
				RemoveInputCapitalization(val2);
				if ((Object)(object)val2.textComponent != (Object)null && MixedCaseFont.Apply(val2.textComponent, val))
				{
					ApplyObservedMarkerTypefaceStyle(val2.textComponent);
					val2.fontAsset = val2.textComponent.font;
					((Graphic)val2.textComponent).SetAllDirty();
					val2.textComponent.ForceMeshUpdate(true, true);
					LogInputRoutingOnce(val2.textComponent);
				}
				Graphic placeholder = val2.placeholder;
				TMP_Text val3 = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
				if (val3 != null && MixedCaseFont.Apply(val3, val))
				{
					ApplyObservedMarkerTypefaceStyle(val3);
					((Graphic)val3).SetAllDirty();
				}
			}
			if (!_inputLogged)
			{
				string text = (_observedMarkerStyleCaptured ? (", copied marker style=" + ((object)Unsafe.As<FontStyles, FontStyles>(ref _observedMarkerStyle)/*cast due to .constrained prefix*/).ToString() + ", weight=" + ((object)Unsafe.As<FontWeight, FontWeight>(ref _observedMarkerWeight)/*cast due to .constrained prefix*/).ToString()) : ", marker style not yet captured");
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("Configured the map-marker input field for mixed case using marker font '" + ((Object)val).name + "'" + text + "."));
				}
				_inputLogged = true;
			}
		}

		public static void ConfigureCreatedMapLabel(object? pinData, RectTransform? createRoot, int previousChildCount)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			TMP_Text val = TryGetPinNameText(pinData);
			if (IsTransientSystemMapText(pinData, val))
			{
				if (!_transientSkipLogged)
				{
					ManualLogSource? log = Plugin.Log;
					if (log != null)
					{
						log.LogDebug((object)"Leaving transient map PING / I HAVE ARRIVED text completely untouched.");
					}
					_transientSkipLogged = true;
				}
				return;
			}
			if ((Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null)
			{
				if ((Object)(object)_observedMarkerFont == (Object)null)
				{
					_observedMarkerFont = val.font;
					ManualLogSource? log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogDebug((object)("Captured the actual map-label font: '" + ((Object)_observedMarkerFont).name + "'."));
					}
				}
				if (!_observedMarkerStyleCaptured)
				{
					_observedMarkerStyle = StripCaseStyles(val.fontStyle);
					_observedMarkerWeight = val.fontWeight;
					_observedMarkerStyleCaptured = true;
					ManualLogSource? log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogDebug((object)("Captured the actual map-label typeface style: fontStyle=" + ((object)Unsafe.As<FontStyles, FontStyles>(ref _observedMarkerStyle)/*cast due to .constrained prefix*/).ToString() + ", fontWeight=" + ((object)Unsafe.As<FontWeight, FontWeight>(ref _observedMarkerWeight)/*cast due to .constrained prefix*/).ToString() + "."));
					}
				}
			}
			bool flag = (Object)(object)val != (Object)null && ContainsCustomLowercase(val.text);
			if (!_markerCaseLogged && (Object)(object)val != (Object)null)
			{
				ManualLogSource? log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogDebug((object)("Map-label source text contains lowercase characters before font replacement: " + flag + "."));
				}
				_markerCaseLogged = true;
			}
			GameObject val2 = TryGetPinNameGameObject(pinData);
			if ((Object)(object)val2 == (Object)null && (Object)(object)createRoot != (Object)null && previousChildCount >= 0)
			{
				int num = Mathf.Clamp(previousChildCount, 0, ((Transform)createRoot).childCount);
				if (num < ((Transform)createRoot).childCount)
				{
					val2 = ((Component)((Transform)createRoot).GetChild(num)).gameObject;
				}
			}
			int num2 = 0;
			if ((Object)(object)val2 != (Object)null)
			{
				TMP_Text[] componentsInChildren = val2.GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val3 in componentsInChildren)
				{
					if (!((Object)(object)val3.font == (Object)null) && ContainsCustomLowercase(val3.text))
					{
						TMP_FontAsset originalFont = _observedMarkerFont ?? val3.font;
						if (MixedCaseFont.Apply(val3, originalFont))
						{
							AttachGuard(val3, originalFont);
							LogRenderedLowercaseOnce(val3);
							num2++;
						}
					}
				}
			}
			if (num2 == 0 && (Object)(object)val != (Object)null && (Object)(object)val.font != (Object)null && ContainsCustomLowercase(val.text))
			{
				TMP_FontAsset originalFont2 = _observedMarkerFont ?? val.font;
				if (MixedCaseFont.Apply(val, originalFont2))
				{
					AttachGuard(val, originalFont2);
					LogRenderedLowercaseOnce(val);
					num2 = 1;
				}
			}
			if (num2 > 0 && !_markerLogged)
			{
				ManualLogSource? log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogDebug((object)("Applied the mixed-case font to " + num2 + " lowercase-containing TMP component(s) in the exact map-label object."));
				}
				_markerLogged = true;
			}
		}

		internal static void LogRenderedLowercaseOnce(TMP_Text text)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			if (_markerRenderLogged || (Object)(object)text == (Object)null)
			{
				return;
			}
			text.ForceMeshUpdate(true, true);
			TMP_TextInfo textInfo = text.textInfo;
			TMP_CharacterInfo? character = null;
			TMP_CharacterInfo? character2 = null;
			for (int i = 0; i < textInfo.characterCount; i++)
			{
				TMP_CharacterInfo val = textInfo.characterInfo[i];
				if (!character.HasValue && ((val.character >= 'A' && val.character <= 'Z') || (val.character >= '0' && val.character <= '9')))
				{
					character = val;
				}
				if (!character2.HasValue && IsCustomLowercase(val.character))
				{
					character2 = val;
				}
				if (character.HasValue && character2.HasValue)
				{
					break;
				}
			}
			if (character2.HasValue)
			{
				string text2 = (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name : "<null>");
				string text3 = (((Object)(object)text.fontSharedMaterial != (Object)null) ? ((Object)text.fontSharedMaterial).name : "<null>");
				string text4 = DescribeRenderedCharacter(textInfo, character);
				string text5 = DescribeRenderedCharacter(textInfo, character2);
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("Rendered mixed-case check: upper/digit=" + text4 + "; lowercase=" + text5 + "; assignedFont='" + text2 + "', fontStyle=" + ((object)text.fontStyle/*cast due to .constrained prefix*/).ToString() + ", fontWeight=" + ((object)text.fontWeight/*cast due to .constrained prefix*/).ToString() + ", sharedMaterial='" + text3 + "'."));
				}
				_markerRenderLogged = true;
			}
		}

		private static string DescribeRenderedCharacter(TMP_TextInfo info, TMP_CharacterInfo? character)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!character.HasValue)
			{
				return "<none>";
			}
			TMP_CharacterInfo value = character.Value;
			string text = (((Object)(object)value.fontAsset != (Object)null) ? ((Object)value.fontAsset).name : "<null>");
			string text2 = "<none>";
			int materialReferenceIndex = value.materialReferenceIndex;
			if (info.meshInfo != null && materialReferenceIndex >= 0 && materialReferenceIndex < info.meshInfo.Length && (Object)(object)info.meshInfo[materialReferenceIndex].material != (Object)null)
			{
				text2 = ((Object)info.meshInfo[materialReferenceIndex].material).name;
			}
			return "'" + value.character + "' fontAsset='" + text + "', materialIndex=" + materialReferenceIndex + ", material='" + text2 + "'";
		}

		private unsafe static void LogInputRoutingOnce(TMP_Text text)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!_inputRoutingLogged && !((Object)(object)text == (Object)null) && !((Object)(object)text.font == (Object)null))
			{
				FontStyles val = StripCaseStyles(text.fontStyle);
				FontWeight fontWeight = text.fontWeight;
				bool flag = default(bool);
				TMP_Character characterFromFontAsset = TMP_FontAssetUtilities.GetCharacterFromFontAsset(97u, text.font, true, val, fontWeight, ref flag);
				bool flag2 = default(bool);
				TMP_Character characterFromFontAsset2 = TMP_FontAssetUtilities.GetCharacterFromFontAsset(65u, text.font, true, val, fontWeight, ref flag2);
				string text2 = (((Object)(object)((characterFromFontAsset != null) ? ((TMP_TextElement)characterFromFontAsset).textAsset : null) != (Object)null) ? ((Object)((TMP_TextElement)characterFromFontAsset).textAsset).name : "<none>");
				string text3 = (((Object)(object)((characterFromFontAsset2 != null) ? ((TMP_TextElement)characterFromFontAsset2).textAsset : null) != (Object)null) ? ((Object)((TMP_TextElement)characterFromFontAsset2).textAsset).name : "<none>");
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("Input routing check: fontStyle=" + ((object)(*(FontStyles*)(&val))/*cast due to .constrained prefix*/).ToString() + ", fontWeight=" + ((object)(*(FontWeight*)(&fontWeight))/*cast due to .constrained prefix*/).ToString() + "; 'A' -> '" + text3 + "'; 'a' -> '" + text2 + "'."));
				}
				_inputRoutingLogged = true;
			}
		}

		private static void ApplyObservedMarkerTypefaceStyle(TMP_Text text)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (_observedMarkerStyleCaptured && !((Object)(object)text == (Object)null))
			{
				FontStyles val = (FontStyles)(text.fontStyle & -60);
				FontStyles val2 = (FontStyles)(_observedMarkerStyle & 3);
				text.fontStyle = (FontStyles)(val | val2);
				text.fontWeight = _observedMarkerWeight;
			}
		}

		private static FontStyles StripCaseStyles(FontStyles style)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return (FontStyles)(style & -57);
		}

		private static void AttachGuard(TMP_Text text, TMP_FontAsset originalFont)
		{
			MarkerFontGuard markerFontGuard = ((Component)text).gameObject.GetComponent<MarkerFontGuard>();
			if ((Object)(object)markerFontGuard == (Object)null)
			{
				markerFontGuard = ((Component)text).gameObject.AddComponent<MarkerFontGuard>();
			}
			markerFontGuard.Initialize(text, originalFont);
		}

		private static void RemoveInputCapitalization(TMP_InputField inputField)
		{
			inputField.contentType = (ContentType)0;
			inputField.characterValidation = (CharacterValidation)0;
			inputField.inputValidator = null;
			inputField.onValidateInput = null;
		}

		private static bool IsTransientSystemMapText(object? pinData, TMP_Text? text)
		{
			if (pinData != null)
			{
				string text2 = (AccessTools.Field(pinData.GetType(), "m_type")?.GetValue(pinData))?.ToString();
				if (!string.IsNullOrEmpty(text2) && text2.IndexOf("Ping", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			string text3 = ((text != null) ? text.text : null);
			if (string.IsNullOrEmpty(text3))
			{
				return false;
			}
			if (!text3.Equals("PING", StringComparison.OrdinalIgnoreCase) && !text3.EndsWith(": PING", StringComparison.OrdinalIgnoreCase) && !text3.Equals("I HAVE ARRIVED!", StringComparison.OrdinalIgnoreCase))
			{
				return text3.EndsWith(": I HAVE ARRIVED!", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static object? TryGetNamePinData(object? pinData)
		{
			if (pinData == null)
			{
				return null;
			}
			return AccessTools.Field(pinData.GetType(), "m_NamePinData")?.GetValue(pinData);
		}

		private static TMP_Text? TryGetPinNameText(object? pinData)
		{
			object obj = TryGetNamePinData(pinData);
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			object? obj2 = AccessTools.Property(type, "PinNameText")?.GetValue(obj);
			TMP_Text val = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
			if (val != null)
			{
				return val;
			}
			object? obj3 = AccessTools.Field(type, "<PinNameText>k__BackingField")?.GetValue(obj);
			return (TMP_Text?)((obj3 is TMP_Text) ? obj3 : null);
		}

		private static GameObject? TryGetPinNameGameObject(object? pinData)
		{
			object obj = TryGetNamePinData(pinData);
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			object? obj2 = AccessTools.Property(type, "PinNameGameObject")?.GetValue(obj);
			GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
			if (val != null)
			{
				return val;
			}
			object? obj3 = AccessTools.Field(type, "<PinNameGameObject>k__BackingField")?.GetValue(obj);
			return (GameObject?)((obj3 is GameObject) ? obj3 : null);
		}

		private static TMP_FontAsset? FindFont(object? value)
		{
			TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
			if (val != null)
			{
				return val.font;
			}
			TMP_InputField val2 = (TMP_InputField)((value is TMP_InputField) ? value : null);
			if (val2 != null)
			{
				TMP_Text textComponent = val2.textComponent;
				object obj = ((textComponent != null) ? textComponent.font : null);
				if (obj == null)
				{
					Graphic placeholder = val2.placeholder;
					Graphic obj2 = ((placeholder is TMP_Text) ? placeholder : null);
					if (obj2 == null)
					{
						return null;
					}
					obj = ((TMP_Text)obj2).font;
				}
				return (TMP_FontAsset?)obj;
			}
			GameObject root = GetRoot(value);
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			TMP_Text[] componentsInChildren = root.GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i].font != (Object)null && ((Object)componentsInChildren[i].font).name.IndexOf("Valheim-Norse", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return componentsInChildren[i].font;
				}
			}
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				if ((Object)(object)componentsInChildren[j].font != (Object)null)
				{
					return componentsInChildren[j].font;
				}
			}
			return null;
		}

		private static GameObject? GetRoot(object? value)
		{
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (val == null)
			{
				Component val2 = (Component)((value is Component) ? value : null);
				if (val2 != null)
				{
					return val2.gameObject;
				}
				return null;
			}
			return val;
		}

		private static bool ContainsCustomLowercase(string? value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			for (int i = 0; i < value.Length; i++)
			{
				if (IsCustomLowercase(value[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsCustomLowercase(char c)
		{
			if ((c < 'a' || c > 'z') && c != 'ä' && c != 'ö' && c != 'ü' && c != 'ñ')
			{
				return c == 'ç';
			}
			return true;
		}

		private static void LogOnce(ref bool flag, string message, bool warning)
		{
			if (flag)
			{
				return;
			}
			if (warning)
			{
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)message);
				}
			}
			else
			{
				ManualLogSource? log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)message);
				}
			}
			flag = true;
		}
	}
	internal sealed class MarkerFontGuard : MonoBehaviour
	{
		private TMP_Text? _text;

		private TMP_FontAsset? _originalFont;

		private bool _overwriteLogged;

		public void Initialize(TMP_Text text, TMP_FontAsset originalFont)
		{
			_text = text;
			_originalFont = originalFont;
		}

		private void LateUpdate()
		{
			if ((Object)(object)_text == (Object)null || (Object)(object)_originalFont == (Object)null || MixedCaseFont.IsApplied(_text))
			{
				return;
			}
			if (!_overwriteLogged)
			{
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)"Valheim changed the map-label font/style after creation; reapplying the mixed-case font on the exact label component.");
				}
				_overwriteLogged = true;
			}
			if (MixedCaseFont.Apply(_text, _originalFont))
			{
				MapMarkerController.LogRenderedLowercaseOnce(_text);
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "ShowPinNameInput")]
	internal static class ShowPinNameInputPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Minimap __instance)
		{
			MapMarkerController.ConfigureInput(__instance);
		}
	}
	[HarmonyPatch(typeof(Minimap), "CreateMapNamePin")]
	internal static class CreateMapNamePinPatch
	{
		[HarmonyPrefix]
		private static void Prefix(RectTransform __1, out int __state)
		{
			__state = MapMarkerController.CaptureChildCount(__1);
		}

		[HarmonyPostfix]
		private static void Postfix(object __0, RectTransform __1, int __state)
		{
			MapMarkerController.ConfigureCreatedMapLabel(__0, __1, __state);
		}
	}
}
namespace MixedCaseMapMarkers.Fonts
{
	internal static class MixedCaseFont
	{
		private readonly struct FontStyleKey : IEquatable<FontStyleKey>
		{
			private readonly int _fontId;

			private readonly int _styleId;

			public FontStyleKey(int fontId, int styleId)
			{
				_fontId = fontId;
				_styleId = styleId;
			}

			public bool Equals(FontStyleKey other)
			{
				if (_fontId == other._fontId)
				{
					return _styleId == other._styleId;
				}
				return false;
			}

			public override bool Equals(object? obj)
			{
				if (obj is FontStyleKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (_fontId * 397) ^ _styleId;
			}
		}

		private sealed class CompositeFont
		{
			public TMP_FontAsset PrimaryFont { get; }

			public TMP_FontAsset LowercaseFont { get; }

			public Material? StyledPrimaryMaterial { get; }

			public IReadOnlyList<TMP_FontAsset> AlternativeTypefaces { get; }

			public CompositeFont(TMP_FontAsset primaryFont, TMP_FontAsset lowercaseFont, Material? styledPrimaryMaterial, IReadOnlyList<TMP_FontAsset> alternativeTypefaces)
			{
				PrimaryFont = primaryFont;
				LowercaseFont = lowercaseFont;
				StyledPrimaryMaterial = styledPrimaryMaterial;
				AlternativeTypefaces = alternativeTypefaces;
			}
		}

		private static readonly Dictionary<FontStyleKey, CompositeFont> CompositeFonts = new Dictionary<FontStyleKey, CompositeFont>();

		private static bool _validationLogged;

		public static bool Apply(TMP_Text text, TMP_FontAsset originalFont)
		{
			if ((Object)(object)text == (Object)null || (Object)(object)originalFont == (Object)null)
			{
				return false;
			}
			object obj = text.fontSharedMaterial;
			if (obj == null)
			{
				TMP_FontAsset font = text.font;
				obj = ((font != null) ? ((TMP_Asset)font).material : null) ?? ((TMP_Asset)originalFont).material;
			}
			Material styleSource = (Material)obj;
			CompositeFont orCreateComposite = GetOrCreateComposite(originalFont, styleSource);
			if (orCreateComposite == null)
			{
				return false;
			}
			RemoveCaseStyle(text);
			text.font = orCreateComposite.PrimaryFont;
			Material primaryMaterial = GetPrimaryMaterial(orCreateComposite, styleSource);
			if ((Object)(object)primaryMaterial != (Object)null)
			{
				text.fontSharedMaterial = primaryMaterial;
			}
			((Graphic)text).SetAllDirty();
			text.ForceMeshUpdate(true, true);
			return true;
		}

		public static bool IsApplied(TMP_Text text)
		{
			if ((Object)(object)text != (Object)null && (Object)(object)text.font != (Object)null && ((Object)text.font).name.IndexOf("MixedCaseMapMarkers Primary", StringComparison.Ordinal) >= 0)
			{
				return !HasCaseStyle(text);
			}
			return false;
		}

		public static void Dispose()
		{
			CompositeFonts.Clear();
			RuntimeLowercaseFont.Dispose();
			_validationLogged = false;
		}

		private static CompositeFont? GetOrCreateComposite(TMP_FontAsset originalFont, Material? styleSource)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			int styleId = (((Object)(object)styleSource != (Object)null) ? ((Object)styleSource).GetInstanceID() : 0);
			FontStyleKey key = new FontStyleKey(((Object)originalFont).GetInstanceID(), styleId);
			if (CompositeFonts.TryGetValue(key, out CompositeFont value))
			{
				return value;
			}
			TMP_FontAsset val = RuntimeLowercaseFont.Get();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			originalFont.ReadFontAssetDefinition();
			TMP_FontAsset val2 = Object.Instantiate<TMP_FontAsset>(originalFont);
			((Object)val2).name = ((Object)originalFont).name + " (MixedCaseMapMarkers Primary)";
			AtlasPopulationMode atlasPopulationMode = val2.atlasPopulationMode;
			val2.atlasPopulationMode = (AtlasPopulationMode)0;
			RemoveLowercaseMappings(val2);
			TMP_FontAsset val3 = Object.Instantiate<TMP_FontAsset>(val);
			((Object)val3).name = "MixedCaseNorseLowercase (MixedCaseMapMarkers Fallback)";
			val3.atlasPopulationMode = (AtlasPopulationMode)0;
			Material val4 = CreateMatchedStyleMaterial(((TMP_Asset)val3).material, styleSource, "MixedCaseMapMarkers-Lowercase-Material");
			if ((Object)(object)val4 != (Object)null)
			{
				((TMP_Asset)val3).material = val4;
			}
			List<TMP_FontAsset> list = CloneAndSanitizeAlternativeTypefaces(originalFont, val2);
			RouteAllWeightsToSelf(val3);
			List<TMP_FontAsset> fallbackFontAssetTable = BuildFallbackChain(val2.fallbackFontAssetTable, val3, originalFont);
			val2.fallbackFontAssetTable = fallbackFontAssetTable;
			for (int i = 0; i < list.Count; i++)
			{
				TMP_FontAsset obj = list[i];
				obj.fallbackFontAssetTable = BuildFallbackChain(obj.fallbackFontAssetTable, val3, originalFont);
				obj.ReadFontAssetDefinition();
			}
			val3.ReadFontAssetDefinition();
			Material val5 = CreateStyledAtlasMaterial(((TMP_Asset)val2).material, styleSource, "MixedCaseMapMarkers-Primary-Material");
			Object.DontDestroyOnLoad((Object)(object)val2);
			Object.DontDestroyOnLoad((Object)(object)val3);
			for (int j = 0; j < list.Count; j++)
			{
				if ((Object)(object)list[j] != (Object)null)
				{
					Object.DontDestroyOnLoad((Object)(object)list[j]);
				}
			}
			if ((Object)(object)val4 != (Object)null)
			{
				Object.DontDestroyOnLoad((Object)(object)val4);
			}
			if ((Object)(object)val5 != (Object)null)
			{
				Object.DontDestroyOnLoad((Object)(object)val5);
			}
			ValidateCompositeOnce(val2, val3, atlasPopulationMode);
			CompositeFont compositeFont = new CompositeFont(val2, val3, val5, list);
			CompositeFonts.Add(key, compositeFont);
			return compositeFont;
		}

		private static List<TMP_FontAsset> CloneAndSanitizeAlternativeTypefaces(TMP_FontAsset originalFont, TMP_FontAsset primaryFont)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			List<TMP_FontAsset> list = new List<TMP_FontAsset>();
			Dictionary<int, TMP_FontAsset> clonesBySourceId = new Dictionary<int, TMP_FontAsset>();
			TMP_FontWeightPair[] fontWeightTable = primaryFont.fontWeightTable;
			if (fontWeightTable == null)
			{
				return list;
			}
			for (int i = 0; i < fontWeightTable.Length; i++)
			{
				TMP_FontWeightPair val = fontWeightTable[i];
				val.regularTypeface = CloneAlternativeTypeface(val.regularTypeface, originalFont, primaryFont, clonesBySourceId, list);
				val.italicTypeface = CloneAlternativeTypeface(val.italicTypeface, originalFont, primaryFont, clonesBySourceId, list);
				fontWeightTable[i] = val;
			}
			return list;
		}

		private static TMP_FontAsset? CloneAlternativeTypeface(TMP_FontAsset? source, TMP_FontAsset originalFont, TMP_FontAsset primaryFont, Dictionary<int, TMP_FontAsset> clonesBySourceId, List<TMP_FontAsset> owned)
		{
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (((Object)source).GetInstanceID() == ((Object)originalFont).GetInstanceID())
			{
				return primaryFont;
			}
			int instanceID = ((Object)source).GetInstanceID();
			if (clonesBySourceId.TryGetValue(instanceID, out TMP_FontAsset value))
			{
				return value;
			}
			source.ReadFontAssetDefinition();
			TMP_FontAsset val = Object.Instantiate<TMP_FontAsset>(source);
			((Object)val).name = ((Object)source).name + " (MixedCaseMapMarkers Typeface)";
			val.atlasPopulationMode = (AtlasPopulationMode)0;
			RemoveLowercaseMappings(val);
			clonesBySourceId.Add(instanceID, val);
			owned.Add(val);
			return val;
		}

		private static List<TMP_FontAsset> BuildFallbackChain(List<TMP_FontAsset>? existing, TMP_FontAsset lowercaseFont, TMP_FontAsset originalValheimFont)
		{
			List<TMP_FontAsset> list = new List<TMP_FontAsset>();
			list.Add(lowercaseFont);
			list.Add(originalValheimFont);
			if (existing != null)
			{
				for (int i = 0; i < existing.Count; i++)
				{
					TMP_FontAsset val = existing[i];
					if (!((Object)(object)val == (Object)null) && val != lowercaseFont && val != originalValheimFont)
					{
						list.Add(val);
					}
				}
			}
			return list;
		}

		private static void RouteAllWeightsToSelf(TMP_FontAsset font)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			TMP_FontWeightPair[] fontWeightTable = font.fontWeightTable;
			if (fontWeightTable != null)
			{
				for (int i = 0; i < fontWeightTable.Length; i++)
				{
					TMP_FontWeightPair val = fontWeightTable[i];
					val.regularTypeface = font;
					val.italicTypeface = font;
					fontWeightTable[i] = val;
				}
			}
		}

		private static Material? GetPrimaryMaterial(CompositeFont composite, Material? styleSource)
		{
			if ((Object)(object)styleSource != (Object)null && MaterialUsesFontAtlas(styleSource, composite.PrimaryFont))
			{
				return styleSource;
			}
			return composite.StyledPrimaryMaterial ?? ((TMP_Asset)composite.PrimaryFont).material;
		}

		private static bool MaterialUsesFontAtlas(Material material, TMP_FontAsset font)
		{
			if ((Object)(object)material == (Object)null || (Object)(object)font == (Object)null || (Object)(object)font.atlasTexture == (Object)null)
			{
				return false;
			}
			int iD_MainTex = ShaderUtilities.ID_MainTex;
			if (!material.HasProperty(iD_MainTex))
			{
				return false;
			}
			Texture texture = material.GetTexture(iD_MainTex);
			if ((Object)(object)texture != (Object)null)
			{
				return ((Object)texture).GetInstanceID() == ((Object)font.atlasTexture).GetInstanceID();
			}
			return false;
		}

		private static void RemoveLowercaseMappings(TMP_FontAsset font)
		{
			List<TMP_Character> characterTable = font.characterTable;
			for (int num = characterTable.Count - 1; num >= 0; num--)
			{
				if (IsCustomLowercaseUnicode(((TMP_TextElement)characterTable[num]).unicode))
				{
					characterTable.RemoveAt(num);
				}
			}
			font.ReadFontAssetDefinition();
			List<uint> list = new List<uint>();
			foreach (uint key in font.characterLookupTable.Keys)
			{
				if (IsCustomLowercaseUnicode(key & 0xFFFFFF))
				{
					list.Add(key);
				}
			}
			for (int i = 0; i < list.Count; i++)
			{
				font.characterLookupTable.Remove(list[i]);
			}
		}

		private static bool IsCustomLowercaseUnicode(uint unicode)
		{
			if ((unicode < 97 || unicode > 122) && unicode != 228 && unicode != 246 && unicode != 252 && unicode != 241)
			{
				return unicode == 231;
			}
			return true;
		}

		private unsafe static void ValidateCompositeOnce(TMP_FontAsset primaryFont, TMP_FontAsset lowercaseFont, AtlasPopulationMode originalPopulationMode)
		{
			if (!_validationLogged)
			{
				bool flag = primaryFont.characterLookupTable.ContainsKey(97u);
				bool flag2 = lowercaseFont.characterLookupTable.ContainsKey(97u);
				bool flag3 = default(bool);
				TMP_Character characterFromFontAsset = TMP_FontAssetUtilities.GetCharacterFromFontAsset(97u, primaryFont, true, (FontStyles)0, (FontWeight)400, ref flag3);
				bool flag4 = default(bool);
				TMP_Character characterFromFontAsset2 = TMP_FontAssetUtilities.GetCharacterFromFontAsset(97u, primaryFont, true, (FontStyles)1, (FontWeight)700, ref flag4);
				bool flag5 = default(bool);
				TMP_Character characterFromFontAsset3 = TMP_FontAssetUtilities.GetCharacterFromFontAsset(65u, primaryFont, true, (FontStyles)1, (FontWeight)700, ref flag5);
				string text = (((Object)(object)((characterFromFontAsset != null) ? ((TMP_TextElement)characterFromFontAsset).textAsset : null) != (Object)null) ? ((Object)((TMP_TextElement)characterFromFontAsset).textAsset).name : "<none>");
				string text2 = (((Object)(object)((characterFromFontAsset2 != null) ? ((TMP_TextElement)characterFromFontAsset2).textAsset : null) != (Object)null) ? ((Object)((TMP_TextElement)characterFromFontAsset2).textAsset).name : "<none>");
				string text3 = (((Object)(object)((characterFromFontAsset3 != null) ? ((TMP_TextElement)characterFromFontAsset3).textAsset : null) != (Object)null) ? ((Object)((TMP_TextElement)characterFromFontAsset3).textAsset).name : "<none>");
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("Composite routing check: Valheim primary population mode was " + ((object)(*(AtlasPopulationMode*)(&originalPopulationMode))/*cast due to .constrained prefix*/).ToString() + "; frozen clone contains lowercase 'a': " + flag + "; custom fallback contains 'a': " + flag2 + "; regular 'a' -> '" + text + "'; bold 'a' -> '" + text2 + "'; bold 'A' -> '" + text3 + "'."));
				}
				_validationLogged = true;
			}
		}

		private static Material? CreateMatchedStyleMaterial(Material? targetFontMaterial, Material? styleSource, string name)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			if ((Object)(object)targetFontMaterial == (Object)null)
			{
				return null;
			}
			if ((Object)(object)styleSource == (Object)null)
			{
				return new Material(targetFontMaterial)
				{
					name = name
				};
			}
			try
			{
				Material fallbackMaterial = TMP_MaterialManager.GetFallbackMaterial(styleSource, targetFontMaterial);
				return new Material(fallbackMaterial)
				{
					name = name,
					shaderKeywords = fallbackMaterial.shaderKeywords
				};
			}
			catch (Exception ex)
			{
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("TMP material-preset matching failed; using the conservative style copier: " + ex.Message));
				}
				return CreateStyledAtlasMaterial(targetFontMaterial, styleSource, name);
			}
		}

		private static Material? CreateStyledAtlasMaterial(Material? atlasMaterial, Material? styleSource, string name)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			if ((Object)(object)atlasMaterial == (Object)null)
			{
				return null;
			}
			Material val = new Material(atlasMaterial)
			{
				name = name
			};
			if ((Object)(object)styleSource != (Object)null)
			{
				CopyColor(styleSource, val, "_FaceColor");
				CopyFloat(styleSource, val, "_FaceDilate");
				CopyColor(styleSource, val, "_OutlineColor");
				CopyFloat(styleSource, val, "_OutlineWidth");
				CopyFloat(styleSource, val, "_OutlineSoftness");
				CopyColor(styleSource, val, "_UnderlayColor");
				CopyFloat(styleSource, val, "_UnderlayOffsetX");
				CopyFloat(styleSource, val, "_UnderlayOffsetY");
				CopyFloat(styleSource, val, "_UnderlayDilate");
				CopyFloat(styleSource, val, "_UnderlaySoftness");
				CopyFloat(styleSource, val, "_StencilComp");
				CopyFloat(styleSource, val, "_Stencil");
				CopyFloat(styleSource, val, "_StencilOp");
				CopyFloat(styleSource, val, "_StencilWriteMask");
				CopyFloat(styleSource, val, "_StencilReadMask");
				CopyFloat(styleSource, val, "_ColorMask");
				CopyFloat(styleSource, val, "_MaskSoftnessX");
				CopyFloat(styleSource, val, "_MaskSoftnessY");
				CopyKeyword(styleSource, val, "OUTLINE_ON");
				CopyKeyword(styleSource, val, "UNDERLAY_ON");
				CopyKeyword(styleSource, val, "UNDERLAY_INNER");
				CopyKeyword(styleSource, val, "GLOW_ON");
			}
			return val;
		}

		private static void CopyColor(Material source, Material target, string propertyName)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			int num = Shader.PropertyToID(propertyName);
			if (source.HasProperty(num) && target.HasProperty(num))
			{
				target.SetColor(num, source.GetColor(num));
			}
		}

		private static void CopyFloat(Material source, Material target, string propertyName)
		{
			int num = Shader.PropertyToID(propertyName);
			if (source.HasProperty(num) && target.HasProperty(num))
			{
				target.SetFloat(num, source.GetFloat(num));
			}
		}

		private static void CopyKeyword(Material source, Material target, string keyword)
		{
			if (source.IsKeywordEnabled(keyword))
			{
				target.EnableKeyword(keyword);
			}
			else
			{
				target.DisableKeyword(keyword);
			}
		}

		private static void RemoveCaseStyle(TMP_Text text)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			text.fontStyle = (FontStyles)(text.fontStyle & -57);
			TMP_Style textStyle = text.textStyle;
			if (textStyle != null && (ContainsCaseTag(textStyle.styleOpeningDefinition) || ContainsCaseTag(textStyle.styleClosingDefinition)))
			{
				text.textStyle = TMP_Style.NormalStyle;
			}
		}

		private static bool HasCaseStyle(TMP_Text text)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if ((text.fontStyle & 0x38) != 0)
			{
				return true;
			}
			TMP_Style textStyle = text.textStyle;
			if (textStyle != null)
			{
				if (!ContainsCaseTag(textStyle.styleOpeningDefinition))
				{
					return ContainsCaseTag(textStyle.styleClosingDefinition);
				}
				return true;
			}
			return false;
		}

		private static bool ContainsCaseTag(string? definition)
		{
			if (string.IsNullOrWhiteSpace(definition))
			{
				return false;
			}
			if (definition.IndexOf("<uppercase>", StringComparison.OrdinalIgnoreCase) < 0 && definition.IndexOf("<allcaps>", StringComparison.OrdinalIgnoreCase) < 0 && definition.IndexOf("<lowercase>", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return definition.IndexOf("<smallcaps>", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}
	}
	internal static class RuntimeLowercaseFont
	{
		private const string FontFileName = "MixedCaseNorseLowercase-Regular.ttf";

		private const string CustomLowercaseCharacters = "abcdefghijklmnopqrstuvwxyzäöüñç";

		private static TMP_FontAsset? _font;

		private static bool _attempted;

		private static bool _errorLogged;

		public static TMP_FontAsset? Get()
		{
			if ((Object)(object)_font != (Object)null)
			{
				return _font;
			}
			if (_attempted)
			{
				return null;
			}
			_attempted = true;
			try
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				if (string.IsNullOrWhiteSpace(directoryName))
				{
					LogError("The plugin directory could not be determined.");
					return null;
				}
				string text = Path.Combine(directoryName, "MixedCaseNorseLowercase-Regular.ttf");
				if (!File.Exists(text))
				{
					LogError("Custom lowercase TTF was not found: " + text);
					return null;
				}
				TMP_FontAsset val = TMP_FontAsset.CreateFontAsset(text, 0, 90, 18, (GlyphRenderMode)4165, 512, 512);
				if ((Object)(object)val == (Object)null)
				{
					LogError("TextMeshPro returned null while creating the lowercase font from the TTF.");
					return null;
				}
				((Object)val).name = "MixedCaseNorseLowercase (Runtime)";
				string text2 = default(string);
				if (!val.TryAddCharacters("abcdefghijklmnopqrstuvwxyzäöüñç", ref text2, false))
				{
					LogError("TextMeshPro could not add all custom lowercase characters. Missing: " + text2);
					return null;
				}
				val.atlasPopulationMode = (AtlasPopulationMode)0;
				val.ReadFontAssetDefinition();
				Object.DontDestroyOnLoad((Object)(object)val);
				if ((Object)(object)((TMP_Asset)val).material != (Object)null)
				{
					Object.DontDestroyOnLoad((Object)(object)((TMP_Asset)val).material);
				}
				Texture2D[] atlasTextures = val.atlasTextures;
				if (atlasTextures != null)
				{
					for (int i = 0; i < atlasTextures.Length; i++)
					{
						if ((Object)(object)atlasTextures[i] != (Object)null)
						{
							Object.DontDestroyOnLoad((Object)(object)atlasTextures[i]);
						}
					}
				}
				_font = val;
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)"Created the lowercase TextMeshPro font directly from MixedCaseNorseLowercase-Regular.ttf at runtime.");
				}
				return _font;
			}
			catch (Exception ex)
			{
				LogError("Creating the lowercase runtime font failed: " + ex);
				return null;
			}
		}

		public static void Dispose()
		{
			_font = null;
			_attempted = false;
			_errorLogged = false;
		}

		private static void LogError(string message)
		{
			if (!_errorLogged)
			{
				ManualLogSource? log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)message);
				}
				_errorLogged = true;
			}
		}
	}
}