Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MixedCaseMapMarkers v1.1.0
plugins/MixedCaseMapMarkers/MixedCaseMapMarkers.dll
Decompiled a day agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using MixedCaseMapMarkers.Patches; using TMPro; using UnityEngine; 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: AssemblyDescription("Displays Valheim map marker names using their stored lowercase and mixed-case text.")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("MixedCaseMapMarkers")] [assembly: AssemblyTitle("MixedCaseMapMarkers")] [assembly: AssemblyVersion("1.1.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", "1.1.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.lexpy.mixedcasemapmarkers"; public const string PluginName = "MixedCaseMapMarkers"; public const string PluginVersion = "1.1.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 1.1.0 loaded."); } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } MapMarkerText.Dispose(); _harmony = null; Log = null; } } } namespace MixedCaseMapMarkers.Patches { internal static class MapMarkerText { private const float FontSizeMultiplier = 0.86f; private const float CharacterSpacingAdjustment = -3.25f; private const float WordSpacingAdjustment = -2f; private const float CharacterWidthAdjustment = 18f; private const float OutlineWidth = 0.12f; private const string UnderlayKeyword = "UNDERLAY_ON"; private static readonly Color OutlineColor = new Color(0f, 0f, 0f, 1f); private static readonly Color UnderlayColor = new Color(0f, 0f, 0f, 0.85f); private static readonly int OutlineColorId = Shader.PropertyToID("_OutlineColor"); private static readonly int OutlineWidthId = Shader.PropertyToID("_OutlineWidth"); private static readonly int UnderlayColorId = Shader.PropertyToID("_UnderlayColor"); private static readonly int UnderlayOffsetXId = Shader.PropertyToID("_UnderlayOffsetX"); private static readonly int UnderlayOffsetYId = Shader.PropertyToID("_UnderlayOffsetY"); private static readonly int UnderlayDilateId = Shader.PropertyToID("_UnderlayDilate"); private static readonly int UnderlaySoftnessId = Shader.PropertyToID("_UnderlaySoftness"); private static readonly FieldInfo? ChatInputField = AccessTools.Field(typeof(Terminal), "m_input"); private static readonly FieldInfo? NameInputField = AccessTools.Field(typeof(Minimap), "m_nameInput"); private static TMP_FontAsset? _chatFont; private static Material? _markerMaterial; private static FieldInfo? _pinSaveField; private static Type? _pinDataType; private static bool _fontLogged; private static bool _missingInputWarningLogged; private static bool _missingSaveFieldWarningLogged; public static void CaptureChatFont(Chat chat) { if (_chatFont != null || chat == null) { return; } _chatFont = FindFont(ChatInputField?.GetValue(chat)); if (_chatFont == null) { return; } _markerMaterial = CreateMarkerMaterial(_chatFont); if (!_fontLogged) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogInfo((object)("Using Valheim chat font '" + ((Object)_chatFont).name + "' for persistent map markers.")); } _fontLogged = true; } } public static void ConfigureNameInput(Minimap minimap) { if (minimap == null || _chatFont == null) { return; } object obj = NameInputField?.GetValue(minimap); if (obj == null) { LogMissingInputWarning(); return; } GameObject root = GetRoot(obj); if (root != null) { TMP_InputField[] componentsInChildren = root.GetComponentsInChildren<TMP_InputField>(true); foreach (TMP_InputField obj2 in componentsInChildren) { obj2.contentType = (ContentType)0; obj2.characterValidation = (CharacterValidation)0; obj2.inputValidator = null; obj2.onValidateInput = null; } TMP_Text[] componentsInChildren2 = root.GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { ApplyText(componentsInChildren2[i]); } } } public static int CaptureChildCount(RectTransform? root) { if (root == null) { return -1; } return ((Transform)root).childCount; } public static void ApplyCreatedPersistentMarker(object? pinData, RectTransform? root, int previousChildCount) { if (_chatFont == null || root == null || previousChildCount < 0 || !IsPersistentPin(pinData)) { return; } for (int i = Mathf.Clamp(previousChildCount, 0, ((Transform)root).childCount); i < ((Transform)root).childCount; i++) { TMP_Text[] componentsInChildren = ((Component)((Transform)root).GetChild(i)).GetComponentsInChildren<TMP_Text>(true); for (int j = 0; j < componentsInChildren.Length; j++) { ApplyText(componentsInChildren[j]); } } } public static void Dispose() { if (_markerMaterial != null) { Object.Destroy((Object)(object)_markerMaterial); } _chatFont = null; _markerMaterial = null; _pinSaveField = null; _pinDataType = null; } private static bool IsPersistentPin(object? pinData) { if (pinData == null) { return false; } Type type = pinData.GetType(); if (_pinDataType != type) { _pinDataType = type; _pinSaveField = AccessTools.Field(type, "m_save"); } if ((object)_pinSaveField == null) { if (!_missingSaveFieldWarningLogged) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogWarning((object)"Valheim's PinData.m_save field was not found. Persistent marker labels will not be modified."); } _missingSaveFieldWarningLogged = true; } return false; } object value = _pinSaveField.GetValue(pinData); if (value is bool) { return (bool)value; } return false; } private static void ApplyText(TMP_Text text) { if (!((Object)(object)text.font == (Object)(object)_chatFont) || (_markerMaterial != null && !((Object)(object)text.fontSharedMaterial == (Object)(object)_markerMaterial))) { RemoveCaseStyle(text); text.font = _chatFont; if (_markerMaterial != null) { text.fontSharedMaterial = _markerMaterial; } text.fontSize *= 0.86f; text.fontSizeMin *= 0.86f; text.fontSizeMax *= 0.86f; text.characterSpacing += -3.25f; text.wordSpacing += -2f; text.characterWidthAdjustment = Mathf.Max(text.characterWidthAdjustment, 18f); ((Graphic)text).SetVerticesDirty(); ((Graphic)text).SetLayoutDirty(); } } private static Material? CreateMarkerMaterial(TMP_FontAsset font) { //IL_0022: 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_0032: 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_0042: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00ae: Expected O, but got Unknown Material material = ((TMP_Asset)font).material; if (material == null) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogWarning((object)"Valheim's chat font has no material. The custom outline will not be applied."); } return null; } Material val = new Material(material) { name = "MixedCaseMapMarkers-Material" }; SetColor(val, OutlineColorId, OutlineColor); SetFloat(val, OutlineWidthId, 0.12f); val.EnableKeyword("UNDERLAY_ON"); SetColor(val, UnderlayColorId, UnderlayColor); SetFloat(val, UnderlayOffsetXId, 0.1f); SetFloat(val, UnderlayOffsetYId, -0.1f); SetFloat(val, UnderlayDilateId, 0.15f); SetFloat(val, UnderlaySoftnessId, 0.05f); return val; } 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 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; } private static TMP_FontAsset? FindFont(object? value) { TMP_InputField val = (TMP_InputField)((value is TMP_InputField) ? value : null); if (val != null) { TMP_Text textComponent = val.textComponent; object obj = ((textComponent != null) ? textComponent.font : null); if (obj == null) { Graphic placeholder = val.placeholder; Graphic obj2 = ((placeholder is TMP_Text) ? placeholder : null); if (obj2 == null) { return null; } obj = ((TMP_Text)obj2).font; } return (TMP_FontAsset?)obj; } TMP_Text val2 = (TMP_Text)((value is TMP_Text) ? value : null); if (val2 != null) { return val2.font; } GameObject root = GetRoot(value); if (root == null) { return null; } TMP_Text[] componentsInChildren = root.GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { TMP_FontAsset font = componentsInChildren[i].font; if (font != null) { return 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 void LogMissingInputWarning() { if (!_missingInputWarningLogged) { ManualLogSource? log = Plugin.Log; if (log != null) { log.LogWarning((object)"Valheim's map-marker name input field was not found. A game update may have changed the map UI."); } _missingInputWarningLogged = true; } } private static void SetColor(Material material, int propertyId, Color value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyId)) { material.SetColor(propertyId, value); } } private static void SetFloat(Material material, int propertyId, float value) { if (material.HasProperty(propertyId)) { material.SetFloat(propertyId, value); } } } [HarmonyPatch(typeof(Chat), "Awake")] internal static class ChatAwakePatch { [HarmonyPostfix] private static void Postfix(Chat __instance) { MapMarkerText.CaptureChatFont(__instance); } } [HarmonyPatch(typeof(Minimap), "ShowPinNameInput")] internal static class MinimapShowPinNameInputPatch { [HarmonyPostfix] private static void Postfix(Minimap __instance) { MapMarkerText.ConfigureNameInput(__instance); } } [HarmonyPatch(typeof(Minimap), "CreateMapNamePin")] internal static class MinimapCreateMapNamePinPatch { [HarmonyPrefix] private static void Prefix(RectTransform __1, out int __state) { __state = MapMarkerText.CaptureChildCount(__1); } [HarmonyPostfix] private static void Postfix(object __0, RectTransform __1, int __state) { MapMarkerText.ApplyCreatedPersistentMarker(__0, __1, __state); } } }