using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Extensions; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using NoMapDiscordAdditions.MapCompile; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyCompany("NoMapDiscordAdditions")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+b65614dffee2d29f02a8d9546d4579fe4b048e87")] [assembly: AssemblyProduct("NoMapDiscordAdditions")] [assembly: AssemblyTitle("NoMapDiscordAdditions")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace NoMapDiscordAdditions { public static class CaptureButton { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__15_2; public static UnityAction <>9__15_0; public static UnityAction <>9__15_1; internal void b__15_2(bool val) { if (Plugin.ShowBiomeText != null) { Plugin.ShowBiomeText.Value = val; } } internal void b__15_0() { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null)) { PinCaptureFilter.ArmFromCurrentInput(); instance.TriggerDiscordSend(); } } internal void b__15_1() { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null)) { PinCaptureFilter.ArmFromCurrentInput(); instance.TriggerClipboardCopy(); } } } private static GameObject _containerObj; private static Button _captureBtn; private static TextMeshProUGUI _captureBtnText; private static Button _clipboardBtn; private static TextMeshProUGUI _clipboardBtnText; private static GameObject _biomeToggleObj; private static Toggle _biomeToggle; private static Image _biomeToggleCheckmark; private static float _biomeToggleWidth = 130f; private static float _biomeToggleHeight = 38f; private const string ContainerName = "CaptureButtonPanel"; private const float BtnWidth = 180f; private const float BtnHeight = 38f; private const float HlgPadVertical = 6f; private const float HlgSpacing = 8f; public static void Create() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Expected O, but got Unknown Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_largeRoot == (Object)null) { return; } Transform transform = instance.m_largeRoot.transform; DestroyExisting(transform); if ((Object)(object)_containerObj != (Object)null) { return; } _containerObj = new GameObject("CaptureButtonPanel"); _containerObj.transform.SetParent(transform, false); RectTransform obj = _containerObj.AddComponent(); obj.pivot = new Vector2(0.5f, 1f); float num = Mathf.Max(_biomeToggleHeight, 38f) + 12f; obj.sizeDelta = new Vector2(8f + _biomeToggleWidth + 8f + 180f + 8f, num); ApplyAlignment(obj); MapUI.ApplyPanelBackground(_containerObj.AddComponent(), instance); HorizontalLayoutGroup obj2 = _containerObj.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f; ((LayoutGroup)obj2).padding = new RectOffset(8, 8, 6, 6); Transform val2 = Utils.FindChild(((Component)instance).transform, "SharedPanel", (IterativeSearchType)0); if ((Object)(object)val2 != (Object)null) { _biomeToggleObj = Object.Instantiate(((Component)val2).gameObject, _containerObj.transform); ((Object)_biomeToggleObj).name = "BiomeToggle"; _biomeToggleObj.SetActive(true); RectTransform component = _biomeToggleObj.GetComponent(); if ((Object)(object)component != (Object)null) { if (component.sizeDelta.x > 0f) { _biomeToggleWidth = component.sizeDelta.x; } _biomeToggleHeight = 38f; component.sizeDelta = new Vector2(_biomeToggleWidth, 38f); } _biomeToggle = _biomeToggleObj.GetComponentInChildren(true); if ((Object)(object)_biomeToggle != (Object)null) { ((UnityEventBase)_biomeToggle.onValueChanged).RemoveAllListeners(); _biomeToggle.isOn = Plugin.ShowBiomeText?.Value ?? false; ((UnityEvent)(object)_biomeToggle.onValueChanged).AddListener((UnityAction)delegate(bool val) { if (Plugin.ShowBiomeText != null) { Plugin.ShowBiomeText.Value = val; } }); } Transform val3 = Utils.FindChild(_biomeToggleObj.transform, "Label", (IterativeSearchType)0); if ((Object)(object)val3 != (Object)null) { TextMeshProUGUI component2 = ((Component)val3).GetComponent(); if ((Object)(object)component2 != (Object)null) { ((TMP_Text)component2).text = "Show Biome Text"; } } Transform obj3 = Utils.FindChild(_biomeToggleObj.transform, "Checkmark", (IterativeSearchType)0); _biomeToggleCheckmark = ((obj3 != null) ? ((Component)obj3).GetComponent() : null); } else { ModLog.Warn("[NoMapDiscordAdditions] SharedPanel not found — biome toggle skipped."); } _captureBtn = MapUI.CreateButton("CaptureBtn", _containerObj.transform, 180f, 38f, BuildSendLabel(), out _captureBtnText); ButtonClickedEvent onClick = _captureBtn.onClick; object obj4 = <>c.<>9__15_0; if (obj4 == null) { UnityAction val4 = delegate { Plugin instance3 = Plugin.Instance; if (!((Object)(object)instance3 == (Object)null)) { PinCaptureFilter.ArmFromCurrentInput(); instance3.TriggerDiscordSend(); } }; <>c.<>9__15_0 = val4; obj4 = (object)val4; } ((UnityEvent)onClick).AddListener((UnityAction)obj4); _clipboardBtn = MapUI.CreateButton("ClipboardBtn", _containerObj.transform, 180f, 38f, BuildCopyLabel(), out _clipboardBtnText); ButtonClickedEvent onClick2 = _clipboardBtn.onClick; object obj5 = <>c.<>9__15_1; if (obj5 == null) { UnityAction val5 = delegate { Plugin instance2 = Plugin.Instance; if (!((Object)(object)instance2 == (Object)null)) { PinCaptureFilter.ArmFromCurrentInput(); instance2.TriggerClipboardCopy(); } }; <>c.<>9__15_1 = val5; obj5 = (object)val5; } ((UnityEvent)onClick2).AddListener((UnityAction)obj5); Plugin.SendingStateChanged -= RefreshLoadingState; Plugin.SendingStateChanged += RefreshLoadingState; _containerObj.SetActive(true); RefreshEnabledState(); RefreshBiomeToggleState(); RefreshLoadingState(); ModLog.Info("[NoMapDiscordAdditions] Map button container created."); } public static void RefreshLoadingState() { if (!((Object)(object)_captureBtn == (Object)null) && !((Object)(object)_clipboardBtn == (Object)null) && !((Object)(object)_captureBtnText == (Object)null) && !((Object)(object)_clipboardBtnText == (Object)null)) { bool isSendingInProgress = Plugin.IsSendingInProgress; Plugin.SendingOp currentSendingOp = Plugin.CurrentSendingOp; bool flag = !string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl); ((Selectable)_captureBtn).interactable = !isSendingInProgress && flag; ((Selectable)_clipboardBtn).interactable = !isSendingInProgress; ((TMP_Text)_captureBtnText).text = ((isSendingInProgress && currentSendingOp == Plugin.SendingOp.Send) ? "SENDING..." : BuildSendLabel()); ((TMP_Text)_clipboardBtnText).text = ((isSendingInProgress && currentSendingOp == Plugin.SendingOp.Copy) ? "COPYING..." : BuildCopyLabel()); } } public static void RefreshEnabledState() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_containerObj == (Object)null)) { bool flag = false; if ((Object)(object)_captureBtn != (Object)null) { flag = !string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl); ((Component)_captureBtn).gameObject.SetActive(flag); } RectTransform component = _containerObj.GetComponent(); if ((Object)(object)component != (Object)null) { float num = 8f + _biomeToggleWidth + 8f + 180f + 8f + (flag ? 188f : 0f); float num2 = Mathf.Max(_biomeToggleHeight, 38f) + 12f; component.sizeDelta = new Vector2(num, num2); ApplyAlignment(component); } } } public static void RefreshHotkeyLabels() { if ((Object)(object)_captureBtnText != (Object)null) { ((TMP_Text)_captureBtnText).text = BuildSendLabel(); } if ((Object)(object)_clipboardBtnText != (Object)null) { ((TMP_Text)_clipboardBtnText).text = BuildCopyLabel(); } } private static string BuildSendLabel() { //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) ConfigEntry sendKey = Plugin.SendKey; object obj; if (sendKey == null) { obj = null; } else { KeyCode value = sendKey.Value; obj = ((object)(KeyCode)(ref value)).ToString(); } if (obj == null) { obj = "F10"; } return "SEND MAP (" + (string?)obj + ")"; } private static string BuildCopyLabel() { //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) ConfigEntry copyKey = Plugin.CopyKey; object obj; if (copyKey == null) { obj = null; } else { KeyCode value = copyKey.Value; obj = ((object)(KeyCode)(ref value)).ToString(); } if (obj == null) { obj = "F11"; } return "COPY MAP (" + (string?)obj + ")"; } public static void RefreshBiomeToggleState() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_biomeToggle == (Object)null)) { bool flag = Plugin.ShowBiomeText?.Value ?? false; _biomeToggle.isOn = flag; if ((Object)(object)_biomeToggleCheckmark != (Object)null) { ((Graphic)_biomeToggleCheckmark).color = (Color)(flag ? new Color(1f, 0.631f, 0.235f, 1f) : Color.white); } } } public static void SetVisible(bool visible) { if (!((Object)(object)_containerObj == (Object)null)) { _containerObj.SetActive(visible); if (visible) { RefreshEnabledState(); RefreshLoadingState(); } } } public static void ApplyAlignment() { if (!((Object)(object)_containerObj == (Object)null)) { ApplyAlignment(_containerObj.GetComponent()); } } private static void ApplyAlignment(RectTransform rect) { //IL_000b: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { float num = rect.sizeDelta.x * 0.5f; rect.anchorMin = new Vector2(1f, 0f); rect.anchorMax = new Vector2(1f, 0f); rect.anchoredPosition = new Vector2(0f - (8f + num), -8f); } } private static void DestroyExisting(Transform largeRoot) { for (int num = largeRoot.childCount - 1; num >= 0; num--) { Transform child = largeRoot.GetChild(num); if (!((Object)(object)child == (Object)null) && ((Object)child).name == "CaptureButtonPanel") { Object.Destroy((Object)(object)((Component)child).gameObject); } } if (!Object.op_Implicit((Object)(object)_containerObj)) { _containerObj = null; } if (!Object.op_Implicit((Object)(object)_captureBtn)) { _captureBtn = null; } if (!Object.op_Implicit((Object)(object)_captureBtnText)) { _captureBtnText = null; } if (!Object.op_Implicit((Object)(object)_clipboardBtn)) { _clipboardBtn = null; } if (!Object.op_Implicit((Object)(object)_clipboardBtnText)) { _clipboardBtnText = null; } if (!Object.op_Implicit((Object)(object)_biomeToggleObj)) { _biomeToggleObj = null; } if (!Object.op_Implicit((Object)(object)_biomeToggle)) { _biomeToggle = null; } if (!Object.op_Implicit((Object)(object)_biomeToggleCheckmark)) { _biomeToggleCheckmark = null; } MapUI.InvalidateCaches(); } } [HarmonyPatch] public static class CartographyTablePatch { [HarmonyPatch(typeof(MapTable), "OnRead", new Type[] { typeof(Switch), typeof(Humanoid), typeof(ItemData) })] [HarmonyPostfix] private static void OnRead_Postfix(MapTable __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null)) { MapCompileSession.SetActiveTable(((Component)__instance).transform.position); } } } public static class DiscordWebhook { private sealed class BypassCertificateHandler : CertificateHandler { protected override bool ValidateCertificate(byte[] certificateData) { return true; } } public struct OutgoingImage { public byte[] Bytes; public string FileName; } public const int MaxImagesPerMessage = 5; public static IEnumerator SendImages(IList images, string message, bool useSpoilerTag) { if (images == null || images.Count == 0) { yield break; } string webhookUrl = ModHelpers.EffectiveConfig.WebhookUrl; if (string.IsNullOrEmpty(webhookUrl)) { ModLog.Warn("[NoMapDiscordAdditions] Webhook URL not configured."); yield break; } WWWForm val = new WWWForm(); int count = Mathf.Min(images.Count, 5); for (int i = 0; i < count; i++) { val.AddBinaryData($"files[{i}]", images[i].Bytes, GetAttachmentFileName(images[i].FileName, useSpoilerTag), "image/png"); } if (!string.IsNullOrEmpty(message)) { val.AddField("payload_json", JsonConvert.SerializeObject((object)new { content = message })); } UnityWebRequest request = UnityWebRequest.Post(webhookUrl, val); try { request.certificateHandler = (CertificateHandler)(object)new BypassCertificateHandler(); yield return request.SendWebRequest(); if ((int)request.result != 1) { ModLog.Error("[NoMapDiscordAdditions] Discord webhook failed: " + request.error); } else { ModLog.Info($"[NoMapDiscordAdditions] Sent {count} image(s) to Discord."); } } finally { ((IDisposable)request)?.Dispose(); } } public static IEnumerator SendImageBatches(IList images, string message, bool useSpoilerTag) { if (images == null || images.Count == 0) { yield break; } for (int start = 0; start < images.Count; start += 5) { int num = Mathf.Min(5, images.Count - start); List list = new List(num); for (int i = 0; i < num; i++) { list.Add(images[start + i]); } string message2 = ((start == 0) ? message : null); yield return SendImages(list, message2, useSpoilerTag); } } public static IEnumerator SendImage(byte[] imageData, string filename, string message, bool useSpoilerTag) { string webhookUrl = ModHelpers.EffectiveConfig.WebhookUrl; if (string.IsNullOrEmpty(webhookUrl)) { ModLog.Warn("[NoMapDiscordAdditions] Webhook URL not configured."); yield break; } WWWForm val = new WWWForm(); val.AddBinaryData("files[0]", imageData, GetAttachmentFileName(filename, useSpoilerTag), "image/png"); if (!string.IsNullOrEmpty(message)) { val.AddField("payload_json", JsonConvert.SerializeObject((object)new { content = message })); } UnityWebRequest request = UnityWebRequest.Post(webhookUrl, val); try { request.certificateHandler = (CertificateHandler)(object)new BypassCertificateHandler(); yield return request.SendWebRequest(); if ((int)request.result != 1) { ModLog.Error("[NoMapDiscordAdditions] Discord webhook failed: " + request.error); } else { ModLog.Info("[NoMapDiscordAdditions] Map screenshot sent to Discord."); } } finally { ((IDisposable)request)?.Dispose(); } } private static string GetAttachmentFileName(string filename, bool useSpoilerTag) { if (!useSpoilerTag || string.IsNullOrEmpty(filename) || filename.StartsWith("SPOILER_")) { return filename; } return "SPOILER_" + filename; } } public static class MapCaptureTexture { public const int OutputWidth = 1920; public const int OutputHeight = 1080; private static readonly Dictionary _atlasCache = new Dictionary(); private static bool _uvRemapActive; private static float _ruX0; private static float _ruX1; private static float _ruY0; private static float _ruY1; private static float _cuX0; private static float _cuY0; private static float _cuW; private static float _cuH; public static void GetDefaultCaptureSize(out int width, out int height) { width = 1920; height = 1080; Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_mapImageLarge == (Object)null)) { Vector3[] array = (Vector3[])(object)new Vector3[4]; ((Graphic)instance.m_mapImageLarge).rectTransform.GetWorldCorners(array); int num = Mathf.RoundToInt(Mathf.Abs(array[2].x - array[0].x)); int num2 = Mathf.RoundToInt(Mathf.Abs(array[2].y - array[0].y)); if (num >= 64 && num2 >= 64) { width = num; height = num2; } } } public static byte[] CaptureMap() { GetDefaultCaptureSize(out var width, out var height); return CaptureMap(width, height); } public static byte[] CaptureMap(int outputWidth, int outputHeight, Texture2D styledBase = null, bool drawPinIcons = true) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Invalid comparison between Unknown and I4 //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if (outputWidth < 64 || outputHeight < 64) { ModLog.Error($"[NoMapDiscordAdditions] CaptureMap: invalid size {outputWidth}x{outputHeight}."); return null; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || (int)instance.m_mode != 2) { ModLog.Error("[NoMapDiscordAdditions] Large map not active."); return null; } Texture2D mapTexture = instance.m_mapTexture; RawImage mapImageLarge = instance.m_mapImageLarge; RectTransform pinRootLarge = instance.m_pinRootLarge; if ((Object)(object)mapTexture == (Object)null || (Object)(object)mapImageLarge == (Object)null) { ModLog.Error("[NoMapDiscordAdditions] Required Minimap fields not available."); return null; } Material val = instance.m_mapLargeShader; if ((Object)(object)val == (Object)null) { val = ((Graphic)mapImageLarge).material; } RectTransform rectTransform = ((Graphic)mapImageLarge).rectTransform; Vector3[] array = (Vector3[])(object)new Vector3[4]; rectTransform.GetWorldCorners(array); float x = array[0].x; float y = array[0].y; float x2 = array[2].x; float y2 = array[2].y; float num = x2 - x; float num2 = y2 - y; if (num <= 0f || num2 <= 0f) { ModLog.Error("[NoMapDiscordAdditions] Map RectTransform has zero size."); return null; } RenderTexture temporary = RenderTexture.GetTemporary(outputWidth, outputHeight, 0, (RenderTextureFormat)0); Color32[] array2; try { if ((Object)(object)styledBase != (Object)null) { DrawStyledBase(temporary, styledBase); } else { DrawMapBase(temporary, mapTexture, val, mapImageLarge.uvRect); } array2 = ReadRTPixels(temporary); } finally { RenderTexture.ReleaseTemporary(temporary); } if (array2 == null) { ModLog.Error("[NoMapDiscordAdditions] GPU pass failed."); return null; } BeginUvRemap(mapImageLarge.uvRect); PinCaptureFilter.State state = default(PinCaptureFilter.State); if (drawPinIcons) { state = PinCaptureFilter.Apply(); } try { if ((Object)(object)pinRootLarge != (Object)null && drawPinIcons) { BlitUIChildren(array2, outputWidth, outputHeight, x, y, num, num2, (Transform)(object)pinRootLarge); } if ((Object)(object)instance.m_pinNameRootLarge != (Object)null && drawPinIcons) { BlitUIChildren(array2, outputWidth, outputHeight, x, y, num, num2, (Transform)(object)instance.m_pinNameRootLarge); } BlitMarker(instance.m_largeMarker, array2, outputWidth, outputHeight, x, y, num, num2); BlitMarker(instance.m_largeShipMarker, array2, outputWidth, outputHeight, x, y, num, num2); return Encode(array2, outputWidth, outputHeight); } finally { PinCaptureFilter.Restore(state); _atlasCache.Clear(); EndUvRemap(); } } private static void BeginUvRemap(Rect uv) { _ruX0 = ((Rect)(ref uv)).xMin; _ruX1 = ((Rect)(ref uv)).xMax; _ruY0 = ((Rect)(ref uv)).yMin; _ruY1 = ((Rect)(ref uv)).yMax; _cuX0 = Mathf.Clamp01(_ruX0); _cuY0 = Mathf.Clamp01(_ruY0); _cuW = Mathf.Clamp01(_ruX1) - _cuX0; _cuH = Mathf.Clamp01(_ruY1) - _cuY0; float num = _ruX1 - _ruX0; float num2 = _ruY1 - _ruY0; _uvRemapActive = _cuW > 1E-06f && _cuH > 1E-06f && num > 1E-06f && num2 > 1E-06f && (Mathf.Abs(num - _cuW) > 1E-05f || Mathf.Abs(num2 - _cuH) > 1E-05f); } private static void EndUvRemap() { _uvRemapActive = false; } private static float ProjectX(float screenX, float mapMinX, float mapW, int outW) { float num = (screenX - mapMinX) / mapW; if (!_uvRemapActive) { return num * (float)outW; } return (_ruX0 + num * (_ruX1 - _ruX0) - _cuX0) / _cuW * (float)outW; } private static float ProjectY(float screenY, float mapMinY, float mapH, int outH) { float num = (screenY - mapMinY) / mapH; if (!_uvRemapActive) { return num * (float)outH; } return (_ruY0 + num * (_ruY1 - _ruY0) - _cuY0) / _cuH * (float)outH; } private static float RemapScaleX(float mapW, int outW) { if (!_uvRemapActive) { return (float)outW / mapW; } return (float)outW / _cuW * ((_ruX1 - _ruX0) / mapW); } private static float RemapScaleY(float mapH, int outH) { if (!_uvRemapActive) { return (float)outH / mapH; } return (float)outH / _cuH * ((_ruY1 - _ruY0) / mapH); } private static void DrawMapBase(RenderTexture target, Texture2D mapTex, Material mat, Rect uv) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(((Rect)(ref uv)).xMin); float num2 = Mathf.Clamp01(((Rect)(ref uv)).yMin); float num3 = Mathf.Clamp01(((Rect)(ref uv)).xMax); float num4 = Mathf.Clamp01(((Rect)(ref uv)).yMax); List list = null; Texture val = null; bool flag = (Object)(object)mat != (Object)null && mat.HasProperty("_MainTex"); bool num5 = Plugin.NormalizeCaptureLighting?.Value ?? true; ModHelpers.SavedLighting saved = default(ModHelpers.SavedLighting); if (num5) { saved = ModHelpers.OverrideLightingToNoon(); } if (ModHelpers.EffectiveConfig.HideClouds && (Object)(object)mat != (Object)null) { list = ModHelpers.SuppressShaderPropsContaining(mat, "cloud"); } if (flag) { val = mat.GetTexture("_MainTex"); mat.SetTexture("_MainTex", (Texture)(object)mapTex); } RenderTexture active = RenderTexture.active; try { RenderTexture.active = target; GL.Clear(true, true, Color.black); bool flag2 = false; if ((Object)(object)mat != (Object)null && mat.SetPass(0)) { GL.PushMatrix(); GL.LoadOrtho(); GL.Begin(7); GL.TexCoord2(num, num2); GL.Vertex3(0f, 0f, 0f); GL.TexCoord2(num3, num2); GL.Vertex3(1f, 0f, 0f); GL.TexCoord2(num3, num4); GL.Vertex3(1f, 1f, 0f); GL.TexCoord2(num, num4); GL.Vertex3(0f, 1f, 0f); GL.End(); GL.PopMatrix(); flag2 = true; } if (!flag2) { Graphics.Blit((Texture)(object)mapTex, target, new Vector2(num3 - num, num4 - num2), new Vector2(num, num2)); } } finally { RenderTexture.active = active; if (flag && (Object)(object)val != (Object)null) { mat.SetTexture("_MainTex", val); } if (list != null) { ModHelpers.RestoreShaderProps(mat, list); } ModHelpers.RestoreLighting(saved); } } private static void DrawStyledBase(RenderTexture target, Texture2D styled) { Graphics.Blit((Texture)(object)styled, target); } private static Color32[] ReadRTPixels(RenderTexture rt) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown RenderTexture active = RenderTexture.active; RenderTexture.active = rt; Texture2D val = new Texture2D(((Texture)rt).width, ((Texture)rt).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)rt).width, (float)((Texture)rt).height), 0, 0); val.Apply(); RenderTexture.active = active; Color32[] pixels = val.GetPixels32(); Object.Destroy((Object)val); return pixels; } private static void BlitUIChildren(Color32[] output, int outputWidth, int outputHeight, float mapMinX, float mapMinY, float mapW, float mapH, Transform parent) { int childCount = parent.childCount; for (int i = 0; i < childCount; i++) { Transform child = parent.GetChild(i); if ((Object)(object)child == (Object)null || !((Component)child).gameObject.activeInHierarchy) { continue; } RectTransform val = (RectTransform)(object)((child is RectTransform) ? child : null); if (!((Object)(object)val == (Object)null)) { Image component = ((Component)child).GetComponent(); if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled && (Object)(object)component.sprite != (Object)null) { BlitImage(output, outputWidth, outputHeight, mapMinX, mapMinY, mapW, mapH, val, component); } TMP_Text component2 = ((Component)child).GetComponent(); if ((Object)(object)component2 != (Object)null && ((Behaviour)component2).enabled && !string.IsNullOrEmpty(component2.text)) { BlitText(output, outputWidth, outputHeight, mapMinX, mapMinY, mapW, mapH, component2, forceMeshUpdate: true, drawOutline: true); } if (child.childCount > 0) { BlitUIChildren(output, outputWidth, outputHeight, mapMinX, mapMinY, mapW, mapH, child); } } } } private static void BlitMarker(RectTransform rt, Color32[] output, int outputWidth, int outputHeight, float mapMinX, float mapMinY, float mapW, float mapH) { if (!((Object)(object)rt == (Object)null) && ((Component)rt).gameObject.activeInHierarchy) { Image component = ((Component)rt).GetComponent(); if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled && (Object)(object)component.sprite != (Object)null) { BlitImage(output, outputWidth, outputHeight, mapMinX, mapMinY, mapW, mapH, rt, component); } } } private static void BlitImage(Color32[] output, int outputWidth, int outputHeight, float mapMinX, float mapMinY, float mapW, float mapH, RectTransform target, Image img) { //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4]; target.GetWorldCorners(array); float screenX = (array[0].x + array[2].x) * 0.5f; float screenY = (array[0].y + array[2].y) * 0.5f; float num = array[2].x - array[0].x; float num2 = array[2].y - array[0].y; if (num <= 0f || num2 <= 0f) { return; } int num3 = Mathf.RoundToInt(ProjectX(screenX, mapMinX, mapW, outputWidth)); int num4 = Mathf.RoundToInt(ProjectY(screenY, mapMinY, mapH, outputHeight)); float num5 = RemapScaleX(mapW, outputWidth); float num6 = RemapScaleY(mapH, outputHeight); int num7 = Mathf.Max(1, Mathf.RoundToInt(num * num5)); int num8 = Mathf.Max(1, Mathf.RoundToInt(num2 * num6)); int num9 = num7 / 2; int num10 = num8 / 2; if (num3 + num9 < 0 || num3 - num9 >= outputWidth || num4 + num10 < 0 || num4 - num10 >= outputHeight) { return; } Sprite sprite = img.sprite; Rect textureRect = sprite.textureRect; int num11 = Mathf.RoundToInt(((Rect)(ref textureRect)).x); int num12 = Mathf.RoundToInt(((Rect)(ref textureRect)).y); int num13 = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num14 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); if (num13 <= 0 || num14 <= 0) { return; } Color32[] cachedAtlasPixels = GetCachedAtlasPixels(sprite.texture); if (cachedAtlasPixels == null) { return; } int width = ((Texture)sprite.texture).width; Color32 val = Color32.op_Implicit(((Graphic)img).color); float num15 = (float)num13 / (float)num7; float num16 = (float)num14 / (float)num8; for (int i = 0; i < num8; i++) { int num17 = num4 - num10 + i; if (num17 < 0 || num17 >= outputHeight) { continue; } int num18 = Mathf.Clamp((int)((float)i * num16), 0, num14 - 1); int num19 = (num12 + num18) * width + num11; int num20 = num17 * outputWidth; for (int j = 0; j < num7; j++) { int num21 = num3 - num9 + j; if (num21 < 0 || num21 >= outputWidth) { continue; } int num22 = Mathf.Clamp((int)((float)j * num15), 0, num13 - 1); Color32 val2 = cachedAtlasPixels[num19 + num22]; int num23 = val2.a * val.a / 255; if (num23 != 0) { int num24 = val2.r * val.r / 255; int num25 = val2.g * val.g / 255; int num26 = val2.b * val.b / 255; int num27 = num20 + num21; if (num23 >= 250) { output[num27] = new Color32((byte)num24, (byte)num25, (byte)num26, byte.MaxValue); continue; } Color32 val3 = output[num27]; int num28 = 255 - num23; output[num27] = new Color32((byte)((num24 * num23 + val3.r * num28) / 255), (byte)((num25 * num23 + val3.g * num28) / 255), (byte)((num26 * num23 + val3.b * num28) / 255), byte.MaxValue); } } } } private static void BlitText(Color32[] output, int outputWidth, int outputHeight, float mapMinX, float mapMinY, float mapW, float mapH, TMP_Text tmp, bool forceMeshUpdate = true, bool drawOutline = false) { //IL_0037: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_019c: 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) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: 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) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) if (forceMeshUpdate) { tmp.ForceMeshUpdate(false, false); } TMP_TextInfo textInfo = tmp.textInfo; if (textInfo == null || textInfo.characterCount == 0) { return; } RectTransform rectTransform = tmp.rectTransform; for (int i = 0; i < textInfo.characterCount; i++) { TMP_CharacterInfo val = textInfo.characterInfo[i]; if (!val.isVisible) { continue; } Texture obj = (((Object)(object)val.material != (Object)null) ? val.material.mainTexture : null); Texture2D val2 = (Texture2D)(object)((obj is Texture2D) ? obj : null); if ((Object)(object)val2 == (Object)null && (Object)(object)val.fontAsset != (Object)null) { val2 = val.fontAsset.atlasTexture; } if ((Object)(object)val2 == (Object)null) { continue; } Color32[] cachedAtlasPixels = GetCachedAtlasPixels(val2); if (cachedAtlasPixels == null) { continue; } int width = ((Texture)val2).width; int height = ((Texture)val2).height; Vector3 val3 = ((Transform)rectTransform).TransformPoint(val.vertex_BL.position); Vector3 val4 = ((Transform)rectTransform).TransformPoint(val.vertex_TR.position); float num = ProjectX(val3.x, mapMinX, mapW, outputWidth); float num2 = ProjectX(val4.x, mapMinX, mapW, outputWidth); float num3 = ProjectY(val3.y, mapMinY, mapH, outputHeight); float num4 = ProjectY(val4.y, mapMinY, mapH, outputHeight); int num5 = Mathf.FloorToInt(Mathf.Min(num, num2)); int num6 = Mathf.CeilToInt(Mathf.Max(num, num2)); int num7 = Mathf.FloorToInt(Mathf.Min(num3, num4)); int num8 = Mathf.CeilToInt(Mathf.Max(num3, num4)); if (num6 <= num5 || num8 <= num7 || num6 < 0 || num5 >= outputWidth || num8 < 0 || num7 >= outputHeight) { continue; } Vector4 uv = val.vertex_BL.uv; Vector4 uv2 = val.vertex_TR.uv; float x = uv.x; float x2 = uv2.x; float y = uv.y; float y2 = uv2.y; Color32 val5 = val.color; if (val5.a == 0) { val5 = Color32.op_Implicit(((Graphic)tmp).color); } float num9 = 1f / (num2 - num); float num10 = 1f / (num4 - num3); for (int j = Mathf.Max(num7, 0); j < Mathf.Min(num8, outputHeight); j++) { float num11 = ((float)j + 0.5f - num3) * num10; int num12 = Mathf.Clamp((int)(Mathf.Lerp(y, y2, Mathf.Clamp01(num11)) * (float)height), 0, height - 1) * width; int num13 = j * outputWidth; for (int k = Mathf.Max(num5, 0); k < Mathf.Min(num6, outputWidth); k++) { float num14 = ((float)k + 0.5f - num) * num9; int num15 = Mathf.Clamp((int)(Mathf.Lerp(x, x2, Mathf.Clamp01(num14)) * (float)width), 0, width - 1); Color32 val6 = cachedAtlasPixels[num12 + num15]; int num16 = val6.a; if (val6.r > num16) { num16 = val6.r; } if (val6.g > num16) { num16 = val6.g; } if (val6.b > num16) { num16 = val6.b; } float num17 = (float)num16 / 255f; float num18 = Mathf.Clamp01((num17 - 0.46f) / 0.08f); float num19 = (drawOutline ? Mathf.Clamp01((num17 - 0.3f) / 0.08f) : num18); if (num19 <= 0f) { continue; } int num20 = (int)(num19 * (float)(int)val5.a); if (num20 > 0) { float num21 = (drawOutline ? (num18 / num19) : 1f); byte b = (byte)((float)(int)val5.r * num21); byte b2 = (byte)((float)(int)val5.g * num21); byte b3 = (byte)((float)(int)val5.b * num21); int num22 = num13 + k; Color32 val7 = output[num22]; if (num20 >= 255) { output[num22] = new Color32(b, b2, b3, byte.MaxValue); continue; } int num23 = 255 - num20; output[num22] = new Color32((byte)((b * num20 + val7.r * num23) / 255), (byte)((b2 * num20 + val7.g * num23) / 255), (byte)((b3 * num20 + val7.b * num23) / 255), byte.MaxValue); } } } } } private static Color32[] GetCachedAtlasPixels(Texture2D src) { if ((Object)(object)src == (Object)null) { return null; } if (_atlasCache.TryGetValue(src, out var value)) { return value; } Color32[] array = ReadPixelsSafe(src); _atlasCache[src] = array; return array; } private static Color32[] ReadPixelsSafe(Texture2D src) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown if ((Object)(object)src == (Object)null) { return null; } try { return src.GetPixels32(); } catch { RenderTexture temporary = RenderTexture.GetTemporary(((Texture)src).width, ((Texture)src).height, 0, (RenderTextureFormat)0); Graphics.Blit((Texture)(object)src, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)src).width, ((Texture)src).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)src).width, (float)((Texture)src).height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); Color32[] pixels = val.GetPixels32(); Object.Destroy((Object)val); return pixels; } } internal static void RasterizeTmpInto(Color32[] buf, int w, int h, TMP_Text tmp, bool forceMeshUpdate = true, bool drawOutline = false) { BlitText(buf, w, h, 0f, 0f, w, h, tmp, forceMeshUpdate, drawOutline); } internal static void BlitSpriteInto(Color32[] buf, int w, int h, Sprite sprite, Color32 tint, float centerPx, float centerPyBottom, float widthPx, float heightPx) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)sprite == (Object)null || buf == null || widthPx < 1f || heightPx < 1f) { return; } Rect textureRect = sprite.textureRect; int num = Mathf.RoundToInt(((Rect)(ref textureRect)).x); int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).y); int num3 = Mathf.RoundToInt(((Rect)(ref textureRect)).width); int num4 = Mathf.RoundToInt(((Rect)(ref textureRect)).height); if (num3 <= 0 || num4 <= 0) { return; } Color32[] cachedAtlasPixels = GetCachedAtlasPixels(sprite.texture); if (cachedAtlasPixels == null) { return; } int width = ((Texture)sprite.texture).width; int num5 = Mathf.Max(1, Mathf.RoundToInt(widthPx)); int num6 = Mathf.Max(1, Mathf.RoundToInt(heightPx)); int num7 = num5 / 2; int num8 = num6 / 2; int num9 = Mathf.RoundToInt(centerPx); int num10 = Mathf.RoundToInt(centerPyBottom); if (num9 + num7 < 0 || num9 - num7 >= w || num10 + num8 < 0 || num10 - num8 >= h) { return; } float num11 = (float)num3 / (float)num5; float num12 = (float)num4 / (float)num6; for (int i = 0; i < num6; i++) { int num13 = num10 - num8 + i; if (num13 < 0 || num13 >= h) { continue; } int num14 = Mathf.Clamp((int)((float)i * num12), 0, num4 - 1); int num15 = (num2 + num14) * width + num; int num16 = num13 * w; for (int j = 0; j < num5; j++) { int num17 = num9 - num7 + j; if (num17 < 0 || num17 >= w) { continue; } int num18 = Mathf.Clamp((int)((float)j * num11), 0, num3 - 1); Color32 val = cachedAtlasPixels[num15 + num18]; int num19 = val.a * tint.a / 255; if (num19 != 0) { int num20 = val.r * tint.r / 255; int num21 = val.g * tint.g / 255; int num22 = val.b * tint.b / 255; int num23 = num16 + num17; if (num19 >= 250) { buf[num23] = new Color32((byte)num20, (byte)num21, (byte)num22, byte.MaxValue); continue; } Color32 val2 = buf[num23]; int num24 = 255 - num19; buf[num23] = new Color32((byte)((num20 * num19 + val2.r * num24) / 255), (byte)((num21 * num19 + val2.g * num24) / 255), (byte)((num22 * num19 + val2.b * num24) / 255), byte.MaxValue); } } } } internal static void ClearLabelAtlasCache() { _atlasCache.Clear(); } private static byte[] Encode(Color32[] output, int outputWidth, int outputHeight) { //IL_0004: 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) //IL_0010: 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_001c: Expected O, but got Unknown //IL_0022: Expected O, but got Unknown Texture2D val = new Texture2D(outputWidth, outputHeight, (TextureFormat)3, false); val.SetPixels32(output); val.Apply(); byte[] result = ImageConversion.EncodeToPNG(val); Object.Destroy((Object)val); return result; } } internal sealed class MapStyleContext { private static readonly Color32 Parchment = new Color32((byte)203, (byte)155, (byte)87, byte.MaxValue); public int OutWidth; public int OutHeight; public bool Failed; public string Error; public Color32[] Result; private Plugin.MapStyleMode _style; private int _srcSize; private float _waterLevel; private Color32 _heathColor; private Color32[] _srcBiome; private float[] _srcHeight; private bool[] _srcExplored; private float _u0; private float _v0; private float _u1; private float _v1; private int _width; private int _height; private float _shadowScale; private Color32[] _biomeLayer; private Color32[] _biomeNearest; private Color32[] _heightLayer; private Color32[] _fogLayer; private float[] _shallowField; private static readonly Color32 BiomeEdge = new Color32((byte)35, (byte)25, (byte)18, (byte)235); private static readonly Color32 ShallowWater = new Color32((byte)155, (byte)215, (byte)230, byte.MaxValue); private float GrainTightness => (float)Mathf.Max(_width, _height) / 16f; public static MapStyleContext CaptureLayers(Rect uvRect, int outWidth, int outHeight) { //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) if (outWidth < 64 || outHeight < 64) { return null; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return null; } ZoneSystem instance2 = ZoneSystem.instance; if ((Object)(object)instance2 == (Object)null) { return null; } int textureSize = instance.m_textureSize; if (textureSize <= 0) { return null; } int num = textureSize * textureSize; float num2 = Mathf.Clamp01(((Rect)(ref uvRect)).xMin); float num3 = Mathf.Clamp01(((Rect)(ref uvRect)).yMin); float num4 = Mathf.Clamp01(((Rect)(ref uvRect)).xMax); float num5 = Mathf.Clamp01(((Rect)(ref uvRect)).yMax); if (num4 - num2 < 1E-05f || num5 - num3 < 1E-05f) { return null; } Texture2D mapTexture = instance.m_mapTexture; Texture2D heightTexture = instance.m_heightTexture; bool[] explored = instance.m_explored; if ((Object)(object)mapTexture == (Object)null || (Object)(object)heightTexture == (Object)null || explored == null) { return null; } if (explored.Length < num) { return null; } Color32[] pixels = mapTexture.GetPixels32(); if (pixels.Length < num) { return null; } Color[] pixels2 = heightTexture.GetPixels(); if (pixels2.Length < num) { return null; } float[] array = new float[num]; for (int i = 0; i < num; i++) { array[i] = pixels2[i].r; } bool[] exploredOthers = instance.m_exploredOthers; bool flag = exploredOthers != null && exploredOthers.Length >= num; bool[] array2 = new bool[num]; for (int j = 0; j < num; j++) { array2[j] = explored[j] || (flag && exploredOthers[j]); } ModLog.Info($"[NoMapDiscordAdditions] Map style: source {textureSize}px, viewport " + $"{(num4 - num2) * 100f:F0}%x{(num5 - num3) * 100f:F0}% -> {outWidth}x{outHeight} output."); return new MapStyleContext { _style = Plugin.MapStyle.Value, _srcSize = textureSize, _srcBiome = pixels, _srcHeight = array, _srcExplored = array2, _waterLevel = instance2.m_waterLevel, _heathColor = Color32.op_Implicit(instance.m_heathColor), _u0 = num2, _v0 = num3, _u1 = num4, _v1 = num5, OutWidth = outWidth, OutHeight = outHeight }; } public void RunPipeline() { try { _width = OutWidth; _height = OutHeight; _shadowScale = (float)Mathf.Max(_width, _height) / 2048f; _biomeLayer = SampleColour(_srcBiome, _srcSize); _biomeNearest = SampleColourNearest(_srcBiome, _srcSize); _heightLayer = SampleHeight(_srcHeight, _srcSize, _waterLevel); _fogLayer = SampleFog(_srcExplored, _srcSize); float num = (float)_width / Mathf.Max(1f, (_u1 - _u0) * (float)_srcSize); int radius = Mathf.Clamp(Mathf.RoundToInt(num * 0.35f), 1, 28); _biomeLayer = BlurBiomeColours(_biomeLayer, radius); _biomeLayer = BlurBiomeColours(_biomeLayer, radius); int radius2 = Mathf.Clamp(Mathf.RoundToInt(num * 0.8f), 2, 48); _shallowField = BuildShallowField(radius2); switch (_style) { case Plugin.MapStyleMode.Chart: Result = GenerateChartMap(); break; case Plugin.MapStyleMode.Topographical: Result = GenerateTopographicalMap(); break; case Plugin.MapStyleMode.Satellite: Result = GenerateSatelliteImage(); break; default: Result = GenerateOldMap(); break; } } catch (Exception ex) { Failed = true; Error = ex.Message; Result = null; } } private Color32[] SampleColour(Color32[] src, int srcSize) { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { float num = (_v0 + ((float)i + 0.5f) / (float)_height * (_v1 - _v0)) * (float)srcSize - 0.5f; int num2 = Mathf.Clamp(Mathf.FloorToInt(num), 0, srcSize - 1); int num3 = Mathf.Min(num2 + 1, srcSize - 1); float num4 = Mathf.Clamp01(num - (float)num2); int num5 = i * _width; for (int j = 0; j < _width; j++) { float num6 = (_u0 + ((float)j + 0.5f) / (float)_width * (_u1 - _u0)) * (float)srcSize - 0.5f; int num7 = Mathf.Clamp(Mathf.FloorToInt(num6), 0, srcSize - 1); int num8 = Mathf.Min(num7 + 1, srcSize - 1); float num9 = Mathf.Clamp01(num6 - (float)num7); Color val = Color32.op_Implicit(src[num2 * srcSize + num7]); Color val2 = Color32.op_Implicit(src[num2 * srcSize + num8]); Color val3 = Color32.op_Implicit(src[num3 * srcSize + num7]); Color val4 = Color32.op_Implicit(src[num3 * srcSize + num8]); array[num5 + j] = Color32.op_Implicit(Color.Lerp(Color.Lerp(val, val2, num9), Color.Lerp(val3, val4, num9), num4)); } } return array; } private Color32[] SampleColourNearest(Color32[] src, int srcSize) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { int num = Mathf.Clamp((int)((_v0 + ((float)i + 0.5f) / (float)_height * (_v1 - _v0)) * (float)srcSize), 0, srcSize - 1) * srcSize; int num2 = i * _width; for (int j = 0; j < _width; j++) { int num3 = Mathf.Clamp((int)((_u0 + ((float)j + 0.5f) / (float)_width * (_u1 - _u0)) * (float)srcSize), 0, srcSize - 1); array[num2 + j] = src[num + num3]; } } return array; } private Color32[] SampleHeight(float[] src, int srcSize, float waterLevel) { //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { float num = (_v0 + ((float)i + 0.5f) / (float)_height * (_v1 - _v0)) * (float)srcSize - 0.5f; int num2 = Mathf.Clamp(Mathf.FloorToInt(num), 0, srcSize - 1); int num3 = Mathf.Min(num2 + 1, srcSize - 1); float num4 = Mathf.Clamp01(num - (float)num2); int num5 = i * _width; for (int j = 0; j < _width; j++) { float num6 = (_u0 + ((float)j + 0.5f) / (float)_width * (_u1 - _u0)) * (float)srcSize - 0.5f; int num7 = Mathf.Clamp(Mathf.FloorToInt(num6), 0, srcSize - 1); int num8 = Mathf.Min(num7 + 1, srcSize - 1); float num9 = Mathf.Clamp01(num6 - (float)num7); float num10 = Mathf.Lerp(src[num2 * srcSize + num7], src[num2 * srcSize + num8], num9); float num11 = Mathf.Lerp(src[num3 * srcSize + num7], src[num3 * srcSize + num8], num9); float num12 = Mathf.Lerp(num10, num11, num4) - waterLevel; if (num12 > 0f) { array[num5 + j] = new Color32((byte)Mathf.Clamp(Mathf.RoundToInt(num12 / 512f * 255f), 0, 255), (byte)0, (byte)0, byte.MaxValue); } else { array[num5 + j] = new Color32((byte)0, (byte)0, (byte)Mathf.Clamp(Mathf.RoundToInt((0f - num12) / 256f * 255f), 0, 255), byte.MaxValue); } } } return array; } private Color32[] SampleFog(bool[] explored, int srcSize) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; Color32 val = default(Color32); ((Color32)(ref val))..ctor((byte)128, (byte)128, (byte)128, byte.MaxValue); for (int i = 0; i < _height; i++) { int num = Mathf.Clamp((int)((_v0 + ((float)i + 0.5f) / (float)_height * (_v1 - _v0)) * (float)srcSize), 0, srcSize - 1) * srcSize; int num2 = i * _width; for (int j = 0; j < _width; j++) { int num3 = Mathf.Clamp((int)((_u0 + ((float)j + 0.5f) / (float)_width * (_u1 - _u0)) * (float)srcSize), 0, srcSize - 1); if (!explored[num + num3]) { array[num2 + j] = val; } } } return array; } private Color32[] BlurBiomeColours(Color32[] src, int radius) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) if (radius < 1) { return src; } int num = _width * _height; float[] array = new float[num]; float[] array2 = new float[num]; float[] array3 = new float[num]; float[] array4 = new float[num]; for (int i = 0; i < _height; i++) { int num2 = i * _width; float num3 = 0f; float num4 = 0f; float num5 = 0f; float num6 = 0f; for (int j = -radius; j <= radius; j++) { int num7 = num2 + Mathf.Clamp(j, 0, _width - 1); if (_heightLayer[num7].b <= 0) { Color32 val = src[num7]; num3 += (float)(int)val.r; num4 += (float)(int)val.g; num5 += (float)(int)val.b; num6 += 1f; } } array[num2] = num3; array2[num2] = num4; array3[num2] = num5; array4[num2] = num6; for (int k = 1; k < _width; k++) { int num8 = num2 + Mathf.Clamp(k + radius, 0, _width - 1); int num9 = num2 + Mathf.Clamp(k - radius - 1, 0, _width - 1); if (_heightLayer[num8].b <= 0) { Color32 val2 = src[num8]; num3 += (float)(int)val2.r; num4 += (float)(int)val2.g; num5 += (float)(int)val2.b; num6 += 1f; } if (_heightLayer[num9].b <= 0) { Color32 val3 = src[num9]; num3 -= (float)(int)val3.r; num4 -= (float)(int)val3.g; num5 -= (float)(int)val3.b; num6 -= 1f; } int num10 = num2 + k; array[num10] = num3; array2[num10] = num4; array3[num10] = num5; array4[num10] = num6; } } Color32[] array5 = (Color32[])src.Clone(); for (int l = 0; l < _width; l++) { float num11 = 0f; float num12 = 0f; float num13 = 0f; float num14 = 0f; for (int m = -radius; m <= radius; m++) { int num15 = Mathf.Clamp(m, 0, _height - 1) * _width + l; num11 += array[num15]; num12 += array2[num15]; num13 += array3[num15]; num14 += array4[num15]; } if (_heightLayer[l].b <= 0 && num14 > 0f) { array5[l] = new Color32((byte)(num11 / num14), (byte)(num12 / num14), (byte)(num13 / num14), byte.MaxValue); } for (int n = 1; n < _height; n++) { int num16 = Mathf.Clamp(n + radius, 0, _height - 1) * _width + l; int num17 = Mathf.Clamp(n - radius - 1, 0, _height - 1) * _width + l; num11 += array[num16] - array[num17]; num12 += array2[num16] - array2[num17]; num13 += array3[num16] - array3[num17]; num14 += array4[num16] - array4[num17]; int num18 = n * _width + l; if (_heightLayer[num18].b <= 0 && num14 > 0f) { array5[num18] = new Color32((byte)(num11 / num14), (byte)(num12 / num14), (byte)(num13 / num14), byte.MaxValue); } } } return array5; } private float[] BuildShallowField(int radius) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; float[] array = new float[num]; for (int i = 0; i < num; i++) { array[i] = (IsOceanBiome(_biomeNearest[i]) ? 0f : 1f); } array = BoxBlur(array, radius); return BoxBlur(array, radius); } private Color32[] GenerateOldMap() { //IL_001d: 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_0037: Unknown result type (might be due to invalid IL or missing references) Color32[] array = GenerateOceanTexture(_heightLayer, clear: false); Color32[] array2 = ReplaceColour(_biomeLayer, new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue), Parchment); array2 = OverlayTexture(array2, array); Color32[] solidColour = GetSolidColour(Parchment); array2 = LerpTextures(array2, solidColour); array2 = LerpTextures(array2, solidColour); array2 = LerpTextures(array2, solidColour); array2 = AddPerlinNoise(array2, GrainTightness, 16f); Color32[] array3 = GenerateContourMap(_heightLayer, 8, 128); array2 = OverlayTexture(array2, array3); Color32[] array4 = StylizeFog(_fogLayer); array2 = OverlayTexture(array2, array4); return SmoothImage(array2); } private Color32[] GenerateChartMap() { //IL_001d: 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_0037: Unknown result type (might be due to invalid IL or missing references) Color32[] array = GenerateOceanTexture(_heightLayer, clear: false); Color32[] array2 = ReplaceColour(_biomeLayer, new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue), Parchment); array2 = OverlayTexture(array2, array); Color32[] solidColour = GetSolidColour(Parchment); array2 = LerpTextures(array2, solidColour); array2 = AddPerlinNoise(array2, GrainTightness, 16f); Color32[] array3 = GenerateContourMap(_heightLayer, 10, 128); array2 = OverlayTexture(array2, array3); Color32[] array4 = StylizeFog(_fogLayer); return OverlayTexture(array2, array4); } private Color32[] GenerateTopographicalMap() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Color32[] input = GenerateOceanTexture(_heightLayer, clear: true); input = AddPerlinNoise(input, GrainTightness / 16f, 64f); Color32[] input2 = CreateSand(); input2 = ReplaceColour(input2, new Color32((byte)51, (byte)51, (byte)51, byte.MaxValue), new Color32((byte)65, (byte)75, (byte)70, byte.MaxValue)); Color32[] array = OverlayTexture(input2, input); Color32[] array2 = CreateShadowMap(_heightLayer, 23); array = DarkenTextureLinear(array, 20); Color32[] array3 = GenerateContourMap(_heightLayer, 8, 128); array = OverlayTexture(array, array2); array = OverlayTexture(array, array3); Color32[] array4 = StylizeFog(_fogLayer); array = OverlayTexture(array, array4); return SmoothImage(array); } private Color32[] GenerateSatelliteImage() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Color32[] input = GenerateOceanTexture(_heightLayer, clear: true); input = AddPerlinNoise(input, GrainTightness / 16f, 64f); Color32[] input2 = CreateSand(); input2 = ReplaceColour(input2, new Color32((byte)51, (byte)51, (byte)51, byte.MaxValue), new Color32((byte)65, (byte)75, (byte)70, byte.MaxValue)); Color32[] array = OverlayTexture(input2, input); Color32[] array2 = CreateShadowMap(_heightLayer, 23); array = DarkenTextureLinear(array, 20); array = OverlayTexture(array, array2); Color32[] array3 = StylizeFog(_fogLayer); array = OverlayTexture(array, array3); return SmoothImage(array); } private Color32[] GenerateOceanTexture(Color32[] height, bool clear) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_018e: 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) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { int num = Mathf.RoundToInt((_v0 + ((float)i + 0.5f) / (float)_height * (_v1 - _v0)) * 256f) - 128; int num2 = i * _width; for (int j = 0; j < _width; j++) { int num3 = num2 + j; if (height[num3].b > 0) { int num4 = Mathf.RoundToInt((_u0 + ((float)j + 0.5f) / (float)_width * (_u1 - _u0)) * 256f) - 128; int num5 = num * num / 128 + num4 * num4 / 512; Color32 val = ((num < 0) ? new Color32((byte)(10 + num5), (byte)(136 - num5 / 4), (byte)193, byte.MaxValue) : new Color32((byte)(10 + num5 / 2), (byte)136, (byte)(193 - num5 / 2), byte.MaxValue)); float num6 = _shallowField[num3]; if (num6 > 0f) { val = Color32.Lerp(val, ShallowWater, 0.5f * num6); } if (clear) { int num7 = Mathf.Min(height[num3].b * 16 + 128, 255); array[num3] = new Color32(val.r, val.g, val.b, (byte)num7); } else { array[num3] = new Color32(val.r, val.g, val.b, byte.MaxValue); } } } } return array; } private Color32[] CreateSand() { //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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_005a: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; Color32[] array = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { if (_heightLayer[i].b > 0) { Color32 val = _biomeLayer[i]; if (val.r != 0 && val.g != 0 && val.b != 0) { array[i] = _heathColor; } } else { array[i] = _biomeLayer[i]; } } return array; } private Color32[] ReplaceColour(Color32[] input, Color32 from, Color32 to) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[input.Length]; for (int i = 0; i < input.Length; i++) { Color32 val = input[i]; array[i] = ((val.r == from.r && val.g == from.g && val.b == from.b) ? to : val); } return array; } private Color32[] GetSolidColour(Color32 colour) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; Color32[] array = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { array[i] = colour; } return array; } private Color32[] OverlayTexture(Color32[] array1, Color32[] array2) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; Color32[] array3 = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { Color val = Color32.op_Implicit(array1[i]); Color val2 = Color32.op_Implicit(array2[i]); float a = val2.a; float a2 = val.a; Color val3 = Color.Lerp(val, val2, a); val3.a = Mathf.Min(a + a2, 1f); array3[i] = Color32.op_Implicit(val3); } return array3; } private Color32[] LerpTextures(Color32[] array1, Color32[] array2) { //IL_0097: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; Color32[] array3 = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { int num2 = array2[i].a - array1[i].a; int num3 = Mathf.Min(array1[i].a + array2[i].a, 255); int num4 = Mathf.Max((int)array1[i].a, (int)array2[i].a) * 2; float num5 = ((num4 == 0) ? 0.5f : ((float)num2 / (float)num4 + 0.5f)); Color32 val = Color32.Lerp(array1[i], array2[i], num5); val.a = (byte)num3; array3[i] = val; } return array3; } private Color32[] DarkenTextureLinear(Color32[] array, byte d) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0041: 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_0056: 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) int num = _width * _height; Color32[] array2 = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { Color32 val = array[i]; array2[i] = new Color32((byte)Mathf.Max(val.r - d, 0), (byte)Mathf.Max(val.g - d, 0), (byte)Mathf.Max(val.b - d, 0), val.a); } return array2; } private Color32[] AddPerlinNoise(Color32[] input, float tightness, float damping) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { for (int j = 0; j < _width; j++) { int num = i * _width + j; Color val = Color32.op_Implicit(input[num]); float num2 = Mathf.PerlinNoise((float)i / tightness, (float)j / tightness); num2 = (num2 - 0.5f) / damping; array[num] = Color32.op_Implicit(new Color(val.r + num2, val.g + num2, val.b + num2, val.a)); } } return array; } private Color32[] GetPerlin(float tightness, float damping) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { for (int j = 0; j < _width; j++) { float num = Mathf.PerlinNoise((float)i / tightness, (float)j / tightness); num = (num - 0.5f) / damping + 0.5f; array[i * _width + j] = Color32.op_Implicit(new Color(num, num, num, 0.2f)); } } return array; } private Color32[] StylizeFog(Color32[] fog) { //IL_0089: 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) Color32[] perlin = GetPerlin(GrainTightness, 16f); int num = _width * _height; Color32[] array = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { if (fog[i].a > 0) { array[i] = new Color32((byte)(203 + (perlin[i].r - 128)), (byte)(155 + (perlin[i].g - 128)), (byte)(87 + (perlin[i].b - 128)), byte.MaxValue); } } return array; } private Color32[] CreateShadowMap(Color32[] heightmap, byte intensity) { Color32[] array = CreateHardShadowMap(heightmap, intensity); Color32[] array2 = CreateSoftShadowMap(heightmap); return LerpTextures(array2, array); } private Color32[] CreateSoftShadowMap(Color32[] input) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[_width * _height]; for (int i = 0; i < _height; i++) { for (int j = 0; j < _width; j++) { int num = 0; if (i < _height - 1) { num = (int)((float)(input[i * _width + j].r - input[(i + 1) * _width + j].r) * _shadowScale * 8f); } byte b = (byte)Mathf.Abs(num); byte b2 = (byte)((num >= 0) ? 255u : 0u); array[i * _width + j] = new Color32(b2, b2, b2, b); } } return array; } private Color32[] CreateHardShadowMap(Color32[] input, byte intensity) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; Color32[] array = (Color32[])(object)new Color32[num]; bool[] array2 = new bool[num]; for (int num2 = _height - 1; num2 > -1; num2--) { for (int i = 0; i < _width; i++) { int num3 = num2 * _width + i; if (!array2[num3]) { array[num3] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)0); for (int j = 1; num2 - j > 0 && (float)(int)input[num3].r * _shadowScale > (float)(int)input[(num2 - j) * _width + i].r * _shadowScale + (float)(j * 2); j++) { array2[(num2 - j) * _width + i] = true; } } else { array[num3] = new Color32((byte)0, (byte)0, (byte)0, intensity); } } } return array; } private Color32[] GenerateContourMap(Color32[] start, int graduations, byte alpha) { //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; Color32[] array = (Color32[])(object)new Color32[num]; Color32[] array2 = (Color32[])(object)new Color32[num]; for (int i = 0; i < num; i++) { int num2 = start[i].r + graduations; if (num2 > 255) { num2 = 255; } if (start[i].b > 0) { num2 = 0; } array[i].r = (byte)num2; } for (int j = 1; j < _height - 1; j++) { int num3 = j * _width; for (int k = 1; k < _width - 1; k++) { int num4 = num3 + k; int num5 = array[num4].r / graduations; for (int l = -1; l < 2; l++) { int num6 = l * _width; for (int m = -1; m < 2; m++) { if (l == 0 && m == 0) { continue; } int num7 = array[num4 + num6 + m].r / graduations; if (num7 < num5) { byte b = alpha; if ((num5 - 1) / 5 == (num7 - 1) / 5) { b /= 2; } if (num7 == 0) { b = alpha; } if (l == 0 || m == 0 || array2[num4].a == b) { array2[num4] = new Color32((byte)0, (byte)0, (byte)0, b); break; } array2[num4] = new Color32((byte)0, (byte)0, (byte)0, (byte)(b / 2)); } } } } } return array2; } private Color32[] GenerateBiomeEdges(Color32[] biome) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) int num = _width * _height; float[] array = new float[num]; for (int i = 1; i < _height - 1; i++) { int num2 = i * _width; for (int j = 1; j < _width - 1; j++) { int num3 = num2 + j; if (_heightLayer[num3].b <= 0) { Color32 c = biome[num3]; if (LandBiomeDiffers(c, biome, num3 - 1) || LandBiomeDiffers(c, biome, num3 + 1) || LandBiomeDiffers(c, biome, num3 - _width) || LandBiomeDiffers(c, biome, num3 + _width)) { array[num3] = 1f; } } } } array = BoxBlur(array, 2); array = BoxBlur(array, 2); float num4 = 0f; for (int k = 0; k < num; k++) { if (array[k] > num4) { num4 = array[k]; } } if (num4 <= 0f) { return (Color32[])(object)new Color32[num]; } float num5 = 1f / num4; Color32[] array2 = (Color32[])(object)new Color32[num]; for (int l = 0; l < num; l++) { if (!(array[l] <= 0f)) { float num6 = Mathf.Clamp01((array[l] * num5 - 0.5f) / 0.4f); num6 = num6 * num6 * (3f - 2f * num6); if (!(num6 <= 0f)) { array2[l] = new Color32(BiomeEdge.r, BiomeEdge.g, BiomeEdge.b, (byte)(num6 * (float)(int)BiomeEdge.a)); } } } return array2; } private float[] BoxBlur(float[] src, int radius) { int num = _width * _height; float num2 = 1f / (float)(2 * radius + 1); float[] array = new float[num]; for (int i = 0; i < _height; i++) { int num3 = i * _width; for (int j = 0; j < _width; j++) { float num4 = 0f; for (int k = -radius; k <= radius; k++) { num4 += src[num3 + Mathf.Clamp(j + k, 0, _width - 1)]; } array[num3 + j] = num4 * num2; } } float[] array2 = new float[num]; for (int l = 0; l < _height; l++) { for (int m = 0; m < _width; m++) { float num5 = 0f; for (int n = -radius; n <= radius; n++) { num5 += array[Mathf.Clamp(l + n, 0, _height - 1) * _width + m]; } array2[l * _width + m] = num5 * num2; } } return array2; } private bool LandBiomeDiffers(Color32 c, Color32[] biome, int nIdx) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002c: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (_heightLayer[nIdx].b > 0) { return false; } Color32 val = biome[nIdx]; if (c.r == val.r && c.g == val.g) { return c.b != val.b; } return true; } private static bool IsOceanBiome(Color32 c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (c.r == byte.MaxValue && c.g == byte.MaxValue) { return c.b == byte.MaxValue; } return false; } private Color32[] SmoothImage(Color32[] input) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])input.Clone(); for (int i = 1; i < _height - 1; i++) { for (int j = 1; j < _width - 1; j++) { int num = i * _width + j; Color32 val = input[num - _width]; Color32 val2 = input[num + 1]; Color32 val3 = input[num + _width]; Color32 val4 = input[num - 1]; Color32 val5 = Color32.Lerp(val2, val4, 0.5f); Color32 val6 = Color32.Lerp(val, val3, 0.5f); Color32 val7 = Color32.Lerp(val5, val6, 0.5f); array[num] = Color32.Lerp(input[num], val7, 0.5f); } } return array; } } public static class MapStyleRender { public static bool IsStyleActive() { if (Plugin.MapStyle != null) { return Plugin.MapStyle.Value != Plugin.MapStyleMode.None; } return false; } public static IEnumerator BuildAsync(Rect uvRect, int width, int height, Action onDone) { //IL_0007: 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 (!IsStyleActive()) { onDone(null); yield break; } MapStyleContext ctx; try { ctx = MapStyleContext.CaptureLayers(uvRect, width, height); } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Map style: layer capture failed: " + ex.Message); ctx = null; } if (ctx == null) { onDone(null); yield break; } Thread thread = new Thread(ctx.RunPipeline) { IsBackground = true, Name = "NMDA-MapStyle" }; thread.Start(); while (thread.IsAlive) { yield return null; } if (ctx.Failed || ctx.Result == null) { ModLog.Warn("[NoMapDiscordAdditions] Map style render failed, using normal capture" + (string.IsNullOrEmpty(ctx.Error) ? "." : (": " + ctx.Error))); onDone(null); yield break; } Texture2D obj; try { Texture2D val = new Texture2D(ctx.OutWidth, ctx.OutHeight, (TextureFormat)3, false) { wrapMode = (TextureWrapMode)1 }; val.SetPixels32(ctx.Result); val.Apply(false); obj = val; } catch (Exception ex2) { ModLog.Warn("[NoMapDiscordAdditions] Map style: texture upload failed: " + ex2.Message); obj = null; } onDone(obj); } } [HarmonyPatch] public static class MinimapPatch { [HarmonyPatch(typeof(Minimap), "Start")] [HarmonyAfter(new string[] { "ZenDragon.ZenMap" })] [HarmonyPostfix] private static void Minimap_Start_Postfix() { CaptureButton.Create(); MapCompileButtons.Create(); } [HarmonyPatch(typeof(Minimap), "ShowPointOnMap")] [HarmonyPostfix] private static void ShowPointOnMap_Postfix(Vector3 point) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (ModHelpers.EffectiveConfig.AllowCompileFromMapItems) { MapCompileSession.SetActiveTable(point); } } [HarmonyPatch(typeof(Minimap), "UpdateDynamicPins")] [HarmonyAfter(new string[] { "ZenDragon.ZenMap" })] [HarmonyPostfix] private static void UpdateDynamicPins_ForceCaptionsDuringCapture(Minimap __instance) { if (!PinCaptureFilter.s_forceShowLabels) { return; } List list = __instance?.m_pins; if (list == null) { return; } int count = list.Count; for (int i = 0; i < count; i++) { PinData val = list[i]; if (val == null) { continue; } PinNameData namePinData = val.m_NamePinData; GameObject val2 = ((namePinData != null) ? namePinData.PinNameGameObject : null); if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(val.m_name)) { PinNameData namePinData2 = val.m_NamePinData; TMP_Text val3 = ((namePinData2 != null) ? namePinData2.PinNameText : null); if ((!((Object)(object)val3 != (Object)null) || ((Behaviour)val3).enabled) && !val2.activeSelf) { val2.SetActive(true); } } } } [HarmonyPatch(typeof(Minimap), "SetMapMode")] [HarmonyPostfix] private static void SetMapMode_Postfix(MapMode mode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 bool num = (int)mode == 2; CaptureButton.SetVisible(num); MapCompileButtons.SetVisible(num); if (!num) { MapCompileSession.ClearActiveTable(); if (MapCompileResultPanel.IsVisible) { MapCompileResultPanel.HideKeepingResult(); } } else if (MapCompileSession.CurrentState == MapCompileSession.State.Reviewing && !MapCompileResultPanel.IsVisible && !MapCompileResultPanel.HasPendingResult) { MapCompileSession.ReturnToCompiling(); MapCompileButtons.SetVisible(visible: true); } } } internal static class ModHelpers { public static class EffectiveConfig { public static string WebhookUrl => Plugin.WebhookUrl?.Value; public static bool SpoilerImageData => Plugin.SpoilerImageData.Value; public static bool HideClouds => Plugin.HideClouds.Value; public static bool AllowCompileFromMapItems => Plugin.AllowCompileFromMapItems?.Value ?? true; public static string CompileMessageTemplate => Plugin.CompileMessageTemplate?.Value ?? "{player} compiled a map from {tileCount} cartography tables."; public static string MessageTemplate => Plugin.MessageTemplate?.Value ?? "{player} shared a map update from {biome}{table}"; public static bool EnableCompileMapSharing => Plugin.EnableCompileMapSharing?.Value ?? true; public static string CompileShareMessageTemplate => Plugin.CompileShareMessageTemplate?.Value ?? "{player} shared {tileCount} map tile(s) for compile mode."; } public struct SavedLighting { public bool Active; public Vector4 SunDir; public Color SunColor; public Color Ambient; public Color SunFogColor; } public struct SavedShaderProp { public string Name; public ShaderPropertyType Type; public Texture Tex; public float Float; public Color Color; public Vector4 Vec; } private static readonly int _idSunDir = Shader.PropertyToID("_SunDir"); private static readonly int _idSunColor = Shader.PropertyToID("_SunColor"); private static readonly int _idAmbient = Shader.PropertyToID("_AmbientColor"); private static readonly int _idSunFogColor = Shader.PropertyToID("_SunFogColor"); public static SavedLighting OverrideLightingToNoon() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_004a: 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) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) SavedLighting savedLighting = default(SavedLighting); savedLighting.Active = true; savedLighting.SunDir = Shader.GetGlobalVector(_idSunDir); savedLighting.SunColor = Shader.GetGlobalColor(_idSunColor); savedLighting.Ambient = Shader.GetGlobalColor(_idAmbient); savedLighting.SunFogColor = Shader.GetGlobalColor(_idSunFogColor); SavedLighting result = savedLighting; Color val = default(Color); ((Color)(ref val))..ctor(0.8f, 0.8f, 0.8f, 1f); Color val2 = Color.white * 1.2f; Color white = Color.white; Vector3 val3 = -(Quaternion.Euler(-30f, 0f, 0f) * Quaternion.Euler(0f, -90f, 0f) * Quaternion.Euler(90f, 0f, 0f) * Vector3.forward); Shader.SetGlobalVector(_idSunDir, new Vector4(val3.x, val3.y, val3.z, 0f)); Shader.SetGlobalColor(_idSunColor, val2); Shader.SetGlobalColor(_idAmbient, val); Shader.SetGlobalColor(_idSunFogColor, white); return result; } public static void RestoreLighting(SavedLighting saved) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (saved.Active) { Shader.SetGlobalVector(_idSunDir, saved.SunDir); Shader.SetGlobalColor(_idSunColor, saved.SunColor); Shader.SetGlobalColor(_idAmbient, saved.Ambient); Shader.SetGlobalColor(_idSunFogColor, saved.SunFogColor); } } public static List SuppressShaderPropsContaining(Material mat, string substring) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected I4, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if ((Object)(object)mat == (Object)null || (Object)(object)mat.shader == (Object)null) { return list; } Shader shader = mat.shader; int propertyCount = shader.GetPropertyCount(); for (int i = 0; i < propertyCount; i++) { string propertyName = shader.GetPropertyName(i); if (!string.IsNullOrEmpty(propertyName) && propertyName.IndexOf(substring, StringComparison.OrdinalIgnoreCase) >= 0) { ShaderPropertyType propertyType = shader.GetPropertyType(i); SavedShaderProp savedShaderProp = default(SavedShaderProp); savedShaderProp.Name = propertyName; savedShaderProp.Type = propertyType; SavedShaderProp item = savedShaderProp; switch ((int)propertyType) { case 4: item.Tex = mat.GetTexture(propertyName); mat.SetTexture(propertyName, (Texture)(object)Texture2D.blackTexture); break; case 2: case 3: item.Float = mat.GetFloat(propertyName); mat.SetFloat(propertyName, 0f); break; case 0: item.Color = mat.GetColor(propertyName); mat.SetColor(propertyName, new Color(0f, 0f, 0f, 0f)); break; case 1: item.Vec = mat.GetVector(propertyName); mat.SetVector(propertyName, Vector4.zero); break; } list.Add(item); } } return list; } public static void RestoreShaderProps(Material mat, List saved) { //IL_001f: 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_003f: Expected I4, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mat == (Object)null || saved == null) { return; } foreach (SavedShaderProp item in saved) { ShaderPropertyType type = item.Type; switch ((int)type) { case 4: mat.SetTexture(item.Name, item.Tex); break; case 2: case 3: mat.SetFloat(item.Name, item.Float); break; case 0: mat.SetColor(item.Name, item.Color); break; case 1: mat.SetVector(item.Name, item.Vec); break; } } } } internal static class ModLog { private static bool Enabled => Plugin.EnableLogs?.Value ?? false; public static void Info(string message) { if (Enabled) { Debug.Log((object)message); } } public static void Warn(string message) { if (Enabled) { Debug.LogWarning((object)message); } } public static void Error(string message) { if (Enabled) { Debug.LogError((object)message); } } } internal static class PinCaptureFilter { internal struct State { public List<(Image img, bool wasEnabled)> DisabledImages; public List<(TMP_Text tmp, bool wasEnabled)> DisabledTexts; public List<(TMP_Text tmp, string original)> StrippedTexts; public List<(GameObject go, bool wasActive)> ForcedCaptionGOs; } private static readonly Regex s_richText = new Regex("<[^>]+>", RegexOptions.Compiled); internal static bool s_armedIncludeFiltered; internal static bool s_forceShowLabels; internal static void ArmFromCurrentInput() { s_armedIncludeFiltered = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); } private static bool ConsumeArmedIncludeFiltered() { bool result = s_armedIncludeFiltered; s_armedIncludeFiltered = false; return result; } internal static State Apply(bool includeFilteredPins = false) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Invalid comparison between Unknown and I4 includeFilteredPins = includeFilteredPins || ConsumeArmedIncludeFiltered(); State state = default(State); state.DisabledImages = new List<(Image, bool)>(); state.DisabledTexts = new List<(TMP_Text, bool)>(); state.StrippedTexts = new List<(TMP_Text, string)>(); state.ForcedCaptionGOs = new List<(GameObject, bool)>(); State state2 = state; s_forceShowLabels = true; List list = Minimap.instance?.m_pins; if (list == null) { return state2; } int count = list.Count; for (int i = 0; i < count; i++) { PinData val = list[i]; if (val == null) { continue; } if (!includeFilteredPins && ((int)val.m_type == 10 || (int)val.m_type == 4)) { DisableImage(state2, val.m_iconElement); State state3 = state2; PinNameData namePinData = val.m_NamePinData; DisableText(state3, (namePinData != null) ? namePinData.PinNameText : null); continue; } PinNameData namePinData2 = val.m_NamePinData; TMP_Text val2 = ((namePinData2 != null) ? namePinData2.PinNameText : null); if ((Object)(object)val2 != (Object)null && !string.IsNullOrEmpty(val2.text) && val2.text.IndexOf('<') >= 0) { state2.StrippedTexts.Add((val2, val2.text)); val2.text = s_richText.Replace(val2.text, string.Empty).Trim(); } PinNameData namePinData3 = val.m_NamePinData; GameObject val3 = ((namePinData3 != null) ? namePinData3.PinNameGameObject : null); if ((Object)(object)val3 != (Object)null && !string.IsNullOrEmpty(val.m_name)) { bool activeSelf = val3.activeSelf; if (!activeSelf) { val3.SetActive(true); } state2.ForcedCaptionGOs.Add((val3, activeSelf)); } } return state2; } internal static void Restore(State state) { s_forceShowLabels = false; if (state.DisabledImages != null) { for (int i = 0; i < state.DisabledImages.Count; i++) { var (val, enabled) = state.DisabledImages[i]; if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = enabled; } } } if (state.DisabledTexts != null) { for (int j = 0; j < state.DisabledTexts.Count; j++) { var (val2, enabled2) = state.DisabledTexts[j]; if ((Object)(object)val2 != (Object)null) { ((Behaviour)val2).enabled = enabled2; } } } if (state.StrippedTexts != null) { for (int k = 0; k < state.StrippedTexts.Count; k++) { var (val3, text) = state.StrippedTexts[k]; if ((Object)(object)val3 != (Object)null) { val3.text = text; } } } if (state.ForcedCaptionGOs == null) { return; } for (int l = 0; l < state.ForcedCaptionGOs.Count; l++) { var (val4, flag) = state.ForcedCaptionGOs[l]; if ((Object)(object)val4 != (Object)null && !flag) { val4.SetActive(false); } } } private static void DisableImage(State state, Image img) { if (!((Object)(object)img == (Object)null)) { bool enabled = ((Behaviour)img).enabled; if (enabled) { ((Behaviour)img).enabled = false; } state.DisabledImages.Add((img, enabled)); } } private static void DisableText(State state, TMP_Text tmp) { if (!((Object)(object)tmp == (Object)null)) { bool enabled = ((Behaviour)tmp).enabled; if (enabled) { ((Behaviour)tmp).enabled = false; } state.DisabledTexts.Add((tmp, enabled)); } } } [BepInPlugin("com.virtualbjorn.nomapdiscordadditions", "NoMapDiscordAdditions", "1.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public enum MapStyleMode { None, OldMap, Chart, Topographical, Satellite } public enum OutputImageFormat { JPEG, IndexedPNG } public enum SendingOp { None, Send, Copy } public const string PluginGUID = "com.virtualbjorn.nomapdiscordadditions"; public const string PluginName = "NoMapDiscordAdditions"; public const string PluginVersion = "1.1.1"; public static ConfigEntry WebhookUrl; public static ConfigEntry MessageTemplate; public static ConfigEntry SendKey; public static ConfigEntry CopyKey; public static ConfigEntry MapStyle; public static ConfigEntry OutputFormat; public static ConfigEntry JpegQuality; public static ConfigEntry IndexedPngColors; public static ConfigEntry SpoilerImageData; public static ConfigEntry HideClouds; public static ConfigEntry ShowBiomeText; public static ConfigEntry NormalizeCaptureLighting; public static ConfigEntry CompileMessageTemplate; public static ConfigEntry EnableCompileMapSharing; public static ConfigEntry AllowCompileFromMapItems; public static ConfigEntry CompileShareMessageTemplate; public static ConfigEntry EnableLogs; private Harmony _harmony; private bool _sendingInProgressBacking; private const int CaptureMaxDim = 8192; private const uint CF_UNICODETEXT = 13u; private const uint GMEM_MOVEABLE = 2u; private const uint CF_DIB = 8u; public static Plugin Instance { get; private set; } public static SendingOp CurrentSendingOp { get; private set; } public static bool IsSendingInProgress { get; private set; } private bool _sendingInProgress { get { return _sendingInProgressBacking; } set { if (_sendingInProgressBacking == value) { return; } _sendingInProgressBacking = value; IsSendingInProgress = value; if (!value) { CurrentSendingOp = SendingOp.None; } try { Plugin.SendingStateChanged?.Invoke(); } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] SendingStateChanged listener threw: " + ex.Message); } } } public static event Action SendingStateChanged; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Expected O, but got Unknown //IL_0436: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Invalid comparison between Unknown and I4 Instance = this; ConfigFile config = ((BaseUnityPlugin)this).Config; ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { Browsable = false }; WebhookUrl = ConfigFileExtensions.BindConfig(config, "Discord", "Webhook URL", "", "Discord webhook URL used to send captured map images.", true, (int?)null, (AcceptableValueBase)null, (Action)null, val); MessageTemplate = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Discord", "Message Template", "{player} shared a map update from {biome}{table}", "Message sent with each screenshot. Supports {player}, {biome} and {table} placeholders. {table} expands to \" — \" using the name of the map pin on the cartography table (empty when reading a map item, or no named pin sits on the table).", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); SendKey = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Controls", "Send Key", (KeyCode)291, "Press while large map is open to capture and send to Discord.", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); CopyKey = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Controls", "Copy Key", (KeyCode)292, "Press while large map is open to capture and copy to the clipboard.", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); EnableLogs = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "General", "Enable Logs", false, "If true, this mod prints info/warning/error messages to the BepInEx console and Player.log. Defaults to false to keep logs quiet during normal play; turn on if you need to investigate a problem.", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); SpoilerImageData = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Discord", "Spoiler Image Data", false, "If enabled, sent map image attachments are tagged as Discord spoilers.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); HideClouds = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "UI", "Hide Clouds", true, "If enabled, cloud overlay is suppressed while capturing maps.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); ShowBiomeText = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "UI", "Show Biome Text", false, "If enabled, the biome label is included in captured map images. Client-only.", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); NormalizeCaptureLighting = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "General", "Normalize Capture Lighting", true, "If enabled, captures render the map as if at noon regardless of the in-game time of day. Keeps brightness consistent so a multi-tile compiled map doesn't show dark/light seams between tiles captured at different times, and gives SEND/COPY a stable look across an in-game day. Applies to every capture path (texture and screen, SEND/COPY and compile). Disable to have captures reflect the live time of day. Client-only.", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); MapStyle = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Map Style", "Style", MapStyleMode.None, "Optional stylized rendering for SEND / COPY map captures, reconstructed from Valheim's own map data — explored areas show detail, unexplored areas stay fogged. None: the normal in-game map look. Old Map: aged-parchment chart (biome wash, Perlin grain, contour & biome-edge lines). Chart: flat topographic chart with contour & biome-edge lines. Topographical: shaded-relief terrain with hillshading, contours & biome-edge lines. Satellite: naturalistic shaded terrain, no line work. A styled capture always uses the texture-capture path and is not applied to MAP COMPILE tiles. Client-only.", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); OutputFormat = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Output", "Output Format", OutputImageFormat.JPEG, "Image format used for the SAVE button (compiled map → disk) AND for SEND TO DISCORD. COPY (clipboard) always emits an indexed PNG regardless of this setting so paste targets get a real PNG with crisp text. JPEG: lossy DCT at the configured quality (~5-8× smaller than a lossless PNG; can blur sharp pin-label edges below quality ~85). IndexedPNG: 8bpp palette via median-cut + Floyd-Steinberg dither at the configured colour count (~5× smaller; keeps label edges crisp because there's no DCT — best fit for typical maps).", false, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config2 = ((BaseUnityPlugin)this).Config; AcceptableValueBase val2 = (AcceptableValueBase)(object)new AcceptableValueRange(50, 100); JpegQuality = ConfigFileExtensions.BindConfig(config2, "Output", "JPEG Quality", 88, "JPEG encoder quality used when Output Format = JPEG. Higher = larger file, less ringing around hard edges. 88 keeps pin captions readable; values below 80 noticeably blur text.", false, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); ConfigFile config3 = ((BaseUnityPlugin)this).Config; val2 = (AcceptableValueBase)(object)new AcceptableValueRange(16, 256); IndexedPngColors = ConfigFileExtensions.BindConfig(config3, "Output", "Indexed PNG Colours", 64, "Palette size used for indexed-PNG encoding — applies to Output Format = IndexedPNG and to ALL clipboard COPY output. Maps have ~6 dominant colours (water, grass, dirt, ice, swamp, fog) so 32-64 is usually indistinguishable from full-colour; 128-256 is overkill for a map but smooths gradient regions if you have Map Style enabled.", false, (int?)null, val2, (Action)null, (ConfigurationManagerAttributes)null); CompileMessageTemplate = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Map Compile", "Compile Message Template", "{player} compiled a map from {tileCount} cartography tables.", "Discord message template used when SEND TO DISCORD is clicked from the compile result panel. Supports {player} and {tileCount} placeholders.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); EnableCompileMapSharing = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Map Compile", "Enable Map Sharing", true, "If enabled, compile mode can share its tiles with teammates: the SHARE/EXPORT button is shown and the incoming share folder is auto-imported into the active session. Disable to keep compile mode purely local — the SHARE/EXPORT button is hidden and no incoming tiles are imported.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); AllowCompileFromMapItems = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Map Compile", "Allow From Map Items", true, "If enabled, compile mode is also available when the map is opened from a portable map item (e.g. ZenMap parchment), not just from a cartography table. Tiles added while reading a map item dedup by the item's read position. Disable to restrict compile mode to cartography tables only.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); CompileShareMessageTemplate = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Map Compile", "Share Message Template", "{player} shared {tileCount} map tile(s) for compile mode. Save the attached PNG(s) into BepInEx/config/NoMapDiscordAdditions/compile-share/incoming and they auto-import next time you open the map.", "Discord message sent (once, with the first attachment) when SHARE TILES is clicked in compile mode. Supports {player} and {tileCount} placeholders.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); WebhookUrl.SettingChanged += delegate { CaptureButton.RefreshEnabledState(); }; ShowBiomeText.SettingChanged += delegate { CaptureButton.RefreshBiomeToggleState(); }; SendKey.SettingChanged += delegate { CaptureButton.RefreshHotkeyLabels(); }; CopyKey.SettingChanged += delegate { CaptureButton.RefreshHotkeyLabels(); }; _harmony = new Harmony("com.virtualbjorn.nomapdiscordadditions"); _harmony.PatchAll(typeof(CartographyTablePatch)); _harmony.PatchAll(typeof(MinimapPatch)); if ((Object)(object)Minimap.instance != (Object)null) { bool visible = (int)Minimap.instance.m_mode == 2; CaptureButton.Create(); CaptureButton.SetVisible(visible); MapCompileButtons.Create(); MapCompileButtons.SetVisible(visible); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"NoMapDiscordAdditions v1.1.1 loaded."); } private void Update() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!_sendingInProgress && !((Object)(object)Minimap.instance == (Object)null) && (int)Minimap.instance.m_mode == 2) { if (Input.GetKeyDown(SendKey.Value)) { TriggerDiscordSend(); } else if (Input.GetKeyDown(CopyKey.Value)) { TriggerClipboardCopy(); } } } public void TriggerClipboardCopy() { if (!_sendingInProgress) { CurrentSendingOp = SendingOp.Copy; _sendingInProgress = true; ((MonoBehaviour)this).StartCoroutine(CaptureAndCopy()); } } public static MapCompositor.EncodeOptions GetEncodeOptions() { MapCompositor.EncodeOptions @default = MapCompositor.EncodeOptions.Default; @default.Format = (((OutputFormat?.Value ?? OutputImageFormat.JPEG) != OutputImageFormat.IndexedPNG) ? MapCompositor.EncodeFormat.Jpeg : MapCompositor.EncodeFormat.IndexedPng); if (JpegQuality != null) { @default.JpegQuality = JpegQuality.Value; } if (IndexedPngColors != null) { @default.IndexedPngColors = IndexedPngColors.Value; } return @default; } public static MapCompositor.EncodeOptions GetCopyEncodeOptions() { MapCompositor.EncodeOptions @default = MapCompositor.EncodeOptions.Default; @default.Format = MapCompositor.EncodeFormat.Jpeg; if (JpegQuality != null) { @default.JpegQuality = JpegQuality.Value; } return @default; } private IEnumerator CaptureAndCopy() { try { yield return (object)new WaitForEndOfFrame(); byte[] imageData = null; yield return CaptureTextureWithStyle(delegate(byte[] d) { imageData = d; }); imageData = MapCompositor.Recode(imageData, GetCopyEncodeOptions(), 8192); CopyToClipboard(imageData); } finally { _sendingInProgress = false; } } public void CopyBytesToClipboard(byte[] pngData) { pngData = MapCompositor.Recode(pngData, GetCopyEncodeOptions(), 8192); CopyToClipboard(pngData); } public static bool CopyTextToClipboard(string text) { if (text == null) { text = string.Empty; } byte[] bytes = Encoding.Unicode.GetBytes(text); byte[] array = new byte[bytes.Length + 2]; Buffer.BlockCopy(bytes, 0, array, 0, bytes.Length); IntPtr intPtr = IntPtr.Zero; try { intPtr = AllocGlobal(array); if (!OpenClipboard(IntPtr.Zero)) { GlobalFree(intPtr); ModLog.Error("[NoMapDiscordAdditions] Text clipboard: OpenClipboard failed " + $"(error {Marshal.GetLastWin32Error()})."); return false; } EmptyClipboard(); IntPtr intPtr2 = SetClipboardData(13u, intPtr); CloseClipboard(); if (intPtr2 == IntPtr.Zero) { GlobalFree(intPtr); ModLog.Error("[NoMapDiscordAdditions] Text clipboard: SetClipboardData failed."); return false; } return true; } catch (Exception ex) { if (intPtr != IntPtr.Zero) { GlobalFree(intPtr); } ModLog.Error("[NoMapDiscordAdditions] Text clipboard error: " + ex.Message); return false; } } public void SendCompiledImage(byte[] pngData, int tileCount, Action onComplete = null) { if (_sendingInProgress) { onComplete?.Invoke(obj: false); return; } if (string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl)) { onComplete?.Invoke(obj: false); return; } if (pngData == null || pngData.Length == 0) { onComplete?.Invoke(obj: false); return; } _sendingInProgress = true; ((MonoBehaviour)this).StartCoroutine(SendCompiledImageCoroutine(pngData, tileCount, onComplete)); } private IEnumerator SendCompiledImageCoroutine(byte[] pngData, int tileCount, Action onComplete) { bool ok = false; try { Player localPlayer = Player.m_localPlayer; string text = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : "unknown"); string message = ModHelpers.EffectiveConfig.CompileMessageTemplate.Replace("{player}", text).Replace("{tileCount}", tileCount.ToString()); string filename = BuildMapFileName(text, $"compiled_{tileCount}t"); if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Sending compiled map to Discord...", 0, (Sprite)null); } pngData = MapCompositor.Recode(pngData, GetEncodeOptions()); yield return DiscordWebhook.SendImage(pngData, filename, message, ModHelpers.EffectiveConfig.SpoilerImageData); ok = true; } finally { _sendingInProgress = false; onComplete?.Invoke(ok); } } public void ShareCompileTiles() { if (_sendingInProgress || !ModHelpers.EffectiveConfig.EnableCompileMapSharing) { return; } List list = MapTileShare.PrepareExport(); if (list == null || list.Count == 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "No tiles to share.", 0, (Sprite)null); } return; } string text = MapTileShare.ShareOutDirForCurrentWorld(); if (string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl)) { Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, $"Saved {list.Count} shareable tile(s). Drag them into Discord from the compile-share/out folder.", 0, (Sprite)null); } ModLog.Info("[NoMapDiscordAdditions] Shareable tiles written to " + text); } else { _sendingInProgress = true; ((MonoBehaviour)this).StartCoroutine(ShareCompileTilesCoroutine(list)); } } private IEnumerator ShareCompileTilesCoroutine(List outgoing) { try { Player player = Player.m_localPlayer; string newValue = (((Object)(object)player != (Object)null) ? player.GetPlayerName() : "unknown"); string message = ModHelpers.EffectiveConfig.CompileShareMessageTemplate.Replace("{player}", newValue).Replace("{tileCount}", outgoing.Count.ToString()); if (player != null) { ((Character)player).Message((MessageType)2, $"Sharing {outgoing.Count} tile(s) to Discord...", 0, (Sprite)null); } List list = new List(outgoing.Count); foreach (MapTileShare.OutgoingTile item in outgoing) { list.Add(new DiscordWebhook.OutgoingImage { Bytes = item.Bytes, FileName = item.FileName }); } yield return DiscordWebhook.SendImageBatches(list, message, useSpoilerTag: false); if (player != null) { ((Character)player).Message((MessageType)2, $"Shared {outgoing.Count} tile(s).", 0, (Sprite)null); } } finally { _sendingInProgress = false; } } private static void CopyToClipboard(byte[] pngData) { if (pngData == null) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Failed to capture map.", 0, (Sprite)null); } return; } try { byte[] data = BuildCfDib(pngData); uint uFormat = RegisterClipboardFormat("PNG"); IntPtr hMem = AllocGlobal(data); IntPtr hMem2 = AllocGlobal(pngData); if (!OpenClipboard(IntPtr.Zero)) { GlobalFree(hMem); GlobalFree(hMem2); throw new Exception($"OpenClipboard failed (error {Marshal.GetLastWin32Error()})."); } EmptyClipboard(); SetClipboardData(8u, hMem); SetClipboardData(uFormat, hMem2); CloseClipboard(); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, "Map copied to clipboard!", 0, (Sprite)null); } } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Clipboard copy failed: " + ex.Message); Player localPlayer3 = Player.m_localPlayer; if (localPlayer3 != null) { ((Character)localPlayer3).Message((MessageType)2, "Failed to copy map to clipboard.", 0, (Sprite)null); } } } private static byte[] BuildCfDib(byte[] pngData) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown using MemoryStream memoryStream = new MemoryStream(pngData); Bitmap val = new Bitmap((Stream)memoryStream); try { int width = ((Image)val).Width; int height = ((Image)val).Height; Bitmap val2 = new Bitmap(width, height, (PixelFormat)137224); try { Graphics val3 = Graphics.FromImage((Image)(object)val2); try { val3.DrawImage((Image)(object)val, 0, 0); } finally { ((IDisposable)val3)?.Dispose(); } Rectangle rectangle = new Rectangle(0, 0, width, height); BitmapData val4 = val2.LockBits(rectangle, (ImageLockMode)1, (PixelFormat)137224); try { int stride = val4.Stride; int num = stride * height; byte[] array = new byte[40 + num]; WriteLE32(array, 0, 40); WriteLE32(array, 4, width); WriteLE32(array, 8, height); WriteLE16(array, 12, 1); WriteLE16(array, 14, 24); WriteLE32(array, 16, 0); WriteLE32(array, 20, num); for (int i = 0; i < height; i++) { int num2 = height - 1 - i; Marshal.Copy(new IntPtr(val4.Scan0.ToInt64() + (long)i * (long)stride), array, 40 + num2 * stride, stride); } return array; } finally { val2.UnlockBits(val4); } } finally { ((IDisposable)val2)?.Dispose(); } } finally { ((IDisposable)val)?.Dispose(); } } private static IntPtr AllocGlobal(byte[] data) { IntPtr intPtr = GlobalAlloc(2u, (UIntPtr)(ulong)data.Length); if (intPtr == IntPtr.Zero) { throw new Exception($"GlobalAlloc failed (Win32 error {Marshal.GetLastWin32Error()})."); } IntPtr destination = GlobalLock(intPtr); Marshal.Copy(data, 0, destination, data.Length); GlobalUnlock(intPtr); return intPtr; } private static void WriteLE32(byte[] buf, int off, int v) { buf[off] = (byte)v; buf[off + 1] = (byte)(v >> 8); buf[off + 2] = (byte)(v >> 16); buf[off + 3] = (byte)(v >> 24); } private static void WriteLE16(byte[] buf, int off, short v) { buf[off] = (byte)v; buf[off + 1] = (byte)(v >> 8); } [DllImport("user32.dll", SetLastError = true)] private static extern bool OpenClipboard(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool CloseClipboard(); [DllImport("user32.dll")] private static extern bool EmptyClipboard(); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern uint RegisterClipboardFormat(string lpszFormat); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes); [DllImport("kernel32.dll")] private static extern IntPtr GlobalLock(IntPtr hMem); [DllImport("kernel32.dll")] private static extern bool GlobalUnlock(IntPtr hMem); [DllImport("kernel32.dll")] private static extern IntPtr GlobalFree(IntPtr hMem); public void TriggerDiscordSend() { if (!_sendingInProgress && !string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl)) { CurrentSendingOp = SendingOp.Send; _sendingInProgress = true; ((MonoBehaviour)this).StartCoroutine(CaptureAndSend()); } } private IEnumerator CaptureAndSend() { BuildCaptureContext(out var player, out var playerName, out var biome, out var message); try { yield return (object)new WaitForEndOfFrame(); byte[] imageData = null; yield return CaptureTextureWithStyle(delegate(byte[] d) { imageData = d; }); yield return SendCapturedImage(imageData, player, playerName, biome, message); } finally { _sendingInProgress = false; } } private IEnumerator CaptureTextureWithStyle(Action onResult) { MapCaptureTexture.GetDefaultCaptureSize(out var width, out var height); bool num = MapStyleRender.IsStyleActive(); if (!num) { int num2 = Mathf.Max(width, height); if (num2 > 0 && num2 < 8192) { float num3 = 8192f / (float)num2; width = Mathf.RoundToInt((float)width * num3); height = Mathf.RoundToInt((float)height * num3); } } Texture2D styled = null; if (num) { RawImage val = (((Object)(object)Minimap.instance != (Object)null) ? Minimap.instance.m_mapImageLarge : null); if ((Object)(object)val != (Object)null) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Rendering map style...", 0, (Sprite)null); } yield return MapStyleRender.BuildAsync(val.uvRect, width, height, delegate(Texture2D t) { styled = t; }); } } try { onResult(MapCaptureTexture.CaptureMap(width, height, styled)); } finally { if ((Object)(object)styled != (Object)null) { Object.Destroy((Object)(object)styled); } } } private static void BuildCaptureContext(out Player player, out string playerName, out string biome, out string message) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) player = Player.m_localPlayer; playerName = (((Object)(object)player != (Object)null) ? player.GetPlayerName() : "unknown"); object obj; if (!((Object)(object)player != (Object)null)) { obj = "unknown"; } else { Biome currentBiome = player.GetCurrentBiome(); obj = ((object)(Biome)(ref currentBiome)).ToString(); } biome = (string)obj; string activeTableName = MapCompileSession.ActiveTableName; string text = ((!string.IsNullOrEmpty(activeTableName)) ? (" — " + activeTableName) : ""); message = ModHelpers.EffectiveConfig.MessageTemplate ?? string.Empty; message = message.Replace("{spawnDir}", string.Empty); if (message.Contains("{table}")) { message = message.Replace("{table}", text); } else if (text.Length > 0) { message += text; } message = message.Replace("{player}", playerName).Replace("{biome}", biome); } private static IEnumerator SendCapturedImage(byte[] imageData, Player player, string playerName, string biome, string message) { if (imageData == null) { if (player != null) { ((Character)player).Message((MessageType)2, "Failed to capture map.", 0, (Sprite)null); } yield break; } imageData = MapCompositor.Recode(imageData, GetEncodeOptions()); string filename = BuildMapFileName(playerName, biome); if (player != null) { ((Character)player).Message((MessageType)2, "Sending map to Discord...", 0, (Sprite)null); } yield return DiscordWebhook.SendImage(imageData, filename, message, ModHelpers.EffectiveConfig.SpoilerImageData); } private static string BuildMapFileName(string playerName, string biome) { string text = Sanitize(playerName); string text2 = Sanitize(biome); string text3 = DateTime.Now.ToString("yyyyMMdd-HHmmss"); if (string.IsNullOrEmpty(text)) { text = "player"; } if (string.IsNullOrEmpty(text2)) { text2 = "unknown"; } return text + "_" + text2 + "_" + text3 + ".png"; } private static string Sanitize(string s) { if (string.IsNullOrEmpty(s)) { return string.Empty; } string text = s.Normalize(NormalizationForm.FormD); StringBuilder stringBuilder = new StringBuilder(text.Length); string text2 = text; foreach (char c in text2) { if (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.NonSpacingMark) { continue; } if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9')) { switch (c) { case '-': case '_': break; case ' ': stringBuilder.Append('_'); continue; default: continue; } } stringBuilder.Append(c); } return stringBuilder.ToString(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public static class TablePinName { private const PinType TablePinType = 1; private const string ZenMapTrackingDelimiter = "\0#"; private const float MatchRadius = 8f; public static string Clean(string rawPinName) { if (string.IsNullOrEmpty(rawPinName)) { return null; } int num = rawPinName.IndexOf("\0#", StringComparison.Ordinal); string text = ((num >= 0) ? rawPinName.Substring(0, num) : rawPinName).Trim(); if (text.Length != 0) { return text; } return null; } public static string Resolve(Vector3 worldPos) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return null; } List pins = instance.m_pins; if (pins == null) { return null; } string result = null; float num = 64f; int count = pins.Count; for (int i = 0; i < count; i++) { PinData val = pins[i]; if (val == null || (int)val.m_type != 1) { continue; } string text = Clean(val.m_name); if (text != null) { float num2 = val.m_pos.x - worldPos.x; float num3 = val.m_pos.z - worldPos.z; float num4 = num2 * num2 + num3 * num3; if (!(num4 > num)) { num = num4; result = text; } } } return result; } } } namespace NoMapDiscordAdditions.MapCompile { public static class MapCompileButtons { private sealed class ClearGateDriver : MonoBehaviour { private void Update() { ApplyDestructiveGate(); } } [CompilerGenerated] private static class <>O { public static Action <0>__RefreshLayout; public static UnityAction <1>__OnAddTileClicked; public static UnityAction <2>__OnCompileClicked; public static UnityAction <3>__OnShareClicked; public static UnityAction <4>__OnRemoveTileClicked; public static UnityAction <5>__OnClearClicked; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__30_0; public static UnityAction <>9__32_0; internal void b__30_0() { MapCompileResultPanel.Hide(); MapCompileSession.ReturnToCompiling(); } internal void b__32_0() { MapCompileSession.Suspend(); } } private const string ContainerName = "MapCompilePanel"; private const float BtnHeight = 38f; private const float StartBtnWidth = 220f; private const float ActionBtnWidth = 160f; private const float ClearBtnWidth = 150f; private const float RemoveBtnWidth = 160f; private const float HlgPadVertical = 6f; private const float HlgSpacing = 8f; private static GameObject _containerObj; private static Button _btn1; private static Button _btn2; private static Button _btn3; private static Button _btn4; private static Button _btn5; private static TextMeshProUGUI _btn1Text; private static TextMeshProUGUI _btn2Text; private static TextMeshProUGUI _btn3Text; private static TextMeshProUGUI _btn4Text; private static TextMeshProUGUI _btn5Text; private static Button _btnRemove; private static TextMeshProUGUI _btnRemoveText; private static bool _composeInProgress; private static bool _captureInProgress; private static bool _clearGateHeld; private static bool _autoImportedThisOpen; public static void Create() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_largeRoot == (Object)null)) { if ((Object)(object)((Component)instance).transform.parent != (Object)null) { DestroyExisting(((Component)instance).transform.parent); } DestroyExisting(instance.m_largeRoot.transform); if (!((Object)(object)_containerObj != (Object)null)) { _containerObj = new GameObject("MapCompilePanel"); _containerObj.transform.SetParent(instance.m_largeRoot.transform, false); _containerObj.AddComponent().pivot = new Vector2(0.5f, 1f); MapUI.ApplyPanelBackground(_containerObj.AddComponent(), instance); HorizontalLayoutGroup obj = _containerObj.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 8f; ((LayoutGroup)obj).padding = new RectOffset(8, 8, 6, 6); ((LayoutGroup)obj).childAlignment = (TextAnchor)4; _btn1 = MapUI.CreateButton("CompileBtn1", _containerObj.transform, 220f, 38f, "", out _btn1Text); _btnRemove = MapUI.CreateButton("CompileBtnRemove", _containerObj.transform, 160f, 38f, "", out _btnRemoveText); _btn2 = MapUI.CreateButton("CompileBtn2", _containerObj.transform, 160f, 38f, "", out _btn2Text); _btn3 = MapUI.CreateButton("CompileBtn3", _containerObj.transform, 160f, 38f, "", out _btn3Text); _btn4 = MapUI.CreateButton("CompileBtn4", _containerObj.transform, 160f, 38f, "", out _btn4Text); _btn5 = MapUI.CreateButton("CompileBtn5", _containerObj.transform, 150f, 38f, "", out _btn5Text); _containerObj.AddComponent(); MapCompileSession.StateChanged -= RefreshLayout; MapCompileSession.StateChanged += RefreshLayout; _containerObj.SetActive(false); RefreshLayout(); ModLog.Info("[NoMapDiscordAdditions] Map compile panel created."); } } } public static void SetVisible(bool visible) { if (!((Object)(object)_containerObj == (Object)null)) { bool flag = visible && MapCompileEnvironment.IsAvailable; _containerObj.SetActive(flag); if (flag) { TryAutoImport(); RefreshLayout(); } if (!visible) { _autoImportedThisOpen = false; } } } private static void TryAutoImport() { if (_autoImportedThisOpen || !ModHelpers.EffectiveConfig.EnableCompileMapSharing || MapCompileSession.CurrentState != MapCompileSession.State.Compiling) { return; } _autoImportedThisOpen = true; int num = MapTileShare.ScanAndImport(); if (num > 0) { string arg = ((num == 1) ? "tile" : "tiles"); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, $"Imported {num} shared {arg} ({MapCompileSession.Tiles.Count} total).", 0, (Sprite)null); } } } private static void ApplyAlignment(RectTransform rect) { //IL_000b: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { float num = rect.sizeDelta.x * 0.5f; rect.anchorMin = new Vector2(0f, 0f); rect.anchorMax = new Vector2(0f, 0f); rect.anchoredPosition = new Vector2(8f + num, -8f); } } public static void RefreshLayout() { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Invalid comparison between Unknown and I4 //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_containerObj == (Object)null) { return; } if (!MapCompileEnvironment.IsAvailable) { _containerObj.SetActive(false); return; } ((UnityEventBase)_btn1.onClick).RemoveAllListeners(); ((UnityEventBase)_btn2.onClick).RemoveAllListeners(); ((UnityEventBase)_btn3.onClick).RemoveAllListeners(); ((UnityEventBase)_btn4.onClick).RemoveAllListeners(); ((UnityEventBase)_btn5.onClick).RemoveAllListeners(); ((UnityEventBase)_btnRemove.onClick).RemoveAllListeners(); switch (MapCompileSession.CurrentState) { case MapCompileSession.State.Idle: LayoutIdle(); break; case MapCompileSession.State.Compiling: LayoutCompiling(); break; case MapCompileSession.State.Reviewing: if (MapCompileResultPanel.IsVisible || !MapCompileResultPanel.HasPendingResult) { _containerObj.SetActive(false); return; } LayoutResumeReview(); break; } if (!_containerObj.activeSelf) { _containerObj.SetActive((Object)(object)Minimap.instance != (Object)null && (int)Minimap.instance.m_mode == 2); } float num = 16f; int num2 = 0; if (((Component)_btn1).gameObject.activeSelf) { num += ((Component)_btn1).GetComponent().sizeDelta.x; num2++; } if (((Component)_btnRemove).gameObject.activeSelf) { num += ((Component)_btnRemove).GetComponent().sizeDelta.x; num2++; } if (((Component)_btn2).gameObject.activeSelf) { num += ((Component)_btn2).GetComponent().sizeDelta.x; num2++; } if (((Component)_btn3).gameObject.activeSelf) { num += ((Component)_btn3).GetComponent().sizeDelta.x; num2++; } if (((Component)_btn4).gameObject.activeSelf) { num += ((Component)_btn4).GetComponent().sizeDelta.x; num2++; } if (((Component)_btn5).gameObject.activeSelf) { num += ((Component)_btn5).GetComponent().sizeDelta.x; num2++; } if (num2 > 1) { num += (float)(num2 - 1) * 8f; } float num3 = 50f; RectTransform component = _containerObj.GetComponent(); component.sizeDelta = new Vector2(num, num3); ApplyAlignment(component); } private static void LayoutResumeReview() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown int count = MapCompileSession.Tiles.Count; ((Component)_btn1).gameObject.SetActive(true); ((TMP_Text)_btn1Text).text = $"RESUME COMPILE ({count})"; ((Component)_btn1).GetComponent().sizeDelta = new Vector2(220f, 38f); ((Selectable)_btn1).interactable = !_composeInProgress; ButtonClickedEvent onClick = _btn1.onClick; object obj = <>c.<>9__30_0; if (obj == null) { UnityAction val = delegate { MapCompileResultPanel.Hide(); MapCompileSession.ReturnToCompiling(); }; <>c.<>9__30_0 = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ((Component)_btn2).gameObject.SetActive(false); ((Component)_btn3).gameObject.SetActive(false); ((Component)_btn4).gameObject.SetActive(false); ((Component)_btnRemove).gameObject.SetActive(false); ShowClearButton(show: true); } private static void LayoutIdle() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown bool resumable = MapCompileSession.HasResumableSession(); int num = (resumable ? CountSavedTiles() : 0); ((Component)_btn1).gameObject.SetActive(true); ((TMP_Text)_btn1Text).text = (resumable ? $"RESUME COMPILE ({num})" : "START COMPILE"); ((Component)_btn1).GetComponent().sizeDelta = new Vector2(220f, 38f); ((Selectable)_btn1).interactable = !_composeInProgress; ((UnityEvent)_btn1.onClick).AddListener((UnityAction)delegate { if (resumable) { MapCompileSession.Resume(); } else { MapCompileSession.Start(); } if (MapCompileSession.CanAddTile) { OnAddTileClicked(); } TryAutoImport(); }); ((Component)_btn2).gameObject.SetActive(false); ((Component)_btn3).gameObject.SetActive(false); ((Component)_btn4).gameObject.SetActive(false); ((Component)_btnRemove).gameObject.SetActive(false); ShowClearButton(resumable); } private static void LayoutCompiling() { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Expected O, but got Unknown //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Expected O, but got Unknown int count = MapCompileSession.Tiles.Count; bool flag = _composeInProgress || _captureInProgress; ((Component)_btn1).gameObject.SetActive(true); ((TMP_Text)_btn1Text).text = (_captureInProgress ? "CAPTURING TILE..." : ((!MapCompileSession.CanAddTile) ? "ADD TILE — go to a table" : (MapCompileSession.ActiveTableAlreadyAdded ? $"UPDATE TILE ({count})" : $"ADD TILE ({count})"))); float num = ((_captureInProgress || !MapCompileSession.CanAddTile) ? 240f : 160f); ((Component)_btn1).GetComponent().sizeDelta = new Vector2(num, 38f); ((Selectable)_btn1).interactable = MapCompileSession.CanAddTile && !flag; ButtonClickedEvent onClick = _btn1.onClick; object obj = <>O.<1>__OnAddTileClicked; if (obj == null) { UnityAction val = OnAddTileClicked; <>O.<1>__OnAddTileClicked = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ((Component)_btn2).gameObject.SetActive(true); ((TMP_Text)_btn2Text).text = $"COMPILE ({count})"; ((Component)_btn2).GetComponent().sizeDelta = new Vector2(160f, 38f); ((Selectable)_btn2).interactable = count > 0 && !flag; ButtonClickedEvent onClick2 = _btn2.onClick; object obj2 = <>O.<2>__OnCompileClicked; if (obj2 == null) { UnityAction val2 = OnCompileClicked; <>O.<2>__OnCompileClicked = val2; obj2 = (object)val2; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); bool enableCompileMapSharing = ModHelpers.EffectiveConfig.EnableCompileMapSharing; ((Component)_btn3).gameObject.SetActive(enableCompileMapSharing); if (enableCompileMapSharing) { bool flag2 = !string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl); ((TMP_Text)_btn3Text).text = (flag2 ? $"SHARE ({count})" : $"EXPORT ({count})"); ((Component)_btn3).GetComponent().sizeDelta = new Vector2(160f, 38f); ((Selectable)_btn3).interactable = count > 0 && !flag; ButtonClickedEvent onClick3 = _btn3.onClick; object obj3 = <>O.<3>__OnShareClicked; if (obj3 == null) { UnityAction val3 = OnShareClicked; <>O.<3>__OnShareClicked = val3; obj3 = (object)val3; } ((UnityEvent)onClick3).AddListener((UnityAction)obj3); } ((Component)_btn4).gameObject.SetActive(true); ((TMP_Text)_btn4Text).text = "CANCEL"; ((Component)_btn4).GetComponent().sizeDelta = new Vector2(110f, 38f); ((Selectable)_btn4).interactable = !flag; ButtonClickedEvent onClick4 = _btn4.onClick; object obj4 = <>c.<>9__32_0; if (obj4 == null) { UnityAction val4 = delegate { MapCompileSession.Suspend(); }; <>c.<>9__32_0 = val4; obj4 = (object)val4; } ((UnityEvent)onClick4).AddListener((UnityAction)obj4); bool activeTableAlreadyAdded = MapCompileSession.ActiveTableAlreadyAdded; ((Component)_btnRemove).gameObject.SetActive(activeTableAlreadyAdded); if (activeTableAlreadyAdded) { ((Component)_btnRemove).GetComponent().sizeDelta = new Vector2(160f, 38f); ButtonClickedEvent onClick5 = _btnRemove.onClick; object obj5 = <>O.<4>__OnRemoveTileClicked; if (obj5 == null) { UnityAction val5 = OnRemoveTileClicked; <>O.<4>__OnRemoveTileClicked = val5; obj5 = (object)val5; } ((UnityEvent)onClick5).AddListener((UnityAction)obj5); } ShowClearButton(show: true); } private static void ShowClearButton(bool show) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown ((Component)_btn5).gameObject.SetActive(show); if (show) { ((Component)_btn5).GetComponent().sizeDelta = new Vector2(150f, 38f); ButtonClickedEvent onClick = _btn5.onClick; object obj = <>O.<5>__OnClearClicked; if (obj == null) { UnityAction val = OnClearClicked; <>O.<5>__OnClearClicked = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ApplyDestructiveGate(force: true); } } private static void ApplyDestructiveGate(bool force = false) { bool key = Input.GetKey((KeyCode)306); if (force || key != _clearGateHeld) { _clearGateHeld = key; bool flag = _composeInProgress || _captureInProgress; if ((Object)(object)_btn5 != (Object)null && ((Component)_btn5).gameObject.activeSelf) { ((Selectable)_btn5).interactable = key && !flag; ((TMP_Text)_btn5Text).text = (key ? "CLEAR" : "CLEAR (L-CTRL)"); } if ((Object)(object)_btnRemove != (Object)null && ((Component)_btnRemove).gameObject.activeSelf) { ((Selectable)_btnRemove).interactable = key && !flag && MapCompileSession.ActiveTableAlreadyAdded; ((TMP_Text)_btnRemoveText).text = (key ? "REMOVE TILE" : "REMOVE (L-CTRL)"); } } } private static void OnClearClicked() { if (!_composeInProgress && !_captureInProgress && Input.GetKey((KeyCode)306)) { MapCompileResultPanel.Hide(); MapCompileSession.ClearSession(); } } private static void OnRemoveTileClicked() { if (!_composeInProgress && !_captureInProgress && Input.GetKey((KeyCode)306)) { MapCompileSession.RemoveActiveTableTile(); } } private static void OnShareClicked() { if (_composeInProgress || _captureInProgress) { return; } if (MapCompileSession.Tiles.Count == 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "No tiles to share.", 0, (Sprite)null); } } else { Plugin.Instance?.ShareCompileTiles(); } } private static void OnAddTileClicked() { if (!_captureInProgress && !_composeInProgress && MapCompileSession.CanAddTile) { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null)) { ((MonoBehaviour)instance).StartCoroutine(CaptureTileCoroutine()); } } } private static IEnumerator CaptureTileCoroutine() { if (!MapCompileSession.CanAddTile) { yield break; } Vector3 tablePos = MapCompileSession.ActiveTablePos.Value; _captureInProgress = true; try { RefreshLayout(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, MapStyleRender.IsStyleActive() ? "Rendering styled tile..." : "Capturing tile...", 0, (Sprite)null); } MapCompileCapture.Result? result = null; yield return MapCompileCapture.Capture(delegate(MapCompileCapture.Result? r) { result = r; }); if (result.HasValue) { MapCompileCapture.Result value = result.Value; MapCompileSession.AddTile(value.Png, value.Width, value.Height, value.WorldMin, value.WorldMax, tablePos, value.FullyMapped); yield break; } Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, "Tile capture failed.", 0, (Sprite)null); } } finally { _captureInProgress = false; RefreshLayout(); } } private static void OnCompileClicked() { if (_composeInProgress || _captureInProgress) { return; } if (MapCompileSession.Tiles.Count == 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "No tiles to compile.", 0, (Sprite)null); } } else { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null)) { ((MonoBehaviour)instance).StartCoroutine(ComposeCoroutine()); } } } private static IEnumerator ComposeCoroutine() { _composeInProgress = true; RefreshLayout(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Compiling map...", 0, (Sprite)null); } List tilesSnapshot = new List(MapCompileSession.Tiles); float refScreenW; List pins = MapCompilePinSnapshot.Capture(out refScreenW); MapCompositor.CompiledMap result = null; Exception error = null; ManualResetEventSlim done = new ManualResetEventSlim(initialState: false); ThreadPool.QueueUserWorkItem(delegate { try { result = MapCompositor.Compose(tilesSnapshot, 4096); } catch (Exception ex) { error = ex; } finally { done.Set(); } }); while (!done.IsSet) { yield return null; } done.Dispose(); if (error != null) { _composeInProgress = false; ModLog.Error($"[NoMapDiscordAdditions] Compose failed: {error}"); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, "Compile failed.", 0, (Sprite)null); } RefreshLayout(); yield break; } if (result == null) { _composeInProgress = false; Player localPlayer3 = Player.m_localPlayer; if (localPlayer3 != null) { ((Character)localPlayer3).Message((MessageType)2, "Compile produced no output.", 0, (Sprite)null); } RefreshLayout(); yield break; } yield return MapCompileLabelStamp.Finalize(result, pins, tilesSnapshot, refScreenW); _composeInProgress = false; if (result.PngBytes == null) { ModLog.Error("[NoMapDiscordAdditions] Compile encode produced no PNG."); Player localPlayer4 = Player.m_localPlayer; if (localPlayer4 != null) { ((Character)localPlayer4).Message((MessageType)2, "Compile failed.", 0, (Sprite)null); } RefreshLayout(); } else { MapCompileSession.Finish(); MapCompileResultPanel.Show(result); } } private static int CountSavedTiles() { try { string sessionDir = MapCompileEnvironment.GetSessionDir(MapCompileEnvironment.GetSessionKey()); if (!Directory.Exists(sessionDir)) { return 0; } return Directory.GetFiles(sessionDir, "tile_*.png").Length; } catch { return 0; } } private static void DestroyExisting(Transform largeRoot) { for (int num = largeRoot.childCount - 1; num >= 0; num--) { Transform child = largeRoot.GetChild(num); if ((Object)(object)child != (Object)null && ((Object)child).name == "MapCompilePanel") { Object.Destroy((Object)(object)((Component)child).gameObject); } } if (!Object.op_Implicit((Object)(object)_containerObj)) { _containerObj = null; } } } public static class MapCompileCapture { public struct Result { public byte[] Png; public int Width; public int Height; public Vector2 WorldMin; public Vector2 WorldMax; public bool FullyMapped; } private const int TileMaxDim = 4096; private const int StyledRenderMaxDim = 1536; private const float WorldRadius = 10000f; public static IEnumerator Capture(Action callback) { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_mapImageLarge == (Object)null) { ModLog.Warn("[NoMapDiscordAdditions] Compile capture: Minimap unavailable."); callback?.Invoke(null); yield break; } if ((int)instance.m_mode != 2) { ModLog.Warn("[NoMapDiscordAdditions] Compile capture: large map not active."); callback?.Invoke(null); yield break; } Rect uv = instance.m_mapImageLarge.uvRect; MapCompileTile.ComputeWorldRect(instance, uv, out var wmin, out var wmax); bool fully = IsFullyMapped(instance, uv); if (MapStyleRender.IsStyleActive()) { Result? styledResult = null; yield return CaptureStyledTile(uv, wmin, wmax, fully, delegate(Result? r) { styledResult = r; }); callback?.Invoke(styledResult); } else { yield return (object)new WaitForEndOfFrame(); if ((Object)(object)Minimap.instance == (Object)null || (int)Minimap.instance.m_mode != 2) { callback?.Invoke(null); } else { callback?.Invoke(CaptureTexture(uv, wmin, wmax, fully)); } } } private static Result? CaptureTexture(Rect uv, Vector2 wmin, Vector2 wmax, bool fully) { //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(((Rect)(ref uv)).xMax) - Mathf.Clamp01(((Rect)(ref uv)).xMin); float num2 = Mathf.Clamp01(((Rect)(ref uv)).yMax) - Mathf.Clamp01(((Rect)(ref uv)).yMin); int num4; int num5; if (num > 1E-06f && num2 > 1E-06f) { float num3 = num / num2; if (num3 >= 1f) { num4 = 4096; num5 = Mathf.Max(64, Mathf.RoundToInt(4096f / num3)); } else { num5 = 4096; num4 = Mathf.Max(64, Mathf.RoundToInt(4096f * num3)); } } else { num4 = 1920; num5 = 1080; } byte[] array = MapCaptureTexture.CaptureMap(num4, num5, null, drawPinIcons: false); if (array == null) { ModLog.Warn("[NoMapDiscordAdditions] Compile capture: MapCaptureTexture returned null."); return null; } Result value = default(Result); value.Png = array; value.Width = num4; value.Height = num5; value.WorldMin = wmin; value.WorldMax = wmax; value.FullyMapped = fully; return value; } private static IEnumerator CaptureStyledTile(Rect uv, Vector2 wmin, Vector2 wmax, bool fully, Action callback) { //IL_0007: 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) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(((Rect)(ref uv)).xMax) - Mathf.Clamp01(((Rect)(ref uv)).xMin); float num2 = Mathf.Clamp01(((Rect)(ref uv)).yMax) - Mathf.Clamp01(((Rect)(ref uv)).yMin); int capW; int capH; if (num > 1E-06f && num2 > 1E-06f) { float num3 = num / num2; if (num3 >= 1f) { capW = 4096; capH = Mathf.Max(64, Mathf.RoundToInt(4096f / num3)); } else { capH = 4096; capW = Mathf.Max(64, Mathf.RoundToInt(4096f * num3)); } } else { capW = 1920; capH = 1080; } int width = capW; int height = capH; int num4 = Mathf.Max(capW, capH); if (num4 > 1536) { float num5 = 1536f / (float)num4; width = Mathf.Max(64, Mathf.RoundToInt((float)capW * num5)); height = Mathf.Max(64, Mathf.RoundToInt((float)capH * num5)); } Texture2D styled = null; yield return MapStyleRender.BuildAsync(uv, width, height, delegate(Texture2D t) { styled = t; }); if ((Object)(object)Minimap.instance == (Object)null || (int)Minimap.instance.m_mode != 2) { if ((Object)(object)styled != (Object)null) { Object.Destroy((Object)(object)styled); } callback?.Invoke(null); yield break; } byte[] array = MapCaptureTexture.CaptureMap(capW, capH, styled, drawPinIcons: false); if ((Object)(object)styled != (Object)null) { Object.Destroy((Object)(object)styled); } if (array == null) { ModLog.Warn("[NoMapDiscordAdditions] Compile capture (styled): MapCaptureTexture returned null."); callback?.Invoke(null); yield break; } callback?.Invoke(new Result { Png = array, Width = capW, Height = capH, WorldMin = wmin, WorldMax = wmax, FullyMapped = fully }); } private static bool IsFullyMapped(Minimap minimap, Rect uv) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (ZenMapInterop.TryGetActiveRevealPercent(out var percent)) { return percent >= 0.999f; } return IsRegionFullyMapped(minimap, uv); } private static bool IsRegionFullyMapped(Minimap minimap, Rect uv) { bool[] explored = minimap.m_explored; int textureSize = minimap.m_textureSize; if (explored == null || textureSize <= 0 || explored.Length < textureSize * textureSize) { return false; } float num = Mathf.Clamp01(((Rect)(ref uv)).xMin); float num2 = Mathf.Clamp01(((Rect)(ref uv)).yMin); float num3 = Mathf.Clamp01(((Rect)(ref uv)).xMax); float num4 = Mathf.Clamp01(((Rect)(ref uv)).yMax); int num5 = Mathf.Clamp(Mathf.FloorToInt(num * (float)textureSize), 0, textureSize - 1); int num6 = Mathf.Clamp(Mathf.CeilToInt(num3 * (float)textureSize) - 1, 0, textureSize - 1); int num7 = Mathf.Clamp(Mathf.FloorToInt(num2 * (float)textureSize), 0, textureSize - 1); int num8 = Mathf.Clamp(Mathf.CeilToInt(num4 * (float)textureSize) - 1, 0, textureSize - 1); float pixelSize = minimap.m_pixelSize; float num9 = (float)textureSize / 2f; float num10 = 100000000f; for (int i = num7; i <= num8; i++) { float num11 = ((float)i + 0.5f - num9) * pixelSize; int num12 = i * textureSize; for (int j = num5; j <= num6; j++) { float num13 = ((float)j + 0.5f - num9) * pixelSize; if (!(num13 * num13 + num11 * num11 > num10) && !explored[num12 + j]) { return false; } } } return true; } } public static class MapCompileEnvironment { private const string ZenMapGuid = "ZenDragon.ZenMap"; private const string SessionsDirName = "compile-sessions"; private const string CompiledOutDirName = "compiled"; private const string ShareDirName = "compile-share"; private const string ShareOutDirName = "out"; private const string IncomingDirName = "incoming"; private const string IncomingProcessedName = "processed"; private const string IncomingIgnoredName = "ignored"; private static bool? _zenMapPresent; public static bool IsZenMapLoaded { get { if (_zenMapPresent.HasValue) { return _zenMapPresent.Value; } _zenMapPresent = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("ZenDragon.ZenMap"); return _zenMapPresent.Value; } } public static bool IsNoMap { get { if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetGlobalKey((GlobalKeys)26); } return false; } } public static bool IsAvailable { get { if (IsZenMapLoaded && IsNoMap && HasSessionKey()) { return IsTableOrCompiling; } return false; } } private static bool IsTableOrCompiling { get { if (MapCompileSession.CurrentState != MapCompileSession.State.Compiling) { return MapCompileSession.ActiveTablePos.HasValue; } return true; } } public static string ModConfigRoot => Path.Combine(Paths.ConfigPath, "NoMapDiscordAdditions"); public static string SessionsRoot => Path.Combine(ModConfigRoot, "compile-sessions"); public static string CompiledOutDir => Path.Combine(ModConfigRoot, "compiled"); public static string ShareRoot => Path.Combine(ModConfigRoot, "compile-share"); public static string ShareOutDir => Path.Combine(ShareRoot, "out"); public static string IncomingDir => Path.Combine(ShareRoot, "incoming"); public static string IncomingProcessedDir => Path.Combine(IncomingDir, "processed"); public static string IncomingIgnoredDir => Path.Combine(IncomingDir, "ignored"); public static bool HasSessionKey() { if ((Object)(object)Player.m_localPlayer != (Object)null) { return (Object)(object)ZNet.instance != (Object)null; } return false; } public static string GetSessionKey() { long worldUID = ZNet.instance.GetWorldUID(); long playerID = Player.m_localPlayer.GetPlayerID(); return $"{worldUID:X16}_{playerID:X16}"; } public static string GetSessionDir(string sessionKey) { return Path.Combine(SessionsRoot, sessionKey); } public static string GetSessionFile(string sessionDir) { return Path.Combine(sessionDir, "session.json"); } public static string GetTileFile(string sessionDir, int index) { return Path.Combine(sessionDir, $"tile_{index:D3}.png"); } public static void EnsureDirectory(string dir) { if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } } public static class MapCompileLabelStamp { private static float _vanillaPinFontSize = -1f; private static FontStyles _vanillaPinFontStyle; public static IEnumerator Finalize(MapCompositor.CompiledMap r, IReadOnlyList pins, IReadOnlyList tiles, float referenceScreenWidth) { return Finalize(r, pins, tiles, referenceScreenWidth, MapCompositor.EncodeOptions.Default); } public static IEnumerator Finalize(MapCompositor.CompiledMap r, IReadOnlyList pins, IReadOnlyList tiles, float referenceScreenWidth, MapCompositor.EncodeOptions opts) { if (r == null || r.Bgra == null) { yield break; } r.Extension = opts.Extension; Color32[] labelled = null; try { labelled = Stamp(r.Bgra, r.Width, r.Height, r.WorldMin, r.WorldMax - r.WorldMin, pins, tiles, referenceScreenWidth); } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Pin stamp failed: " + ex.Message); labelled = null; } byte[] rawBgra = r.Bgra; if (labelled != null) { r.Bgra = null; rawBgra = null; } byte[] png = null; Exception err = null; ManualResetEventSlim done = new ManualResetEventSlim(initialState: false); ThreadPool.QueueUserWorkItem(delegate { try { png = ((labelled != null) ? MapCompositor.EncodeRgbaBottomUp(labelled, r.Width, r.Height, opts) : MapCompositor.EncodeBgra(rawBgra, r.Width, r.Height, opts)); } catch (Exception ex2) { err = ex2; } finally { done.Set(); } }); while (!done.IsSet) { yield return null; } done.Dispose(); if (err != null) { ModLog.Error("[NoMapDiscordAdditions] Compile encode failed: " + err.Message); } r.PngBytes = png; } private static Color32[] Stamp(byte[] bgraTopDown, int w, int h, Vector2 worldMin, Vector2 worldSize, IReadOnlyList pins, IReadOnlyList tiles, float referenceScreenWidth) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) if (worldSize.x <= 0f || worldSize.y <= 0f) { return null; } if (pins == null || pins.Count == 0) { return null; } float num = ((referenceScreenWidth > 1f) ? ((float)w / referenceScreenWidth) : ((float)w / 1920f)) * 0.25f; SampleVanillaPinTmp(out var fontSize, out var fontStyle); float num2 = fontSize * Mathf.Max(1f, (float)w / 4096f); List<(Sprite, Color32, float, float, float, float, string)> list = new List<(Sprite, Color32, float, float, float, float, string)>(); foreach (MapCompositor.PinDraw pin in pins) { if (!((Object)(object)pin.Icon == (Object)null)) { float num3 = (pin.WorldX - worldMin.x) / worldSize.x; float num4 = (worldSize.y - (pin.WorldZ - worldMin.y)) / worldSize.y; if (!(num3 < 0f) && !(num3 > 1f) && !(num4 < 0f) && !(num4 > 1f) && IsInsideAnyTile(pin.WorldX, pin.WorldZ, tiles)) { float item = Mathf.Max(4f, pin.ScreenPxW * num); float item2 = Mathf.Max(4f, pin.ScreenPxH * num); float item3 = (float)h - num4 * (float)h; list.Add((pin.Icon, pin.Tint, num3 * (float)w, item3, item, item2, TablePinName.Clean(pin.Name))); } } } if (list.Count == 0) { return null; } Color32[] array = MaterializeBuffer(bgraTopDown, w, h); GameObject val = new GameObject("NMDA_CompilePinStamp") { hideFlags = (HideFlags)61 }; bool fontOk = true; try { Canvas obj = val.AddComponent(); obj.renderMode = (RenderMode)2; ((Behaviour)obj).enabled = false; RectTransform component = val.GetComponent(); component.pivot = Vector2.zero; component.sizeDelta = new Vector2((float)w, (float)h); ((Transform)component).localScale = Vector3.one; ((Transform)component).position = Vector3.zero; ((Transform)component).rotation = Quaternion.identity; foreach (var item4 in list) { MapCaptureTexture.BlitSpriteInto(array, w, h, item4.Item1, item4.Item2, item4.Item3, item4.Item4, item4.Item5, item4.Item6); } foreach (var item5 in list) { if (!fontOk) { break; } if (!string.IsNullOrEmpty(item5.Item7)) { float pyBottom = item5.Item4 - item5.Item6 * 0.5f - num2 * 0.6f; DrawTmpCaption(val, array, w, h, item5.Item7, item5.Item3, pyBottom, num2, fontStyle, ref fontOk); } } } finally { Object.DestroyImmediate((Object)(object)val); MapCaptureTexture.ClearLabelAtlasCache(); } return array; } private static Color32[] MaterializeBuffer(byte[] bgraTopDown, int w, int h) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[w * h]; for (int i = 0; i < h; i++) { int num = (h - 1 - i) * w; int num2 = i * w * 4; for (int j = 0; j < w; j++) { int num3 = num2 + j * 4; array[num + j] = new Color32(bgraTopDown[num3 + 2], bgraTopDown[num3 + 1], bgraTopDown[num3], byte.MaxValue); } } return array; } private static bool DrawTmpCaption(GameObject root, Color32[] buf, int w, int h, string text, float px, float pyBottom, float fontPx, FontStyles fontStyle, ref bool fontOk) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0056: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("lbl"); val.SetActive(false); val.transform.SetParent(root.transform, false); TextMeshProUGUI val2 = val.AddComponent(); MapUI.ApplyValheimFont((TMP_Text)(object)val2); if ((Object)(object)((TMP_Text)val2).font == (Object)null) { fontOk = false; return false; } ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = fontPx; ((TMP_Text)val2).fontStyle = fontStyle; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((Graphic)val2).raycastTarget = false; ((Graphic)val2).color = Color.white; RectTransform rectTransform = ((TMP_Text)val2).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.zero; rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.sizeDelta = new Vector2(Mathf.Max(64f, (float)text.Length * fontPx), fontPx * 2f); rectTransform.anchoredPosition = new Vector2(px, pyBottom); val.SetActive(true); ((TMP_Text)val2).ForceMeshUpdate(false, false); MapCaptureTexture.RasterizeTmpInto(buf, w, h, (TMP_Text)(object)val2, forceMeshUpdate: false, drawOutline: true); Object.DestroyImmediate((Object)(object)val); return true; } private static bool IsInsideAnyTile(float wx, float wz, IReadOnlyList tiles) { if (tiles == null || tiles.Count == 0) { return true; } for (int i = 0; i < tiles.Count; i++) { MapCompileTile mapCompileTile = tiles[i]; if (wx >= mapCompileTile.WorldMin.x && wx <= mapCompileTile.WorldMax.x && wz >= mapCompileTile.WorldMin.y && wz <= mapCompileTile.WorldMax.y) { return true; } } return false; } private static void SampleVanillaPinTmp(out float fontSize, out FontStyles fontStyle) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected I4, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected I4, but got Unknown if (_vanillaPinFontSize > 0f) { fontSize = _vanillaPinFontSize; fontStyle = (FontStyles)(int)_vanillaPinFontStyle; return; } Minimap instance = Minimap.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.m_pinNamePrefab : null); if ((Object)(object)val != (Object)null) { TMP_Text componentInChildren = val.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { _vanillaPinFontSize = componentInChildren.fontSize; _vanillaPinFontStyle = componentInChildren.fontStyle; fontSize = _vanillaPinFontSize; fontStyle = (FontStyles)(int)_vanillaPinFontStyle; return; } } fontSize = 16f; fontStyle = (FontStyles)0; } } public static class MapCompilePinSnapshot { private static readonly Regex s_richText = new Regex("<[^>]+>", RegexOptions.Compiled); public static List Capture(out float referenceScreenWidth) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Invalid comparison between Unknown and I4 //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Invalid comparison between Unknown and I4 //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected I4, but got Unknown //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) referenceScreenWidth = 0f; List list = new List(); Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null || instance.m_pins == null) { return list; } if ((Object)(object)instance.m_mapImageLarge != (Object)null) { Vector3[] array = (Vector3[])(object)new Vector3[4]; ((Graphic)instance.m_mapImageLarge).rectTransform.GetWorldCorners(array); float num = Mathf.Abs(array[2].x - array[0].x); if (num > 1f) { referenceScreenWidth = num; } } if (referenceScreenWidth <= 1f) { referenceScreenWidth = Screen.width; } bool[] visibleIconTypes = instance.m_visibleIconTypes; bool flag = instance.m_sharedMapDataFade > 0f; float pinSizeLarge = instance.m_pinSizeLarge; Color32 val = Color32.op_Implicit(new Color(0.7f, 0.7f, 0.7f, 0.8f * instance.m_sharedMapDataFade)); List pins = instance.m_pins; int count = pins.Count; for (int i = 0; i < count; i++) { PinData val2 = pins[i]; if (val2 == null || (int)val2.m_type == 10 || (int)val2.m_type == 4) { continue; } int num2 = (int)val2.m_type; if ((visibleIconTypes != null && num2 >= 0 && num2 < visibleIconTypes.Length && !visibleIconTypes[num2]) || (val2.m_ownerID != 0L && !flag)) { continue; } Sprite val3 = null; if ((Object)(object)val2.m_iconElement != (Object)null && (Object)(object)val2.m_iconElement.sprite != (Object)null) { val3 = val2.m_iconElement.sprite; } if ((Object)(object)val3 == (Object)null) { val3 = val2.m_icon; } if ((Object)(object)val3 == (Object)null) { val3 = instance.GetSprite(val2.m_type); } if ((Object)(object)val3 == (Object)null) { continue; } RectTransform uiElement = val2.m_uiElement; float screenPxW; float screenPxH; if ((Object)(object)uiElement != (Object)null && ((Component)uiElement).gameObject.activeInHierarchy) { Rect rect = uiElement.rect; Vector2 size = ((Rect)(ref rect)).size; screenPxW = ((size.x > 0f) ? size.x : pinSizeLarge); screenPxH = ((size.y > 0f) ? size.y : pinSizeLarge); } else { screenPxW = (screenPxH = (val2.m_doubleSize ? (pinSizeLarge * 2f) : pinSizeLarge)); } Color32 tint = ((!((Object)(object)val2.m_iconElement != (Object)null)) ? ((val2.m_ownerID != 0L) ? val : Color32.op_Implicit(Color.white)) : Color32.op_Implicit(((Graphic)val2.m_iconElement).color)); string text = TablePinName.Clean(val2.m_name); if (!string.IsNullOrEmpty(text)) { Localization instance2 = Localization.instance; if (instance2 != null) { text = instance2.Localize(text); } if (!string.IsNullOrEmpty(text)) { text = s_richText.Replace(text, string.Empty).Trim(); } if (string.IsNullOrEmpty(text)) { text = null; } } list.Add(new MapCompositor.PinDraw { WorldX = val2.m_pos.x, WorldZ = val2.m_pos.z, Icon = val3, Tint = tint, ScreenPxW = screenPxW, ScreenPxH = screenPxH, Name = text }); } return list; } } public static class MapCompileResultPanel { [CompilerGenerated] private static class <>O { public static UnityAction <0>__OnCopy; public static UnityAction <1>__OnSaveOrCopyDir; public static UnityAction <2>__OnSend; public static UnityAction <3>__OnDiscard; public static UnityAction <4>__OnDone; } private const string ContainerName = "MapCompileResultPanel"; private const float Pad = 12f; private const float ButtonHeight = 38f; private const float MaxPreviewSize = 360f; private static GameObject _containerObj; private static MapCompositor.CompiledMap _result; private static Texture2D _previewTex; private static TextMeshProUGUI _statusText; private static TextMeshProUGUI _saveBtnText; private static string _savedFilePath; private static bool _saveInProgress; public static bool IsVisible { get { if ((Object)(object)_containerObj != (Object)null) { return _containerObj.activeSelf; } return false; } } public static bool HasPendingResult => _result != null; public static void Show(MapCompositor.CompiledMap result) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0069: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Expected O, but got Unknown //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Expected O, but got Unknown //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Expected O, but got Unknown //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Expected O, but got Unknown //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Expected O, but got Unknown //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Expected O, but got Unknown Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_largeRoot == (Object)null)) { Hide(); _result = result; _containerObj = new GameObject("MapCompileResultPanel"); _containerObj.transform.SetParent(instance.m_largeRoot.transform, false); RectTransform val = _containerObj.AddComponent(); val.anchorMin = new Vector2(0.5f, 0.5f); val.anchorMax = new Vector2(0.5f, 0.5f); val.pivot = new Vector2(0.5f, 0.5f); MapUI.ApplyPanelBackground(_containerObj.AddComponent(), instance); VerticalLayoutGroup val2 = _containerObj.AddComponent(); ((LayoutGroup)val2).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)val2).spacing = 10f; ((LayoutGroup)val2).padding = new RectOffset(12, 12, 12, 12); CreateLabel("MAP COMPILED", 22f); ComputePreviewSize(result.Width, result.Height, out var w, out var h); GameObject val3 = new GameObject("Preview"); val3.transform.SetParent(_containerObj.transform, false); val3.AddComponent().sizeDelta = new Vector2(w, h); _previewTex = DecodePngToTexture(result.PngBytes); val3.AddComponent().texture = (Texture)(object)_previewTex; string text = ((result.TileCount == 1) ? "tile" : "tiles"); _statusText = CreateLabel($"{result.TileCount} {text} | {result.Width}×{result.Height}px", 14f); ((TMP_Text)_statusText).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)_statusText).rectTransform.sizeDelta = new Vector2(640f, 36f); GameObject val4 = new GameObject("Buttons"); val4.transform.SetParent(_containerObj.transform, false); RectTransform obj = val4.AddComponent(); HorizontalLayoutGroup obj2 = val4.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f; ((LayoutGroup)obj2).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = false; float num = 100f; float num2 = 130f; float num3 = 180f; float num4 = 110f; float num5 = 90f; Button obj3 = MapUI.CreateButton("Save", val4.transform, num2, 38f, "SAVE", out _saveBtnText); TextMeshProUGUI labelText; Button obj4 = MapUI.CreateButton("Copy", val4.transform, num, 38f, "COPY", out labelText); Button val5 = MapUI.CreateButton("Send", val4.transform, num3, 38f, "SEND TO DISCORD", out labelText); Button val6 = MapUI.CreateButton("Discard", val4.transform, num4, 38f, "DISCARD", out labelText); Button val7 = MapUI.CreateButton("Done", val4.transform, num5, 38f, "DONE", out labelText); ButtonClickedEvent onClick = obj4.onClick; object obj5 = <>O.<0>__OnCopy; if (obj5 == null) { UnityAction val8 = OnCopy; <>O.<0>__OnCopy = val8; obj5 = (object)val8; } ((UnityEvent)onClick).AddListener((UnityAction)obj5); ButtonClickedEvent onClick2 = obj3.onClick; object obj6 = <>O.<1>__OnSaveOrCopyDir; if (obj6 == null) { UnityAction val9 = OnSaveOrCopyDir; <>O.<1>__OnSaveOrCopyDir = val9; obj6 = (object)val9; } ((UnityEvent)onClick2).AddListener((UnityAction)obj6); ButtonClickedEvent onClick3 = val5.onClick; object obj7 = <>O.<2>__OnSend; if (obj7 == null) { UnityAction val10 = OnSend; <>O.<2>__OnSend = val10; obj7 = (object)val10; } ((UnityEvent)onClick3).AddListener((UnityAction)obj7); ButtonClickedEvent onClick4 = val6.onClick; object obj8 = <>O.<3>__OnDiscard; if (obj8 == null) { UnityAction val11 = OnDiscard; <>O.<3>__OnDiscard = val11; obj8 = (object)val11; } ((UnityEvent)onClick4).AddListener((UnityAction)obj8); ButtonClickedEvent onClick5 = val7.onClick; object obj9 = <>O.<4>__OnDone; if (obj9 == null) { UnityAction val12 = OnDone; <>O.<4>__OnDone = val12; obj9 = (object)val12; } ((UnityEvent)onClick5).AddListener((UnityAction)obj9); ((Selectable)val5).interactable = !string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl); float num6 = num + num2 + num3 + num4 + num5 + 32f; obj.sizeDelta = new Vector2(num6, 38f); float num7 = Mathf.Max(w, num6) + 24f; float num8 = h + 38f + 22f + ((TMP_Text)_statusText).rectTransform.sizeDelta.y + ((HorizontalOrVerticalLayoutGroup)val2).spacing * 3f + 24f; val.sizeDelta = new Vector2(num7, num8); _containerObj.SetActive(true); } } public static void Hide() { if ((Object)(object)_previewTex != (Object)null) { Object.Destroy((Object)(object)_previewTex); _previewTex = null; } if ((Object)(object)_containerObj != (Object)null) { Object.Destroy((Object)(object)_containerObj); _containerObj = null; } _result = null; _statusText = null; _saveBtnText = null; _savedFilePath = null; _saveInProgress = false; } public static void HideKeepingResult() { MapCompositor.CompiledMap result = _result; string savedFilePath = _savedFilePath; Hide(); _result = result; _savedFilePath = savedFilePath; } private static void OnCopy() { if (_result != null) { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null)) { instance.CopyBytesToClipboard(_result.PngBytes); SetStatus("Image copied to clipboard."); } } } private static void OnSaveOrCopyDir() { if (_savedFilePath == null) { DoSave(); } else { DoCopyDir(); } } private static void DoSave() { if (_result != null && !_saveInProgress) { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null)) { ((MonoBehaviour)instance).StartCoroutine(SaveFullResCoroutine()); } } } private static IEnumerator SaveFullResCoroutine() { _saveInProgress = true; SetStatus("Saving full-resolution map…"); MapCompositor.CompiledMap result = _result; if (result == null) { _saveInProgress = false; yield break; } List tiles = new List(MapCompileSession.Tiles); float refScreenW; List pins = MapCompilePinSnapshot.Capture(out refScreenW); MapCompositor.CompiledMap full = null; Exception error = null; MapCompositor.EncodeOptions saveOpts = Plugin.GetEncodeOptions(); if (tiles.Count > 0) { ManualResetEventSlim done = new ManualResetEventSlim(initialState: false); ThreadPool.QueueUserWorkItem(delegate { try { full = MapCompositor.ComposeNative(tiles); } catch (Exception ex2) { error = ex2; } finally { done.Set(); } }); while (!done.IsSet) { yield return null; } done.Dispose(); if (error == null && full != null) { yield return MapCompileLabelStamp.Finalize(full, pins, tiles, refScreenW, saveOpts); if (full.PngBytes == null) { error = new Exception("full-res encode produced no PNG"); } } } byte[] pngBytes; int width; int height; bool flag; string extension; if (error == null && full != null) { pngBytes = full.PngBytes; width = full.Width; height = full.Height; flag = full.WasClamped; extension = full.Extension; } else { if (error != null) { ModLog.Error("[NoMapDiscordAdditions] Full-res recompose failed: " + error.Message); } pngBytes = result.PngBytes; width = result.Width; height = result.Height; flag = true; extension = result.Extension; } try { MapCompileEnvironment.EnsureDirectory(MapCompileEnvironment.CompiledOutDir); string text = DateTime.Now.ToString("yyyyMMdd-HHmmss"); Player localPlayer = Player.m_localPlayer; string text2 = Sanitize(((localPlayer != null) ? localPlayer.GetPlayerName() : null) ?? "player"); string path = $"{text2}_compiled_{result.TileCount}tiles_{width}x{height}_{text}{extension}"; _savedFilePath = Path.Combine(MapCompileEnvironment.CompiledOutDir, path); File.WriteAllBytes(_savedFilePath, pngBytes); if ((Object)(object)_saveBtnText != (Object)null) { ((TMP_Text)_saveBtnText).text = "COPY DIR"; } string text3 = (flag ? "downscaled to fit 8192" : "native resolution"); string text4 = DescribeFormat(saveOpts, extension); string text5 = FormatBytes(pngBytes.LongLength); SetStatus($"Saved {width}×{height}px {text4} {text5} ({text3}) to {SanitizePathForDisplay(_savedFilePath)}"); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, $"Compiled map saved ({width}×{height}, {text4} {text5}).", 0, (Sprite)null); } } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Save failed: " + ex.Message); SetStatus("Save failed — see log."); } _saveInProgress = false; } private static string DescribeFormat(MapCompositor.EncodeOptions opts, string ext) { return opts.Format switch { MapCompositor.EncodeFormat.Jpeg => $"JPEG q{opts.JpegQuality}", MapCompositor.EncodeFormat.IndexedPng => $"PNG-{opts.IndexedPngColors}c", _ => ext.TrimStart(new char[1] { '.' }).ToUpperInvariant(), }; } private static string FormatBytes(long bytes) { if (bytes < 1024) { return $"{bytes} B"; } if (bytes < 1048576) { return $"{(double)bytes / 1024.0:0.#} KB"; } if (bytes < 1073741824) { return $"{(double)bytes / 1048576.0:0.##} MB"; } return $"{(double)bytes / 1073741824.0:0.##} GB"; } private static void DoCopyDir() { string compiledOutDir = MapCompileEnvironment.CompiledOutDir; try { MapCompileEnvironment.EnsureDirectory(compiledOutDir); SetStatus(Plugin.CopyTextToClipboard(compiledOutDir) ? ("Directory copied to clipboard: " + SanitizePathForDisplay(compiledOutDir)) : "Copy directory failed — see log."); } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Copy dir failed: " + ex.Message); SetStatus("Copy directory failed — see log."); } } private static void OnSend() { if (_result == null) { return; } Plugin instance = Plugin.Instance; if ((Object)(object)instance == (Object)null) { return; } if (string.IsNullOrEmpty(ModHelpers.EffectiveConfig.WebhookUrl)) { SetStatus("No webhook URL configured."); return; } SetStatus("Sending to Discord..."); instance.SendCompiledImage(_result.PngBytes, _result.TileCount, delegate(bool ok) { SetStatus(ok ? "Sent to Discord." : "Send failed — see log."); }); } private static void OnDiscard() { Hide(); MapCompileSession.Discard(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Compiled map discarded.", 0, (Sprite)null); } } private static void OnDone() { Hide(); MapCompileSession.ReturnToCompiling(); } private static TextMeshProUGUI CreateLabel(string text, float size) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Label"); val.SetActive(false); val.transform.SetParent(_containerObj.transform, false); RectTransform val2 = val.AddComponent(); TextMeshProUGUI obj = val.AddComponent(); ((TMP_Text)obj).text = text; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0; MapUI.ApplyValheimFont((TMP_Text)(object)obj); ((TMP_Text)obj).fontSize = size; ((Graphic)obj).color = MapUI.LabelColor; val2.sizeDelta = new Vector2(360f, size + 8f); val.SetActive(true); return obj; } private static void SetStatus(string s) { if ((Object)(object)_statusText != (Object)null) { ((TMP_Text)_statusText).text = s; } } private static void ComputePreviewSize(int srcW, int srcH, out float w, out float h) { float num = (float)srcW / (float)Mathf.Max(1, srcH); if (num >= 1f) { w = 360f; h = 360f / num; } else { h = 360f; w = 360f * num; } } private static Texture2D DecodePngToTexture(byte[] pngBytes) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) using MemoryStream memoryStream = new MemoryStream(pngBytes); Bitmap val = new Bitmap((Stream)memoryStream); try { int width = ((Image)val).Width; int height = ((Image)val).Height; Texture2D val2 = new Texture2D(width, height, (TextureFormat)4, false); Color32[] array = (Color32[])(object)new Color32[width * height]; Rectangle rectangle = new Rectangle(0, 0, width, height); BitmapData val3 = val.LockBits(rectangle, (ImageLockMode)1, (PixelFormat)2498570); try { int stride = val3.Stride; byte[] array2 = new byte[stride]; for (int i = 0; i < height; i++) { Marshal.Copy(new IntPtr(val3.Scan0.ToInt64() + (long)i * (long)stride), array2, 0, stride); int num = (height - 1 - i) * width; for (int j = 0; j < width; j++) { int num2 = j * 4; array[num + j] = new Color32(array2[num2 + 2], array2[num2 + 1], array2[num2], array2[num2 + 3]); } } } finally { val.UnlockBits(val3); } val2.SetPixels32(array); val2.Apply(); return val2; } finally { ((IDisposable)val)?.Dispose(); } } private static string Sanitize(string s) { if (string.IsNullOrEmpty(s)) { return "player"; } StringBuilder stringBuilder = new StringBuilder(s.Length); foreach (char c in s) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_') { stringBuilder.Append(c); } } if (stringBuilder.Length != 0) { return stringBuilder.ToString(); } return "player"; } private static string SanitizePathForDisplay(string path) { if (string.IsNullOrEmpty(path)) { return string.Empty; } string text = path.Replace('\\', '/'); string text2 = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)?.Replace('\\', '/'); if (!string.IsNullOrEmpty(text2) && text.StartsWith(text2, StringComparison.OrdinalIgnoreCase)) { text = "~" + text.Substring(text2.Length); } int num = text.IndexOf("/profiles/", StringComparison.OrdinalIgnoreCase); if (num >= 0) { text = ".../" + text.Substring(num + "/profiles/".Length); } return text; } } public static class MapCompileSession { public enum State { Idle, Compiling, Reviewing } private class SessionIndexDto { public int Version = 1; public string SessionKey; public List Tiles = new List(); } private class TileDto { public int Index; public string File; public float[] WorldMin; public float[] WorldMax; public float[] TablePos; public string TableName; public int PixelW; public int PixelH; public long TimestampMs; public bool FullyMapped = true; public string ImportKey; public string Src; } private static readonly List _tiles = new List(); private static string _sessionKey; private static string _sessionDir; private const float DedupRadius = 8f; private static readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings { Formatting = (Formatting)1, NullValueHandling = (NullValueHandling)1 }; public static State CurrentState { get; private set; } = State.Idle; public static IReadOnlyList Tiles => _tiles; public static Vector3? ActiveTablePos { get; private set; } public static string ActiveTableName { get; private set; } public static bool CanAddTile { get { if (CurrentState == State.Compiling) { return ActiveTablePos.HasValue; } return false; } } public static bool ActiveTableAlreadyAdded { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (CanAddTile) { return FindTileNearTable(ActiveTablePos.Value) >= 0; } return false; } } public static event Action StateChanged; public static void SetActiveTable(Vector3 worldPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) ActiveTablePos = worldPos; ActiveTableName = TablePinName.Resolve(worldPos); MapCompileSession.StateChanged?.Invoke(); } public static void ClearActiveTable() { if (ActiveTablePos.HasValue || ActiveTableName != null) { ActiveTablePos = null; ActiveTableName = null; MapCompileSession.StateChanged?.Invoke(); } } public static bool HasResumableSession() { if (CurrentState != 0) { return false; } if (!MapCompileEnvironment.HasSessionKey()) { return false; } return File.Exists(MapCompileEnvironment.GetSessionFile(MapCompileEnvironment.GetSessionDir(MapCompileEnvironment.GetSessionKey()))); } public static void Start() { if (CurrentState != 0) { return; } if (!MapCompileEnvironment.HasSessionKey()) { ModLog.Warn("[NoMapDiscordAdditions] Compile start aborted — session key unavailable."); return; } _sessionKey = MapCompileEnvironment.GetSessionKey(); _sessionDir = MapCompileEnvironment.GetSessionDir(_sessionKey); MapCompileEnvironment.EnsureDirectory(_sessionDir); _tiles.Clear(); CurrentState = State.Compiling; SaveIndex(); MapCompileSession.StateChanged?.Invoke(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Map compile started.", 0, (Sprite)null); } } public static bool Resume() { if (CurrentState != 0) { return false; } if (!MapCompileEnvironment.HasSessionKey()) { return false; } _sessionKey = MapCompileEnvironment.GetSessionKey(); _sessionDir = MapCompileEnvironment.GetSessionDir(_sessionKey); if (!File.Exists(MapCompileEnvironment.GetSessionFile(_sessionDir))) { return false; } _tiles.Clear(); try { LoadIndex(); } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Failed to resume compile session: " + ex.Message); _tiles.Clear(); return false; } CurrentState = State.Compiling; MapCompileSession.StateChanged?.Invoke(); string arg = ((_tiles.Count == 1) ? "tile" : "tiles"); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, $"Resumed compile session ({_tiles.Count} {arg}).", 0, (Sprite)null); } return true; } public static void AddTile(byte[] pngBytes, int width, int height, Vector2 worldMin, Vector2 worldMax, Vector3 tablePos, bool fullyMapped = true) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (CurrentState == State.Compiling && pngBytes != null && pngBytes.Length != 0) { int num = FindTileNearTable(tablePos); int index; if (num >= 0) { index = _tiles[num].Index; _tiles.RemoveAt(num); } else { index = NextTileIndex(); } string tileFile = MapCompileEnvironment.GetTileFile(_sessionDir, index); try { File.WriteAllBytes(tileFile, pngBytes); } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Tile write failed: " + ex.Message); return; } MapCompileTile item = new MapCompileTile { Index = index, WorldMin = worldMin, WorldMax = worldMax, TableWorldPos = tablePos, TableName = TablePinName.Resolve(tablePos), PixelWidth = width, PixelHeight = height, PngPath = tileFile, TimestampUnixMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), FullyMapped = fullyMapped }; _tiles.Add(item); SaveIndex(); MapCompileSession.StateChanged?.Invoke(); string arg = ((num >= 0) ? "updated" : "added"); string arg2 = (fullyMapped ? "" : " — partial map"); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, $"Tile {arg} ({_tiles.Count} total){arg2}", 0, (Sprite)null); } } } public static bool AddImportedTile(byte[] pngBytes, int width, int height, Vector2 worldMin, Vector2 worldMax, string importKey, string sourcePlayer, bool fullyMapped = true) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (CurrentState != State.Compiling) { return false; } if (pngBytes == null || pngBytes.Length == 0) { return false; } if (string.IsNullOrEmpty(importKey)) { return false; } if (string.IsNullOrEmpty(_sessionDir)) { return false; } int num = FindTileByImportKey(importKey); int index; if (num >= 0) { index = _tiles[num].Index; _tiles.RemoveAt(num); } else { index = NextTileIndex(); } string tileFile = MapCompileEnvironment.GetTileFile(_sessionDir, index); try { File.WriteAllBytes(tileFile, pngBytes); } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Imported tile write failed: " + ex.Message); return false; } _tiles.Add(new MapCompileTile { Index = index, WorldMin = worldMin, WorldMax = worldMax, TableWorldPos = new Vector3(1E+09f, 0f, 1E+09f), PixelWidth = width, PixelHeight = height, PngPath = tileFile, TimestampUnixMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), FullyMapped = fullyMapped, ImportKey = importKey, SourcePlayer = (string.IsNullOrEmpty(sourcePlayer) ? "unknown" : sourcePlayer) }); SaveIndex(); MapCompileSession.StateChanged?.Invoke(); return true; } public static bool RemoveActiveTableTile() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (CurrentState != State.Compiling) { return false; } if (!ActiveTablePos.HasValue) { return false; } int num = FindTileNearTable(ActiveTablePos.Value); if (num < 0) { return false; } MapCompileTile mapCompileTile = _tiles[num]; try { if (!string.IsNullOrEmpty(mapCompileTile.PngPath) && File.Exists(mapCompileTile.PngPath)) { File.Delete(mapCompileTile.PngPath); } } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Tile PNG delete failed: " + ex.Message); } _tiles.RemoveAt(num); SaveIndex(); MapCompileSession.StateChanged?.Invoke(); string arg = ((_tiles.Count == 1) ? "tile" : "tiles"); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, $"Tile removed ({_tiles.Count} {arg}).", 0, (Sprite)null); } return true; } public static void Finish() { if (CurrentState != State.Compiling) { return; } if (_tiles.Count == 0) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "No tiles to compile.", 0, (Sprite)null); } } else { CurrentState = State.Reviewing; MapCompileSession.StateChanged?.Invoke(); } } public static void Suspend() { if (CurrentState == State.Idle) { return; } if (_tiles.Count == 0) { Discard(); return; } _tiles.Clear(); _sessionKey = null; _sessionDir = null; CurrentState = State.Idle; MapCompileSession.StateChanged?.Invoke(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Compile session saved — resume any time.", 0, (Sprite)null); } } public static void Discard() { _tiles.Clear(); try { if (!string.IsNullOrEmpty(_sessionDir) && Directory.Exists(_sessionDir)) { Directory.Delete(_sessionDir, recursive: true); } } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Failed to clean session dir: " + ex.Message); } _sessionKey = null; _sessionDir = null; CurrentState = State.Idle; MapCompileSession.StateChanged?.Invoke(); } public static bool ClearSession() { string sessionDir = _sessionDir; if (string.IsNullOrEmpty(sessionDir) && MapCompileEnvironment.HasSessionKey()) { sessionDir = MapCompileEnvironment.GetSessionDir(MapCompileEnvironment.GetSessionKey()); } bool flag = _tiles.Count > 0 || (!string.IsNullOrEmpty(sessionDir) && Directory.Exists(sessionDir)); _tiles.Clear(); try { if (!string.IsNullOrEmpty(sessionDir) && Directory.Exists(sessionDir)) { Directory.Delete(sessionDir, recursive: true); } } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Failed to clear session dir: " + ex.Message); } _sessionKey = null; _sessionDir = null; CurrentState = State.Idle; MapCompileSession.StateChanged?.Invoke(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, flag ? "Compile session cleared." : "No compile session to clear.", 0, (Sprite)null); } return flag; } public static void ReturnToCompiling() { if (CurrentState == State.Reviewing) { CurrentState = State.Compiling; MapCompileSession.StateChanged?.Invoke(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Compile session kept — resume any time.", 0, (Sprite)null); } } } private static int NextTileIndex() { int num = -1; foreach (MapCompileTile tile in _tiles) { if (tile.Index > num) { num = tile.Index; } } return num + 1; } private static int FindTileByImportKey(string importKey) { for (int i = 0; i < _tiles.Count; i++) { if (_tiles[i].ImportKey == importKey) { return i; } } return -1; } private static int FindTileNearTable(Vector3 tablePos) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _tiles.Count; i++) { MapCompileTile mapCompileTile = _tiles[i]; if (!mapCompileTile.IsImported) { float num = mapCompileTile.TableWorldPos.x - tablePos.x; float num2 = mapCompileTile.TableWorldPos.z - tablePos.z; if (num * num + num2 * num2 <= 64f) { return i; } } } return -1; } private static void SaveIndex() { if (string.IsNullOrEmpty(_sessionDir)) { return; } string sessionFile = MapCompileEnvironment.GetSessionFile(_sessionDir); string text = sessionFile + ".tmp"; SessionIndexDto sessionIndexDto = new SessionIndexDto { SessionKey = _sessionKey }; foreach (MapCompileTile tile in _tiles) { sessionIndexDto.Tiles.Add(new TileDto { Index = tile.Index, File = $"tile_{tile.Index:D3}.png", WorldMin = new float[2] { tile.WorldMin.x, tile.WorldMin.y }, WorldMax = new float[2] { tile.WorldMax.x, tile.WorldMax.y }, TablePos = new float[3] { tile.TableWorldPos.x, tile.TableWorldPos.y, tile.TableWorldPos.z }, TableName = tile.TableName, PixelW = tile.PixelWidth, PixelH = tile.PixelHeight, TimestampMs = tile.TimestampUnixMs, FullyMapped = tile.FullyMapped, ImportKey = tile.ImportKey, Src = tile.SourcePlayer }); } try { string contents = JsonConvert.SerializeObject((object)sessionIndexDto, _jsonSettings); File.WriteAllText(text, contents, Encoding.UTF8); if (File.Exists(sessionFile)) { File.Delete(sessionFile); } File.Move(text, sessionFile); } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] SaveIndex failed: " + ex.Message); } } private static void LoadIndex() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) SessionIndexDto sessionIndexDto = JsonConvert.DeserializeObject(File.ReadAllText(MapCompileEnvironment.GetSessionFile(_sessionDir), Encoding.UTF8)); if (sessionIndexDto == null || sessionIndexDto.Tiles == null) { return; } foreach (TileDto tile in sessionIndexDto.Tiles) { if (tile.WorldMin == null || tile.WorldMin.Length < 2 || tile.WorldMax == null || tile.WorldMax.Length < 2 || tile.TablePos == null || tile.TablePos.Length < 3) { ModLog.Warn($"[NoMapDiscordAdditions] Tile {tile.Index} has malformed vector data — skipping."); continue; } string tileFile = MapCompileEnvironment.GetTileFile(_sessionDir, tile.Index); if (!File.Exists(tileFile)) { ModLog.Warn("[NoMapDiscordAdditions] Tile PNG missing: " + tileFile + " — skipping."); continue; } _tiles.Add(new MapCompileTile { Index = tile.Index, WorldMin = new Vector2(tile.WorldMin[0], tile.WorldMin[1]), WorldMax = new Vector2(tile.WorldMax[0], tile.WorldMax[1]), TableWorldPos = new Vector3(tile.TablePos[0], tile.TablePos[1], tile.TablePos[2]), TableName = tile.TableName, PixelWidth = tile.PixelW, PixelHeight = tile.PixelH, PngPath = tileFile, TimestampUnixMs = tile.TimestampMs, FullyMapped = tile.FullyMapped, ImportKey = tile.ImportKey, SourcePlayer = tile.Src }); } } } public class MapCompileTile { public int Index; public Vector2 WorldMin; public Vector2 WorldMax; public Vector3 TableWorldPos; public string TableName; public int PixelWidth; public int PixelHeight; public string PngPath; public long TimestampUnixMs; public bool FullyMapped = true; public string ImportKey; public string SourcePlayer; public bool IsImported => ImportKey != null; public Vector2 WorldSize => WorldMax - WorldMin; public static void ComputeWorldRect(Minimap minimap, Rect uvRect, out Vector2 worldMin, out Vector2 worldMax) { //IL_0037: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp01(((Rect)(ref uvRect)).xMin); float num2 = Mathf.Clamp01(((Rect)(ref uvRect)).yMin); float num3 = Mathf.Clamp01(((Rect)(ref uvRect)).xMax); float num4 = Mathf.Clamp01(((Rect)(ref uvRect)).yMax); Vector3 val = minimap.MapPointToWorld(num, num2); Vector3 val2 = minimap.MapPointToWorld(num3, num4); worldMin = new Vector2(val.x, val.z); worldMax = new Vector2(val2.x, val2.z); } } public static class MapCompositor { public enum EncodeFormat { Png, Jpeg, IndexedPng } public struct EncodeOptions { public EncodeFormat Format; public int JpegQuality; public int IndexedPngColors; public static EncodeOptions Default { get { EncodeOptions result = default(EncodeOptions); result.Format = EncodeFormat.Png; result.JpegQuality = 88; result.IndexedPngColors = 64; return result; } } public string Extension { get { if (Format != EncodeFormat.Jpeg) { return ".png"; } return ".jpg"; } } } public class CompiledMap { public byte[] PngBytes; public string Extension = ".png"; internal byte[] Bgra; public Vector2 WorldMin; public Vector2 WorldMax; public int Width; public int Height; public int TileCount; public bool WasClamped; } public struct PinDraw { public float WorldX; public float WorldZ; public Sprite Icon; public Color32 Tint; public float ScreenPxW; public float ScreenPxH; public string Name; } private struct MedianCutBox { public byte RMin; public byte RMax; public byte GMin; public byte GMax; public byte BMin; public byte BMax; public int PixelCount; public bool IsAtomic; public int LongestExtent { get { int val = RMax - RMin; int val2 = GMax - GMin; int val3 = BMax - BMin; return Math.Max(val, Math.Max(val2, val3)); } } public void Init(int[] counts, long[] sumR, long[] sumG, long[] sumB) { RMin = 31; GMin = 31; BMin = 31; RMax = 0; GMax = 0; BMax = 0; long num = 0L; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { for (int k = 0; k < 32; k++) { int num2 = (i << 10) | (j << 5) | k; if (counts[num2] != 0) { if (i < RMin) { RMin = (byte)i; } if (i > RMax) { RMax = (byte)i; } if (j < GMin) { GMin = (byte)j; } if (j > GMax) { GMax = (byte)j; } if (k < BMin) { BMin = (byte)k; } if (k > BMax) { BMax = (byte)k; } num += counts[num2]; } } } } if (num == 0L) { RMin = (GMin = (BMin = 0)); RMax = (GMax = (BMax = 0)); } PixelCount = (int)Math.Min(num, 2147483647L); } public bool TrySplit(int[] counts, long[] sumR, long[] sumG, long[] sumB, out MedianCutBox left, out MedianCutBox right) { left = default(MedianCutBox); right = default(MedianCutBox); int num = RMax - RMin; int num2 = GMax - GMin; int num3 = BMax - BMin; int num4 = 0; if (num2 >= num && num2 >= num3) { num4 = 1; } else if (num3 >= num && num3 >= num2) { num4 = 2; } int num5 = num4 switch { 1 => GMin, 0 => RMin, _ => BMin, }; int num6 = num4 switch { 1 => GMax, 0 => RMax, _ => BMax, }; if (num6 <= num5) { return false; } int[] array = new int[32]; AccumulateAxis(counts, num4, array); long num7 = PixelCount / 2; long num8 = 0L; int num9 = num5; for (int i = num5; i <= num6; i++) { num8 += array[i]; if (num8 >= num7) { num9 = i; break; } } if (num9 >= num6) { num9 = num6 - 1; } if (num9 < num5) { num9 = num5; } left = this; right = this; switch (num4) { case 0: left.RMax = (byte)num9; right.RMin = (byte)(num9 + 1); break; case 1: left.GMax = (byte)num9; right.GMin = (byte)(num9 + 1); break; default: left.BMax = (byte)num9; right.BMin = (byte)(num9 + 1); break; } left.PixelCount = (int)Math.Min(2147483647L, SumIn(counts, ref left)); right.PixelCount = (int)Math.Min(2147483647L, SumIn(counts, ref right)); left.IsAtomic = false; right.IsAtomic = false; if (left.PixelCount == 0 || right.PixelCount == 0) { return false; } return true; } private void AccumulateAxis(int[] counts, int axis, int[] pop) { for (int i = RMin; i <= RMax; i++) { for (int j = GMin; j <= GMax; j++) { for (int k = BMin; k <= BMax; k++) { int num = counts[(i << 10) | (j << 5) | k]; if (num != 0) { pop[axis switch { 1 => j, 0 => i, _ => k, }] += num; } } } } } private static long SumIn(int[] counts, ref MedianCutBox box) { long num = 0L; for (int i = box.RMin; i <= box.RMax; i++) { for (int j = box.GMin; j <= box.GMax; j++) { for (int k = box.BMin; k <= box.BMax; k++) { num += counts[(i << 10) | (j << 5) | k]; } } } return num; } public void MeanColor(int[] counts, long[] sumR, long[] sumG, long[] sumB, out byte r, out byte g, out byte b) { long num = 0L; long num2 = 0L; long num3 = 0L; long num4 = 0L; for (int i = RMin; i <= RMax; i++) { for (int j = GMin; j <= GMax; j++) { for (int k = BMin; k <= BMax; k++) { int num5 = (i << 10) | (j << 5) | k; int num6 = counts[num5]; if (num6 != 0) { num += num6; num2 += sumR[num5]; num3 += sumG[num5]; num4 += sumB[num5]; } } } } if (num == 0L) { r = (g = (b = 0)); return; } r = (byte)Math.Min(255L, Math.Max(0L, num2 / num)); g = (byte)Math.Min(255L, Math.Max(0L, num3 / num)); b = (byte)Math.Min(255L, Math.Max(0L, num4 / num)); } } private const int NativeMaxDim = 8192; public static CompiledMap Compose(IReadOnlyList tiles, int maxDimensionPx) { //IL_0021: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!ComputeBounds(tiles, out var worldMin, out var worldMax, out var worldSize)) { return null; } int num = Mathf.Clamp(maxDimensionPx, 512, 8192); float num2 = worldSize.x / worldSize.y; int outW; int outH; if (num2 >= 1f) { outW = num; outH = Mathf.Max(1, Mathf.RoundToInt((float)num / num2)); } else { outH = num; outW = Mathf.Max(1, Mathf.RoundToInt((float)num * num2)); } return Render(tiles, worldMin, worldMax, worldSize, outW, outH, wasClamped: false); } public static CompiledMap ComposeNative(IReadOnlyList tiles) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) if (!ComputeBounds(tiles, out var worldMin, out var worldMax, out var worldSize)) { return null; } double num = 0.0; foreach (MapCompileTile tile in tiles) { float num2 = tile.WorldMax.x - tile.WorldMin.x; float num3 = tile.WorldMax.y - tile.WorldMin.y; if (num2 > 0f && tile.PixelWidth > 0) { num = Math.Max(num, (double)tile.PixelWidth / (double)num2); } if (num3 > 0f && tile.PixelHeight > 0) { num = Math.Max(num, (double)tile.PixelHeight / (double)num3); } } if (num <= 0.0) { num = 1.0; } double num4 = (double)worldSize.x * num; double num5 = (double)worldSize.y * num; bool wasClamped = false; double num6 = Math.Max(num4, num5); if (num6 > 8192.0) { double num7 = 8192.0 / num6; num4 *= num7; num5 *= num7; wasClamped = true; } int outW = (int)Math.Min(8192.0, Math.Max(512.0, Math.Round(num4))); int outH = (int)Math.Min(8192.0, Math.Max(512.0, Math.Round(num5))); return Render(tiles, worldMin, worldMax, worldSize, outW, outH, wasClamped); } private static bool ComputeBounds(IReadOnlyList tiles, out Vector2 worldMin, out Vector2 worldMax, out Vector2 worldSize) { //IL_0003: 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) //IL_0009: 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) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) worldMin = (worldMax = (worldSize = Vector2.zero)); if (tiles == null || tiles.Count == 0) { return false; } worldMin = tiles[0].WorldMin; worldMax = tiles[0].WorldMax; for (int i = 1; i < tiles.Count; i++) { worldMin = Vector2.Min(worldMin, tiles[i].WorldMin); worldMax = Vector2.Max(worldMax, tiles[i].WorldMax); } worldSize = worldMax - worldMin; if (worldSize.x <= 0f || worldSize.y <= 0f) { ModLog.Error("[NoMapDiscordAdditions] Composer: degenerate world bounds."); return false; } return true; } private static CompiledMap Render(IReadOnlyList tiles, Vector2 worldMin, Vector2 worldMax, Vector2 worldSize, int outW, int outH, bool wasClamped) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) byte[] array = new byte[outW * 4 * outH]; bool[] array2 = new bool[outW * outH]; bool[] fromFull = new bool[outW * outH]; foreach (MapCompileTile tile in tiles) { CompositeTile(tile, array, array2, fromFull, outW, outH, worldMin, worldMax); } for (int i = 0; i < array2.Length; i++) { if (!array2[i]) { array[i * 4 + 3] = byte.MaxValue; } } return new CompiledMap { Bgra = array, PngBytes = null, WorldMin = worldMin, WorldMax = worldMax, Width = outW, Height = outH, TileCount = tiles.Count, WasClamped = wasClamped }; } private static void CompositeTile(MapCompileTile tile, byte[] outBuf, bool[] covered, bool[] fromFull, int outW, int outH, Vector2 worldMin, Vector2 worldMax) { //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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown bool fullyMapped = tile.FullyMapped; if (!File.Exists(tile.PngPath)) { ModLog.Warn("[NoMapDiscordAdditions] Tile PNG missing during compose: " + tile.PngPath); return; } Vector2 val = worldMax - worldMin; float num = (tile.WorldMin.x - worldMin.x) / val.x; float num2 = (tile.WorldMax.x - worldMin.x) / val.x; float num3 = (worldMax.y - tile.WorldMax.y) / val.y; float num4 = (worldMax.y - tile.WorldMin.y) / val.y; int num5 = Mathf.Clamp(Mathf.FloorToInt(num * (float)outW), 0, outW); int num6 = Mathf.Clamp(Mathf.CeilToInt(num2 * (float)outW), 0, outW); int num7 = Mathf.Clamp(Mathf.FloorToInt(num3 * (float)outH), 0, outH); int num8 = Mathf.Clamp(Mathf.CeilToInt(num4 * (float)outH), 0, outH); int num9 = num6 - num5; int num10 = num8 - num7; if (num9 <= 0 || num10 <= 0) { return; } byte[] array; try { Bitmap val2 = LoadBitmap(tile.PngPath); try { Bitmap val3 = new Bitmap(num9, num10, (PixelFormat)2498570); try { Graphics val4 = Graphics.FromImage((Image)(object)val3); try { val4.InterpolationMode = (InterpolationMode)6; val4.PixelOffsetMode = (PixelOffsetMode)4; val4.CompositingMode = (CompositingMode)1; val4.DrawImage((Image)(object)val2, new Rectangle(0, 0, num9, num10)); } finally { ((IDisposable)val4)?.Dispose(); } array = ExtractBgra(val3); } finally { ((IDisposable)val3)?.Dispose(); } } finally { ((IDisposable)val2)?.Dispose(); } } catch (Exception ex) { ModLog.Error("[NoMapDiscordAdditions] Tile decode/resize failed (" + tile.PngPath + "): " + ex.Message); return; } int num11 = outW * 4; int num12 = num9 * 4; for (int i = 0; i < num10; i++) { int num13 = (num7 + i) * num11 + num5 * 4; int num14 = i * num12; int num15 = (num7 + i) * outW + num5; for (int j = 0; j < num9; j++) { int num16 = num13 + j * 4; int num17 = num14 + j * 4; int num18 = num15 + j; byte b = array[num17]; byte b2 = array[num17 + 1]; byte b3 = array[num17 + 2]; if (!covered[num18]) { outBuf[num16] = b; outBuf[num16 + 1] = b2; outBuf[num16 + 2] = b3; outBuf[num16 + 3] = byte.MaxValue; covered[num18] = true; fromFull[num18] = fullyMapped; continue; } bool flag = fromFull[num18]; if (fullyMapped != flag) { if (fullyMapped) { outBuf[num16] = b; outBuf[num16 + 1] = b2; outBuf[num16 + 2] = b3; fromFull[num18] = true; } continue; } byte b4 = outBuf[num16]; byte g = outBuf[num16 + 1]; int num19 = Chroma(outBuf[num16 + 2], g, b4); if (Chroma(b3, b2, b) > num19) { outBuf[num16] = b; outBuf[num16 + 1] = b2; outBuf[num16 + 2] = b3; } } } } private static int Chroma(byte r, byte g, byte b) { byte num = ((r <= g) ? ((g > b) ? g : b) : ((r > b) ? r : b)); int num2 = ((r >= g) ? ((g < b) ? g : b) : ((r < b) ? r : b)); return num - num2; } private static Bitmap LoadBitmap(string path) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(path)); return new Bitmap((Stream)memoryStream); } private static byte[] ExtractBgra(Bitmap bmp) { int width = ((Image)bmp).Width; int height = ((Image)bmp).Height; byte[] array = new byte[width * height * 4]; Rectangle rectangle = new Rectangle(0, 0, width, height); BitmapData val = bmp.LockBits(rectangle, (ImageLockMode)1, (PixelFormat)2498570); try { int stride = val.Stride; int num = width * 4; for (int i = 0; i < height; i++) { Marshal.Copy(new IntPtr(val.Scan0.ToInt64() + (long)i * (long)stride), array, i * num, num); } return array; } finally { bmp.UnlockBits(val); } } internal static byte[] EncodeBgra(byte[] bgra, int w, int h) { return EncodeBgra(bgra, w, h, EncodeOptions.Default); } internal static byte[] EncodeBgra(byte[] bgra, int w, int h, EncodeOptions opts) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (opts.Format == EncodeFormat.IndexedPng) { return EncodeIndexedPngFromBgra(bgra, w, h, opts.IndexedPngColors); } Bitmap val = new Bitmap(w, h, (PixelFormat)137224); try { Rectangle rectangle = new Rectangle(0, 0, w, h); BitmapData val2 = val.LockBits(rectangle, (ImageLockMode)2, (PixelFormat)137224); try { int stride = val2.Stride; byte[] array = new byte[stride]; for (int i = 0; i < h; i++) { int num = i * w * 4; for (int j = 0; j < w; j++) { int num2 = num + j * 4; int num3 = j * 3; array[num3] = bgra[num2]; array[num3 + 1] = bgra[num2 + 1]; array[num3 + 2] = bgra[num2 + 2]; } IntPtr destination = new IntPtr(val2.Scan0.ToInt64() + (long)i * (long)stride); Marshal.Copy(array, 0, destination, stride); } } finally { val.UnlockBits(val2); } return SaveBitmap(val, opts); } finally { ((IDisposable)val)?.Dispose(); } } internal static byte[] EncodeRgbaBottomUp(Color32[] rgba, int w, int h) { return EncodeRgbaBottomUp(rgba, w, h, EncodeOptions.Default); } internal static byte[] EncodeRgbaBottomUp(Color32[] rgba, int w, int h, EncodeOptions opts) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (opts.Format == EncodeFormat.IndexedPng) { return EncodeIndexedPngFromRgbaBottomUp(rgba, w, h, opts.IndexedPngColors); } Bitmap val = new Bitmap(w, h, (PixelFormat)137224); try { Rectangle rectangle = new Rectangle(0, 0, w, h); BitmapData val2 = val.LockBits(rectangle, (ImageLockMode)2, (PixelFormat)137224); try { int stride = val2.Stride; byte[] array = new byte[stride]; for (int i = 0; i < h; i++) { int num = (h - 1 - i) * w; for (int j = 0; j < w; j++) { Color32 val3 = rgba[num + j]; int num2 = j * 3; array[num2] = val3.b; array[num2 + 1] = val3.g; array[num2 + 2] = val3.r; } IntPtr destination = new IntPtr(val2.Scan0.ToInt64() + (long)i * (long)stride); Marshal.Copy(array, 0, destination, stride); } } finally { val.UnlockBits(val2); } return SaveBitmap(val, opts); } finally { ((IDisposable)val)?.Dispose(); } } public static byte[] Recode(byte[] inputBytes, EncodeOptions opts, int maxDim = 0) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown if (inputBytes == null || inputBytes.Length == 0) { return inputBytes; } try { using MemoryStream memoryStream = new MemoryStream(inputBytes); Bitmap val = new Bitmap((Stream)memoryStream); try { int num = ((Image)val).Width; int num2 = ((Image)val).Height; Bitmap val2 = null; try { Bitmap bmp = val; if (maxDim > 0 && Math.Max(num, num2) > maxDim) { float num3 = (float)maxDim / (float)Math.Max(num, num2); int num4 = Math.Max(1, (int)Math.Round((float)num * num3)); int num5 = Math.Max(1, (int)Math.Round((float)num2 * num3)); val2 = new Bitmap(num4, num5, (PixelFormat)2498570); Graphics val3 = Graphics.FromImage((Image)(object)val2); try { val3.InterpolationMode = (InterpolationMode)6; val3.PixelOffsetMode = (PixelOffsetMode)4; val3.CompositingMode = (CompositingMode)1; val3.DrawImage((Image)(object)val, 0, 0, num4, num5); } finally { ((IDisposable)val3)?.Dispose(); } num = num4; num2 = num5; bmp = val2; } byte[] array = EncodeBgra(ExtractBgra(bmp), num, num2, opts); ModLog.Info($"[NoMapDiscordAdditions] Recoded {inputBytes.Length} -> {array.Length} bytes " + $"({num}×{num2}, format={opts.Format})."); return array; } finally { if (val2 != null) { ((Image)val2).Dispose(); } } } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Recode failed, returning original bytes: " + ex.Message); return inputBytes; } } private static byte[] SaveBitmap(Bitmap bmp, EncodeOptions opts) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown using MemoryStream memoryStream = new MemoryStream(); if (opts.Format == EncodeFormat.Jpeg) { ImageCodecInfo jpegEncoder = GetJpegEncoder(); if (jpegEncoder != null) { int num = Math.Min(100, Math.Max(1, opts.JpegQuality)); EncoderParameters val = new EncoderParameters(1); try { val.Param[0] = new EncoderParameter(Encoder.Quality, (long)num); ((Image)bmp).Save((Stream)memoryStream, jpegEncoder, val); return memoryStream.ToArray(); } finally { ((IDisposable)val)?.Dispose(); } } ((Image)bmp).Save((Stream)memoryStream, ImageFormat.Jpeg); return memoryStream.ToArray(); } ((Image)bmp).Save((Stream)memoryStream, ImageFormat.Png); return memoryStream.ToArray(); } private static ImageCodecInfo GetJpegEncoder() { ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); foreach (ImageCodecInfo val in imageEncoders) { if (val.FormatID == ImageFormat.Jpeg.Guid) { return val; } } return null; } private static byte[] EncodeIndexedPngFromBgra(byte[] bgra, int w, int h, int maxColors) { int num = w * h; byte[] array = new byte[num * 3]; for (int i = 0; i < num; i++) { int num2 = i * 4; int num3 = i * 3; array[num3] = bgra[num2 + 2]; array[num3 + 1] = bgra[num2 + 1]; array[num3 + 2] = bgra[num2]; } return EncodeIndexedPng(array, w, h, maxColors); } private static byte[] EncodeIndexedPngFromRgbaBottomUp(Color32[] rgba, int w, int h, int maxColors) { //IL_0027: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) byte[] array = new byte[w * h * 3]; for (int i = 0; i < h; i++) { int num = (h - 1 - i) * w; int num2 = i * w * 3; for (int j = 0; j < w; j++) { Color32 val = rgba[num + j]; int num3 = num2 + j * 3; array[num3] = val.r; array[num3 + 1] = val.g; array[num3 + 2] = val.b; } } return EncodeIndexedPng(array, w, h, maxColors); } private static byte[] EncodeIndexedPng(byte[] rgbTopDown, int w, int h, int maxColors) { maxColors = Math.Min(256, Math.Max(2, maxColors)); int[] array = new int[32768]; long[] array2 = new long[32768]; long[] array3 = new long[32768]; long[] array4 = new long[32768]; int num = w * h; for (int i = 0; i < num; i++) { int num2 = i * 3; byte b = rgbTopDown[num2]; byte b2 = rgbTopDown[num2 + 1]; byte b3 = rgbTopDown[num2 + 2]; int num3 = (b >> 3 << 10) | (b2 >> 3 << 5) | (b3 >> 3); array[num3]++; array2[num3] += b; array3[num3] += b2; array4[num3] += b3; } List list = new List(maxColors); MedianCutBox item = default(MedianCutBox); item.Init(array, array2, array3, array4); if (item.PixelCount == 0) { return EncodeIndexedPngWithPalette(rgbTopDown, w, h, new byte[3], new int[32768], 1); } list.Add(item); while (list.Count < maxColors) { int num4 = -1; long num5 = -1L; for (int j = 0; j < list.Count; j++) { MedianCutBox medianCutBox = list[j]; if (!medianCutBox.IsAtomic) { long num6 = (long)medianCutBox.LongestExtent * (long)medianCutBox.PixelCount; if (num6 > num5) { num5 = num6; num4 = j; } } } if (num4 < 0) { break; } MedianCutBox value = list[num4]; if (!value.TrySplit(array, array2, array3, array4, out var left, out var right)) { value.IsAtomic = true; list[num4] = value; } else { list[num4] = left; list.Add(right); } } int count = list.Count; byte[] array5 = new byte[count * 3]; for (int k = 0; k < count; k++) { list[k].MeanColor(array, array2, array3, array4, out var r, out var g, out var b4); array5[k * 3] = r; array5[k * 3 + 1] = g; array5[k * 3 + 2] = b4; } int[] array6 = new int[32768]; for (int l = 0; l < 32; l++) { for (int m = 0; m < 32; m++) { for (int n = 0; n < 32; n++) { int num7 = (n << 10) | (m << 5) | l; int num8 = (n << 3) | (n >> 2); int num9 = (m << 3) | (m >> 2); int num10 = (l << 3) | (l >> 2); int num11 = 0; int num12 = int.MaxValue; for (int num13 = 0; num13 < count; num13++) { int num14 = num8 - array5[num13 * 3]; int num15 = num9 - array5[num13 * 3 + 1]; int num16 = num10 - array5[num13 * 3 + 2]; int num17 = num14 * num14 + num15 * num15 + num16 * num16; if (num17 < num12) { num12 = num17; num11 = num13; } } array6[num7] = num11; } } } return EncodeIndexedPngWithPalette(rgbTopDown, w, h, array5, array6, count); } private static byte[] EncodeIndexedPngWithPalette(byte[] rgbTopDown, int w, int h, byte[] palette, int[] lut, int paletteSize) { //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Expected O, but got Unknown short[] array = new short[w + 2]; short[] array2 = new short[w + 2]; short[] array3 = new short[w + 2]; short[] array4 = new short[w + 2]; short[] array5 = new short[w + 2]; short[] array6 = new short[w + 2]; byte[] array7 = new byte[w * h]; for (int i = 0; i < h; i++) { int num = i * w * 3; int num2 = i * w; for (int j = 0; j < w; j++) { int num3 = num + j * 3; int num4 = rgbTopDown[num3] + array[j + 1]; int num5 = rgbTopDown[num3 + 1] + array2[j + 1]; int num6 = rgbTopDown[num3 + 2] + array3[j + 1]; if (num4 < 0) { num4 = 0; } else if (num4 > 255) { num4 = 255; } if (num5 < 0) { num5 = 0; } else if (num5 > 255) { num5 = 255; } if (num6 < 0) { num6 = 0; } else if (num6 > 255) { num6 = 255; } int num7 = (num4 >> 3 << 10) | (num5 >> 3 << 5) | (num6 >> 3); int num8 = lut[num7]; array7[num2 + j] = (byte)num8; int num9 = palette[num8 * 3]; int num10 = palette[num8 * 3 + 1]; int num11 = palette[num8 * 3 + 2]; int num12 = num4 - num9; int num13 = num5 - num10; int num14 = num6 - num11; array[j + 2] += (short)(num12 * 7 / 16); array2[j + 2] += (short)(num13 * 7 / 16); array3[j + 2] += (short)(num14 * 7 / 16); array4[j] += (short)(num12 * 3 / 16); array5[j] += (short)(num13 * 3 / 16); array6[j] += (short)(num14 * 3 / 16); array4[j + 1] += (short)(num12 * 5 / 16); array5[j + 1] += (short)(num13 * 5 / 16); array6[j + 1] += (short)(num14 * 5 / 16); array4[j + 2] += (short)(num12 / 16); array5[j + 2] += (short)(num13 / 16); array6[j + 2] += (short)(num14 / 16); } short[] array8 = array; array = array4; array4 = array8; short[] array9 = array2; array2 = array5; array5 = array9; short[] array10 = array3; array3 = array6; array6 = array10; Array.Clear(array4, 0, array4.Length); Array.Clear(array5, 0, array5.Length); Array.Clear(array6, 0, array6.Length); } Bitmap val = new Bitmap(w, h, (PixelFormat)198659); try { ColorPalette palette2 = ((Image)val).Palette; for (int k = 0; k < paletteSize && k < palette2.Entries.Length; k++) { palette2.Entries[k] = Color.FromArgb(255, palette[k * 3], palette[k * 3 + 1], palette[k * 3 + 2]); } ((Image)val).Palette = palette2; Rectangle rectangle = new Rectangle(0, 0, w, h); BitmapData val2 = val.LockBits(rectangle, (ImageLockMode)2, (PixelFormat)198659); try { int stride = val2.Stride; if (stride == w) { Marshal.Copy(array7, 0, val2.Scan0, array7.Length); } else { for (int l = 0; l < h; l++) { IntPtr destination = new IntPtr(val2.Scan0.ToInt64() + (long)l * (long)stride); Marshal.Copy(array7, l * w, destination, w); } } } finally { val.UnlockBits(val2); } using MemoryStream memoryStream = new MemoryStream(); ((Image)val).Save((Stream)memoryStream, ImageFormat.Png); return memoryStream.ToArray(); } finally { ((IDisposable)val)?.Dispose(); } } } public static class MapTileShare { public struct OutgoingTile { public string FileName; public byte[] Bytes; } public static List PrepareExport() { List list = new List(); IReadOnlyList tiles = MapCompileSession.Tiles; if (tiles == null || tiles.Count == 0) { return list; } long num = CurrentWorldUid(); string text = LocalPlayerName(); string text2 = Path.Combine(MapCompileEnvironment.ShareOutDir, $"{num:X16}"); try { MapCompileEnvironment.EnsureDirectory(text2); } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Could not create share dir: " + ex.Message); text2 = null; } string arg = Sanitize(text); foreach (MapCompileTile item in tiles) { if (item.PngPath == null || !File.Exists(item.PngPath)) { continue; } byte[] png; try { png = File.ReadAllBytes(item.PngPath); } catch (Exception ex2) { ModLog.Warn("[NoMapDiscordAdditions] Share read failed (" + item.PngPath + "): " + ex2.Message); continue; } TilePngMeta.TileMeta tileMeta = new TilePngMeta.TileMeta(); tileMeta.WorldUid = num; tileMeta.WorldMin = new float[2] { item.WorldMin.x, item.WorldMin.y }; tileMeta.WorldMax = new float[2] { item.WorldMax.x, item.WorldMax.y }; tileMeta.PixelWidth = item.PixelWidth; tileMeta.PixelHeight = item.PixelHeight; tileMeta.SourcePlayer = ((item.IsImported && !string.IsNullOrEmpty(item.SourcePlayer)) ? item.SourcePlayer : text); tileMeta.FullyMapped = item.FullyMapped; TilePngMeta.TileMeta meta = tileMeta; byte[] bytes = TilePngMeta.Embed(png, meta); string text3 = $"nmtile_{num:X16}_{arg}_{item.Index:D3}.png"; if (text2 != null) { try { File.WriteAllBytes(Path.Combine(text2, text3), bytes); } catch (Exception ex3) { ModLog.Warn("[NoMapDiscordAdditions] Share write failed: " + ex3.Message); } } list.Add(new OutgoingTile { FileName = text3, Bytes = bytes }); } return list; } public static string ShareOutDirForCurrentWorld() { return Path.Combine(MapCompileEnvironment.ShareOutDir, $"{CurrentWorldUid():X16}"); } public static int ScanAndImport() { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) if (MapCompileSession.CurrentState != MapCompileSession.State.Compiling) { return 0; } string incomingDir = MapCompileEnvironment.IncomingDir; if (!Directory.Exists(incomingDir)) { return 0; } string[] files; try { files = Directory.GetFiles(incomingDir, "*.png"); } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Incoming scan failed: " + ex.Message); return 0; } if (files.Length == 0) { return 0; } long num = CurrentWorldUid(); int num2 = 0; string[] array = files; Vector2 val = default(Vector2); Vector2 val2 = default(Vector2); foreach (string text in array) { if (!TilePngMeta.TryExtractFromFile(text, out var meta)) { MoveTo(text, MapCompileEnvironment.IncomingIgnoredDir); continue; } if (meta.WorldUid != num) { ModLog.Info("[NoMapDiscordAdditions] Skipping shared tile for a " + $"different world ({meta.WorldUid:X16})."); MoveTo(text, MapCompileEnvironment.IncomingIgnoredDir); continue; } byte[] pngBytes; try { pngBytes = File.ReadAllBytes(text); } catch (Exception ex2) { ModLog.Warn("[NoMapDiscordAdditions] Incoming read failed: " + ex2.Message); continue; } ((Vector2)(ref val))..ctor(meta.WorldMin[0], meta.WorldMin[1]); ((Vector2)(ref val2))..ctor(meta.WorldMax[0], meta.WorldMax[1]); string importKey = BuildImportKey(meta, val, val2); if (MapCompileSession.AddImportedTile(pngBytes, meta.PixelWidth, meta.PixelHeight, val, val2, importKey, meta.SourcePlayer, meta.FullyMapped)) { num2++; MoveTo(text, MapCompileEnvironment.IncomingProcessedDir); } } if (num2 > 0) { ModLog.Info($"[NoMapDiscordAdditions] Imported {num2} shared tile(s)."); } return num2; } private static string BuildImportKey(TilePngMeta.TileMeta meta, Vector2 min, Vector2 max) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) string text = (string.IsNullOrEmpty(meta.SourcePlayer) ? "?" : meta.SourcePlayer); return $"{meta.WorldUid:X16}|{F(min.x)},{F(min.y)}|{F(max.x)},{F(max.y)}|{text}"; static string F(float v) { return v.ToString("F1", CultureInfo.InvariantCulture); } } private static void MoveTo(string file, string destDir) { try { MapCompileEnvironment.EnsureDirectory(destDir); string text = Path.Combine(destDir, Path.GetFileName(file)); if (File.Exists(text)) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); string extension = Path.GetExtension(file); text = Path.Combine(destDir, $"{fileNameWithoutExtension}_{DateTime.Now:yyyyMMddHHmmssfff}{extension}"); } File.Move(file, text); } catch (Exception ex) { ModLog.Warn("[NoMapDiscordAdditions] Could not archive " + file + ": " + ex.Message); try { File.Delete(file); } catch { } } } private static long CurrentWorldUid() { if (!((Object)(object)ZNet.instance != (Object)null)) { return 0L; } return ZNet.instance.GetWorldUID(); } private static string LocalPlayerName() { Player localPlayer = Player.m_localPlayer; string text = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : null); if (!string.IsNullOrEmpty(text)) { return text; } return "unknown"; } private static string Sanitize(string s) { if (string.IsNullOrEmpty(s)) { return "player"; } StringBuilder stringBuilder = new StringBuilder(s.Length); foreach (char c in s) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_') { stringBuilder.Append(c); } } if (stringBuilder.Length != 0) { return stringBuilder.ToString(); } return "player"; } } public static class MapUI { public static readonly Color LabelColor = new Color(1f, 0.631f, 0.235f, 1f); private static Button _cachedRefButton; private static TMP_FontAsset _cachedFont; private static Material _cachedFontMaterial; private static bool _fontLookupAttempted; public static Button CreateButton(string name, Transform parent, float width, float height, string label, out TextMeshProUGUI labelText) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.AddComponent().sizeDelta = new Vector2(width, height); Image val2 = val.AddComponent(); Button val3 = val.AddComponent